Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Lazy Bastard

Pages: 1 2 3 [4] 5 6 7 8 9 ... 12
76
Code: [Select]
$ gdb stageview
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\MinGW\msys\1.0\home\[USER OMITTED]\stageview.exe...done.
(gdb) b load_lzs
Breakpoint 1 at 0x401537: file stageview.cpp, line 76.
(gdb) r C:\MinGW\msys\1.0\home\[USER OMITTED]\stage04.lzs
Starting program: C:\MinGW\msys\1.0\home\[USER OMITTED]\stageview.exe C:\MinGW\msys\1.0\home\[USER OMITTED]\stage04.lzs
[New Thread 2760.0xa88]

Breakpoint 1, load_lzs (name=..., data=0x22fa30) at stageview.cpp:76
76              int tsize = load( name, (void**)&buf );
(gdb) n
77              int isize = get_u32le(buf) + 4;
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
45              return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16)
| (((u8*)buf)[3]<<24);
(gdb)

So, same place.

77
Hmm...I don't exactly know how to do that with gdb. Let me know if this is the correct method, or if there's another feature that would be better suited:

Code: [Select]
(gdb) r C:\MinGW\msys\1.0\home\[USER OMITTED]\STAGE04.LZS
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: C:\MinGW\msys\1.0\home\[USER OMITTED]\stageview.exe C:\MinGW\msys\1.0\home\[USER OMITTED]\STAGE04.LZS
[New Thread 2904.0x6e4]

Program received signal SIGSEGV, Segmentation fault.
0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
45              return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16)
| (((u8*)buf)[3]<<24);
(gdb) p 'load_background'::filename
$15 = (const std::string &) @0x22ff3c: {static npos = <optimized out>,
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<
No data fields>}, <No data fields>},
    _M_p = 0x3e2b04 "C:\\MinGW\\msys\\1.0\\home\\[USER OMITTED]\\STAGE04.LZS"}}
(gdb)

78
In some of Akari's QGears testing (for example, this - http://forums.qhimm.com/index.php?topic=13252.0), I've seen modified versions of what I believe is BGINMENU.MNU (SAVEMENU.MNU for some reason contains the Buster Sword TIM, but the menu itself is BGINMENU.MNU, if I'm not mistaken). However, digging around in BGINMENU.MNU hasn't yielded any appreciable results.

Anyone have a clue as to how this was done?

79
I'm using MinGW, but I can use gdb to provide debugging data (and that'll likely be more useful anyway, since you're using Linux).

First, here's my current makefle:

Code: [Select]
all: stageview

stageview: stageview.o
gcc $< -o $@ -L/usr/lib -lopengl32 -lglu32 -lglut32 -lstdc++

stageview.o: stageview.cpp
gcc $< -c -o $@ -I/usr/include -g


And here's my current stageview.cpp:

Code: [Select]
// System
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>



// STL
#include <string>
#include <cassert>



// GLUT
#include <glut/glut.h>

// OpenGL
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glext.h>

using namespace std;

typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned long int u32;

typedef signed char s8;
typedef signed short int s16;
typedef signed long int s32;

// utility functions

u16 get_u16le(void const * const buf)
{
return ((u8*)buf)[0] | (((u8*)buf)[1]<<8);
}

u32 get_u32le(void const * const buf)
{
return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16) | (((u8*)buf)[3]<<24);
}

int load( const string & name, void ** data )
{
        size_t size = 0;
        *data = NULL;
        int fd = open( name.c_str(), O_RDONLY, 0 );
        if (fd >= 0) {
                struct stat sb;
                if ( fstat( fd, &sb ) >= 0) {
                        assert( sb.st_size > 0 );
                        void *tmp = malloc( sb.st_size );
                        if ( tmp!=NULL ) {
                                if (read( fd, tmp, sb.st_size ) == sb.st_size) {
                                        *data = tmp;
                                        size = sb.st_size;
                                } else {
                                        free(tmp);
                                }
                        }
                }
                close( fd );
        }
        return size;
}

int load_lzs(const string & name, void ** data )
{
// read compressed data
u8 *buf;
int tsize = load( name, (void**)&buf );
int isize = get_u32le(buf) + 4;

if (isize != tsize) {
free(buf);
*data = NULL;
return 0;
}

// decompress;
int osize = (isize + 255) & ~255;
u8 * obuf = (u8 *)malloc(osize);
int iofs = 4, oofs = 0;
u8 cmd=0, bit=0;
while (iofs < isize) {
if (bit == 0) {
cmd = buf[iofs++];
bit = 8;
}
if (cmd&1) {
obuf[oofs++]=buf[iofs++];
if (oofs==osize) {
osize+=256;
obuf = (u8*)realloc(obuf, osize);
}
} else {
u8 a = buf[iofs++];
u8 b = buf[iofs++];
u16 o = a | ((b&0xF0)<<4);
u8 len = (b&0xF)+3;

int rofs =  oofs - ((oofs - 18 - o) & 0xFFF);
for (int j=0; j<len; j++) {
if (rofs < 0) {
obuf[oofs++]=0;
} else {
obuf[oofs++]=obuf[rofs];
}
if (oofs==osize) {
osize+=256;
obuf = (u8*)realloc(obuf, osize);
}
rofs++;
}
}
cmd>>=1;
bit--;
}
free( buf );

*data = obuf;
return oofs;
}


// Background loading and storage

struct Vertex {
s16 x, y, z;
s16 u, v;
};

struct Element {
u16 a, b, c, s; // s = shader
};

struct Mesh {
int texture;
int element_start;
int element_count;
};

struct Shader {
int texture;
int palette;
};

struct Background {
int vertex_count;
Vertex *vertex;
int element_count;
Element *element;
int *indexbuffer;
int shader_count;
Shader *shader;
GLuint *textures;
int mesh_count;
Mesh *mesh;
};

int
add_vertex(Background *bg, s16 x, s16 y, s16 z, u8 u, u8 v)
{
for (int i=0; i<bg->vertex_count; i++) {
if (bg->vertex[i].x == x && bg->vertex[i].y == y && bg->vertex[i].z == z && bg->vertex[i].u == u && bg->vertex[i].v == v) {
return i;
}
}

int idx = bg->vertex_count++;
bg->vertex = (Vertex *)realloc(bg->vertex, bg->vertex_count * sizeof(Vertex));
bg->vertex[idx].x = x;
bg->vertex[idx].y = y;
bg->vertex[idx].z = z;
bg->vertex[idx].u = u;
bg->vertex[idx].v = v;
return idx;
}

int
add_triangle(Background *bg, u16 a, u16 b, u16 c, u16 s)
{
int idx = bg->element_count++;
bg->element = (Element*)realloc(bg->element, bg->element_count * sizeof(Element));
bg->element[idx].a = a;
bg->element[idx].b = b;
bg->element[idx].c = c;
bg->element[idx].s = s;
return idx;
}

int
add_shader(Background *bg, int texture, int palette)
{
for (int i=0; i<bg->shader_count; i++) {
if (bg->shader[i].texture == texture && bg->shader[i].palette == palette) {
return i;
}
}

int idx = bg->shader_count++;
bg->shader = (Shader *)realloc(bg->shader, bg->shader_count * sizeof(Shader));
bg->shader[idx].texture = texture;
bg->shader[idx].palette = palette;

return idx;
}

void
load_background(const string & filename, Background *bg)
{
bg->vertex_count = 0;
bg->vertex = NULL;
bg->element_count = 0;
bg->element = NULL;
bg->textures = NULL;
bg->shader_count = 0;
bg->shader = NULL;
bg->mesh_count = 0;
bg->mesh = NULL;

u8 * data;
int size = load_lzs(filename, (void**)&data);

int num_pointer = get_u32le(data);

// background texture
int texdata = get_u32le(data + num_pointer * 4);
int npal = get_u16le(data + texdata + 18);
int paldata_size = get_u32le(data+texdata+8);
int pal_ofs = texdata + 20;
int picdata_size = get_u32le(data+texdata+8+paldata_size);
int pic_ofs = texdata + 20 + npal*512 + 12;

int xsize = get_u16le(data+pic_ofs-4)*2;
int ysize = get_u16le(data+pic_ofs-2);

// convert mesh data
for (int i=1; i<num_pointer-1; i++) {
int base = get_u32le(data + 4 + i * 4);

// triangles
int triangle_offset = base + 4 + get_u32le(data + base);
int num_triangles = get_u16le(data + triangle_offset);
int mesh_tri_flags = get_u16le(data + triangle_offset + 2);

int texture_idx = ((mesh_tri_flags & 0x0E)-6) / 2;
for (int j=0; j<num_triangles; j++) {
int point[3];
int ofs = triangle_offset + 4 + j * 16;
for (int k=0; k<3; k++) {
int p = get_u16le(data + ofs + k * 2) + base + 4;
s16 x =  ((s16)get_u16le(data + p + 0*2));
s16 y = -((s16)get_u16le(data + p + 1*2));
s16 z =  ((s16)get_u16le(data + p + 2*2));

const int uv_offsets[3] = { 8, 12, 14 };
u8 u = data[ofs + uv_offsets[k] + 0];
u8 v = data[ofs + uv_offsets[k] + 1];
point[k] = add_vertex(bg, x,y,z,u,v);
}

u16 flags1 = get_u16le(data + ofs + 6);
u16 flags2 = get_u16le(data + ofs + 10);

int palette_idx = (flags2 >> 6) & 7;
int shader_idx = add_shader(bg, texture_idx, palette_idx);

add_triangle(bg, point[0], point[1], point[2], shader_idx);
}

// quads
int quad_offset = triangle_offset + 4 + num_triangles * 16;
int num_quads = get_u16le(data + quad_offset);
int mesh_quad_flags = get_u16le(data + quad_offset + 2);
for (int j=0; j<num_quads; j++) {
int point[4];
int ofs = quad_offset + 4 + j * 20;
for (int k=0; k<4; k++) {
int p = get_u16le(data + ofs + k * 2) + base + 4;
s16 x =  ((s16)get_u16le(data + p + 0 * 2));
s16 y = -((s16)get_u16le(data + p + 1 * 2));
s16 z =  ((s16)get_u16le(data + p + 2 * 2));

const int uv_offsets[4] = { 8, 12, 14, 16 };
u8 u = data[ofs + uv_offsets[k] + 0];
u8 v = data[ofs + uv_offsets[k] + 1];
point[k] = add_vertex(bg, x,y,z,u,v);
}
u16 flags1 = get_u16le(data + ofs + 18);
u16 flags2 = get_u16le(data + ofs + 10);

int palette_idx = (flags2 >> 6) & 7;
int shader_idx = add_shader(bg, texture_idx, palette_idx);

add_triangle(bg, point[0], point[1], point[2], shader_idx);
add_triangle(bg, point[3], point[2], point[1], shader_idx);
}
}

// build meshes
bg->indexbuffer = (int*)malloc(bg->element_count * 3 * sizeof(int));
int cur_mesh = 0;
for (int i=0; i<bg->element_count; i++) {
bg->indexbuffer[i * 3 + 0] = bg->element[i].a;
bg->indexbuffer[i * 3 + 1] = bg->element[i].b;
bg->indexbuffer[i * 3 + 2] = bg->element[i].c;

if (bg->mesh_count > 0 && bg->mesh[cur_mesh].texture == bg->element[i].s) {
bg->mesh[cur_mesh].element_count++;
} else {
cur_mesh = bg->mesh_count++;
bg->mesh = (Mesh*)realloc(bg->mesh, bg->mesh_count * sizeof(Mesh));
bg->mesh[cur_mesh].texture = bg->element[i].s;
bg->mesh[cur_mesh].element_start = i*3;
bg->mesh[cur_mesh].element_count = 1;
}
}

// build required textures
struct RGBA {
u8 r, g, b, a;
};

RGBA *clut = (RGBA*)malloc(sizeof(RGBA) * 256 * (npal));
for (int j = 0; j < npal; j++) {
for (int i=0; i<256; i++) {
u16 col = (data[i*2 + pal_ofs + j*512 + 1]<<8) | data[i*2 + pal_ofs + j * 512];
clut[i+j*256].r = (((col      ) & 31) * 255 + 15) / 31;
clut[i+j*256].g = (((col >>  5) & 31) * 255 + 15) / 31;
clut[i+j*256].b = (((col >> 10) & 31) * 255 + 15) / 31;
clut[i+j*256].a = ((col & 0x8000) || (col == 0)) ? 0 : 255;
}
}

bg->textures = (GLuint*)malloc(sizeof(GLuint) * bg->shader_count);
glGenTextures( bg->shader_count, bg->textures);
RGBA *texture = (RGBA*)malloc(sizeof(RGBA) * 256 * 256);
for (int i=0; i<bg->shader_count; i++) {
// build
#if 1
if ( bg->shader[i].palette >= npal ) {
printf("%i %i\n", bg->shader[i].palette, npal);
bg->shader[i].palette = 0;
}
#endif
for (int y=0; y<256; y++) {
for (int x=0; x<256; x++) {
texture[y*256+x] = clut[data[pic_ofs + y * xsize + x + bg->shader[i].texture * 256] + bg->shader[i].palette * 256];
}
}

// copy to GL
glBindTexture( GL_TEXTURE_2D, bg->textures[i]);
#if 0
// blocky
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
#else
// interpolated
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, 256, 256, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, texture);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );
#endif
}
free(texture);
free(clut);
free(data);
}

// GLUT and OpenGL stuff
Background battle;
int rot_y;
int rot_x;

void ReshapeWindowFunc(int width, int height)
{
const double kFOVy = 0.57735;
const double kZNear = 0.1;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLdouble aspect = ((GLfloat)width / (GLfloat)height) * (kZNear * kFOVy);
glFrustum(-aspect, aspect, -(kZNear * kFOVy), (kZNear * kFOVy), kZNear, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void MainRenderLoop(void)
{
// render
glClearColor(0, 0, 0, 1.00);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LEQUAL );
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 1.0f/255.0f);
glEnable( GL_TEXTURE_2D );
glEnable( GL_CULL_FACE );
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
        glDisable( GL_LIGHTING );
glDisable( GL_BLEND );

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef( (float)rot_x * 360.0f / 256.0f, 1.0f, 0.0f, 0.0f );
glRotatef( (float)rot_y * 360.0f / 256.0f, 0.0f, 1.0f, 0.0f );
glTranslatef( 0, -16, 0);
glScalef( 1.0f/256.0f, 1.0f/256.0f, 1.0f/256.0f );

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1.0f/256.0f, 1.0f/256.0f, 0);
glTranslatef( 0.5f, 0.5f, 0);

glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );

glVertexPointer( 3, GL_SHORT, sizeof(Vertex), &(battle.vertex[0].x) );
glTexCoordPointer( 2, GL_SHORT, sizeof(Vertex), &(battle.vertex[0].u) );

for (int i = 0; i < battle.mesh_count; i++) {
glBindTexture(GL_TEXTURE_2D, battle.textures[battle.mesh[i].texture]);
glDrawElements(GL_TRIANGLES, battle.mesh[i].element_count * 3, GL_UNSIGNED_INT, battle.indexbuffer + battle.mesh[i].element_start);
}

glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );

glFlush();
}

void SpecialHandler(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
rot_x -= 4;
if (rot_x < -64) {
rot_x = -64;
}
break;
case GLUT_KEY_DOWN:
rot_x += 4;
if (rot_x > 64) {
rot_x = 64;
}
break;
case GLUT_KEY_LEFT:
rot_y -= 5;
break;
case GLUT_KEY_RIGHT:
rot_y += 5;
break;
}
glutPostRedisplay();
}

void KeyboardHandler(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}

int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "stageview <stage.lzs>\n");
} else {
// get current directory
char cwd[1024];
getcwd(cwd, sizeof(cwd));

              string path;
if (argv[1][0] != 0 && argv[1][0] != '/' && argv[1][1] != 0 && argv[1][1] != ':' && argv[1][2] != 0 && argv[1][2] != '\\') {
path = string(cwd) + "/";
}

// init opengl and glut
glutInit(&argc, (char **) argv);
glutInitWindowSize(640, 480);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glutDisplayFunc(MainRenderLoop);
glutIdleFunc(MainRenderLoop);
glutReshapeFunc(ReshapeWindowFunc);
glutKeyboardFunc(KeyboardHandler);
glutSpecialFunc(SpecialHandler);

// load data
load_background(path + argv[1], &battle);

rot_y = rot_x = 0;

// main (this will never return)
glutMainLoop();
}
return 0;
}


gdb using STAGE04.LZS (since you mentioned that specific file, though the outcome is the same regardless of which file I use...even if the file doesn't exist or isn't the right format):

Code: [Select]

[USERNAME OMITTED]@[HOST OMITTED] ~
$ gdb stageview
GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\MinGW\msys\1.0\home\[USERNAME OMITTED]\stageview.exe...done.
(gdb) r C:\MinGW\msys\1.0\home\[USERNAME OMITTED]\STAGE04.LZS
Starting program: C:\MinGW\msys\1.0\home\[USERNAME OMITTED]\stageview.exe C:\MinGW\msys\1.0\home\[USERNAME OMITTED]\STAGE04.LZS
[New Thread 848.0xc08]

Program received signal SIGSEGV, Segmentation fault.
0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
45              return ((u8*)buf)[0] | (((u8*)buf)[1]<<8) | (((u8*)buf)[2]<<16)
| (((u8*)buf)[3]<<24);
(gdb) where
#0  0x00401414 in get_u32le (buf=0x0) at stageview.cpp:45
#1  0x00401557 in load_lzs (name=..., data=0x22fa30) at stageview.cpp:77
#2  0x00401ad0 in load_background (filename=..., bg=0x40c020)
    at stageview.cpp:228
#3  0x00402e49 in main (argc=2, argv=0x3e26f8) at stageview.cpp:502
(gdb)


So, it seems to dislike the array for get_u32le.

80
FF7 PSX stage files are in the STAGE1\ and STAGE2\ directories, with file names of the format STAGExx.LZS. SCENE.BIN is not related.

And nope, Zangan doesn't open STAGExx.LZS files, whether they're compressed or decompressed. One reason would be TIM texture data rather than TEX, but I suspect some of the other data is rearranged or encoded differently as well.

Even if I sit down and break a few STAGExx.LZS files down and document their contingent parts, it won't get me to a viewer, since I don't have any experience in writing graphic-viewing apps. Plus, it seems like at least a couple of other people have completely or nearly-completely mapped out the format, so I'd just be re-inventing the wheel, so to speak.

81
Those are for editing battle scenes, not battle stages. I'm aware of those, but they aren't what I'm looking for. Battle stage files contain the actual background image data.

For the PC version, there is Zangan:


82
Zangan was created for the PC version, but there's no commonly-referred-to app for the PSX version.

I've come across this thread: http://forums.qhimm.com/index.php?topic=3152.0

...which contains micky's app for viewing PSX FF7 battle stages, but after considerable effort to get it to compile (which I finally managed after slapping together a myriad of old libs and include files, and editing the source a bit), it dies with a segmentation fault when fed its expected argument (with no argument, it reminds me to provide a file name for the stage I want to load; with the file name specified, it dies). Reviewing the posts in that thread, I'm not sure anyone actually got it to work in Windows (micky had it working in Linux). In case I'm wrong, does anyone have a compiled, working copy of this app? Or, can anyone else manage to compile it into a working program?

Next I stumbled upon this thread: http://forums.qhimm.com/index.php?topic=4292.0

...which seems to imply that Cyberman had a semi-working program for viewing PSX FF7 battle stage files. So, would anyone (including Cyberman) happen to have a copy of that? Or, any further documentation than I've found in these two threads?

There's only this very brief description on the wiki: http://wiki.qhimm.com/view/FF7/Battle/Battle_Field

Any help or nudge in the right direction is appreciated. I didn't build micky's app on this machine, but I can grab my modified source and post that, along with gdb output for debugging reference, if anyone wants to look at what the hell is crashing this app (seems to be a screwy array, but I don't see what's broken about it).

Thanks in advance.

83
FF7 Tools / Re: FF7 File Reconstruction Project!!
« on: 2013-03-29 01:47:11 »
Awesome; thanks.

I'll update this thread as I add more documentation; hopefully others will chime in as well.

84
FF7 Tools / Re: FF7 File Reconstruction Project!!
« on: 2013-03-28 14:41:50 »
halkun: On that note, would you mind editing the original post to point to the new file?

85
Then you've found differences in the attack defined in the KERNEL.BIN and the one defined in LIMTMENU.MNU. Attacks in the LIMTMENU trump those in the KERNEL, by the way.

Then you should probably change this sentence, in the first post of this thread:

Quote from: Bosola
Oh, and another thing. Limits that are stored in the KERNEL.BIN probably trump Limit Break attacks in the LIMITMENU.MNU, so you will likely need Wallmarket to edit them all. I need to confirm this.


NFITC1 also seems to believe that those values in the kernel override those in LIMTMENU.MNU (or did in April of 2010):

Oh, and another thing. Limits that are stored in the KERNEL.BIN probably trump Limit Break attacks in the LIMITMENU.MNU, so you will likely need Wallmarket to edit them all. I need to confirm this.
I can mostly confirm that this is true. Data for Vincent's, Tifa's, and Cait Sith's limit attacks including Blade Beam's shockwave (the attack indexes that are less than 128) are retrieved from the KERNEL.BIN. That's how this effect was achieved. I just got in a battle with emerald and began that sequence. She can't hit hard enough to kill in one limit chain. I added the "kill regardless of status effect def" to her Final Heaven and that happened.
That's really the only one I tested. I haven't tested Vincent's and Cait Sith's, but I know Tifa's are taken from that.


Have you or others discovered something that contradicts your original assumption and that of NFITC1? I was under the impression that KERNEL.BIN still trumps LIMTMENU.MNU...

86
His oppinion is also valid. It's not as if he said "You are sh*tty and I hope you never walk again".

Heh, agreed.

I also don't like AC stuff jammed into the original, though in this case the OP just used an image and presumably not any storyline content, and as such it isn't such a bad thing. I mean, the original FMVs are higher-quality than the original gameplay, and we still get used to that (and as a matter of fact, the game starts with such an FMV, after which you're greeted by chibi polygons and flat backgrounds, and we still love the game). Running around in-game is a little about using your imagination.

As a side-note, FF7 was made by Squaresoft, not Square-Enix as in the image posted (though AC was made by Square-Enix, so perhaps such credit is still warranted with the inclusion of the image itself).

87
Misc. Tools / Re: [REL] DLPB Tools 1.2
« on: 2013-03-25 21:28:07 »
Ah; I didn't even notice Hextract :)  I'll play around with that and see what I can come up with. Thanks.

88
Misc. Tools / Re: [REL] DLPB Tools 1.2
« on: 2013-03-25 20:17:28 »
Request: Could you add a Hext format instruction that allows Hexeditor to read the value at a certain address (with a user-specified value size), then use that value as an in-file offset to write a subsequent value to?

For example, if I know that the header of a given file type is always the same size and uses the same structure, and that at 0x4 there is a 4-byte value that points to the in-file offset for a certain type of data, and I want to edit the first byte of that data in 40 different files, I could use a feature like that requested above to point Hexteditor at address 0x4, have it pull the 4-byte value from that address, use that as the destination offset to write to, and change the value at that destination to 00 (then automate with a batch script, etc).

89
PC version, I assume?

90
FF7 Tools / Re: FF7 File Reconstruction Project!!
« on: 2013-03-25 15:02:22 »
Heh, OK. Thanks, halkun (also, thanks for starting this in the first place :) ).

91
FF7 Tools / Re: FF7 File Reconstruction Project!!
« on: 2013-03-22 19:56:55 »
Necromancy!

Since I've been unable to get in contact with halkun, and I've been mapping out the contents and purposes of various files, I've decided to mirror his spreadsheet, and update it. I still have a bit more to update, and the process will continue after that once I've finished a few daunting aspects of the mod I'm working on, but for now, here's the new mirror:

https://docs.google.com/spreadsheet/ccc?key=0Ave2E8R3nZQDdFV5Y3c0Tm9mejBORjZ4UmJ3Qmdpd0E&usp=sharing

As was the case with the original, let me know if you've got something to contribute, and if you're fairly active in reverse-engineering FF7's files and data, I'll allow you to edit the spreadsheet directly.

Enjoy!

92
General Discussion / Re: [CHEAT PLAY] Cheat codes/mods?
« on: 2013-03-22 19:28:59 »
Or GameShark codes.

93
Gameplay / Re: The first auction in Final Fantasy VII
« on: 2013-03-18 19:08:21 »
That's very cool.

Any chance you'll be releasing the script for it soon?

94
Yeah, there's the USO menu (character select/swap, even if they're not in your PHS inventory yet), and one more thing...which I can't recall at the moment. KingEdgar0, of GameHacking.org, hacked access to them via GameShark code about 1.5 decades ago.

95
I don't think that would be retained after saving and restarting, when the code was not enabled.

96
I certainly think so. It saves a lot of time normally spent in a hex editor for this purpose.

The ability to convert between BMP and TIM would be nice, since other apps purporting to do so seem to have serious flaws (still, I use a PhotoShop plugin to handle TIM editing, so I don't worry about conversion).

97
Necromancy!

Since this is still the first Google result for MNU-TIMjector, and since it's disappeared from the face of the internet, here's its new mirror: LINK

I've also added a little something to make it work on 64-bit versions of Windows (which was a real pain until I worked out what was going on). Here's the ReadMe:

Quote
[Lazy Bastard, of GameHacking.org]: I didn't write this app. hotdog963al was its author. By the time I wanted it, it had disappeared from the face of the internet. Luckily kranmer still had a copy of it lying around, and provided it to me. Everything was fine, until I tried to run it on my 64-bit machine, and it didn't work. After some digging, I discovered that the DLL it uses, MagickNet.dll, isn't 64-bit compatible, and it seems hotdog963al didn't write the app to force 32-bit mode, thus the OS was trying 64-bit mode and crashing the app. Luckily, Microsoft has something called CorFlags.exe, which allows you to force an executable to run in 32 or 64-bit mode if desired. However, Microsoft loves to bundle such useful apps in several-hundred-megabyte packages, which take quite a while to install once downloaded, and which must be dug through viciously before finding the actual app desired...so I've decided to simply include CorFlags.exe with this download. It's a free app, so I hope Microsoft won't cry about it.

I've also whipped up a short batch script to perform the 32-bit mode force for you, entitled "64-bit_Compat.bat", along with an un-force script entitled "64-bit_Compat_Un.bat", in case for some reason you'd like to reverse the process (though there's no reason I can think of at the moment). Finally, if you're nervous running a batch script that some guy on the internet wrote, just go into your command line, change directory to your MNU-TIMjector folder, and type "CorFlags.exe MNU-TIMjector.exe /32Bit+" (without the quotes), and press Enter. To reverse the process, type "CorFlags.exe MNU-TIMjector.exe /32Bit-" (without the quotes), and press Enter.

Without further ado, here's the original description of this great app, by its author, hotdog963al:

(here I regurgitate the first post of this thread)

Enjoy!

98
I may add a few new fields, but for the most part, I'll be using existing ones.

I already have some interesting work done; just one thing at a time :)

99
Noted. Although, it would be nice if someone from the Black Chocobo team would update the qhimm.com wiki to reflect anything new from the Black Chocobo one (since Black Chocobo is chiefly concerned with saves, and qhimm.com is concerned with all facets of game mechanics and modification). Alternatively, I could update it, though it might help to point out what needs updating since I haven't delved deeply into the savemap/etc.

100
Thanks; I found the problem. I was using MD1STIN as a launching point to the initial field for my mod (I have MD1STIN instantly loading the next field so it's not even perceived by the player), but apparently the game initially turns all menu options on (presumably, via KERNEL.BIN) and relies on MD1STIN to set them correctly, which I'd unknowingly circumvented.

In case anyone ever runs into the same thing, the variable in question is:

Var[2][28] (16-bit)

If your aim is to make everything visible except PHS, you'll want to set that variable to 767 (which is 0x02FF, in case you're using a debugger or watching RAM at 8009D2A4).

This sets visibility only. As sithlord48 mentioned above, there's also the Enabled/Disabled variable, but the game initially sets its value to 0300, which means only PHS and Save are disabled (until you hit a save point in the case of saves, or hit a save point while also in possession of the key item PHS in the case of PHS).

Edit: The variable number above makes more sense after looking more patiently at http://wiki.qhimm.com/view/FF7/Savemap. Savemap Bank 2, byte 28 is indeed this value. Byte 30 is the "menu locking mask", so presumably this is the variable to modify if you want to enable/disable a menu item.

Pages: 1 2 3 [4] 5 6 7 8 9 ... 12