Engine fantasy.

  • Thread starter Thread starter halkun
  • Start date Start date
Status
Not open for further replies.
Halkun:
I'll see if I can get something to work with an ISO image, I suppose ye olde CLI will be a start. I think an @<filename> setup method for testing is appropriate. We do need debugger output on STDERR as well. (IE what line was executed and what were the results).

Cyb
 
Well I've been fighting/installing Eclipse on my Linux box.
:D
I'm also writting up a Plan Of Attack for it.
Has anyone here installed the CDT for eclipse? For some reason it's complaining about permissions.  I installed it as root but I'm adding the CDT as a user. I think this is causing a few problems.  Should I run and install the CDT for Eclipse SU root? (CDT is the C/C++ Eclipse plugin).

Erstwhile the plan is this.
  1. Read Config File
    Mount Media - by this I mean locate the media image and set up to read the ISO.
    proceed with Halkun's operations

I'm using Eclipse specifically since it's cross platform.
I have it for Windoze and Linux.

Makes things more consistant for me. Halkun it's OK you don't HAVE to have Eclipse to build the binaries of the code ;) (LOL) It creates a makefile that's all you should need.

I suppose this is the SFFVM (S_quare F_inal F_antasy Virtual Machine)

Cyb
 
This was going to be a summer project... Like when I was done with school (Almost there)

I haven't had time copy so much as Kernel.bin from my CD yet, much less write a quick a dirty zlib decompressor.
 
Too Late?
I've already got some of the ISO9660 structure done.  It's just a bit of time before I finish the code to read the image and file system of the Image.  I'm working to keep the whole thing working with streams this way the underlying IO is ignored and all the high level operations are all the same.
This way you can assign an ISO image file to a ISO_stream type and be able to open and read files from the image just like you would fstream.  Also since the underlying IO would be an ISO image absolute reads are quite easy to handle.  I might have the underlying ISO_stream etc. done by the end of the week. It takes time to carefully think these things through.  I've already implemented this once, so this is my second iteration, and thus I'm using what I learned already.  ISO9660 file system is NOTHING like windows.  If you ever wondered why the SYSTEM file in FF7 has SCUS_941.63;1 in it well that's because the file Identifyer is SCUS_941.63;1 (not SCUS_941.63 as windows shows it). This is a translation of the file name by windows (and can be a source for problems).  The ;# is the version information in ISO, I'm not sure why they elected to do that, It may have had to do with being able to add new versions of files to the CD Data.

Because the CD file system is ISO9660 things are a bit more complicated in some ways to read the CD completely on the PS1.

My 'layers' so far are thus. ISO object handles the ISO Image and File system where as ISO_stream should work just like a fstream (as it inherits istream's functionality with a different low level IO).

This fixes at the very least the ISO Issue versus mounted media.  On the playstation media most of the files are readable without this. The movie files are the exception of this.  So I figure one can make it fully compatible this way and less of a hassle.

I can worry about opening the kernal.bin and fetching files after this is worked out :D

How were you planing on using zlib? I'll have to look at it's interface to see how to use it. (Nary used that lib had to ADD it to compile packages before though).

Cyb
 
Wait a minute. If I have time I can post my kernel/window loader and font renderer. It shows how you can interface with zlib. I'm not sure if I can convert it to plain C tonight, though...
 
I'm not sure if I can convert it to plain C tonight, though...

I still don't get.... we are using C or C++ after all? ^^''

If I have time I can post my kernel/window loader and font renderer.

Post it =)
It really will be helpful.
 
Code: [Select]
Code:
// GLUT#include <GLUT/glut.h>// OpenGL#include <OpenGL/gl.h>#include <OpenGL/glu.h>// System#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>// STL#include <string>// ZLib#include <zlib.h>using namespace std;typedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;const char * ff7Path = "<path to your ff7 directory>";// This is a table that contains 16-bit unicode codes for all chars in the FF7 font. (US/NTSC Version)const u16 charMatrix[] = { 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e,  0x005f, 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, 0x00c4, 0x00c1, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1, 0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8, 0x00ea, 0x00eb, 0x00ed, 0x0069, 0x00ec, 0x00ef, 0x00f1, 0x00f3, 0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc, 0x0000, 0x00b0, 0x00a2, 0x00a3, 0x0000, 0x0000, 0x0000, 0x00df, 0x0000, 0x0000, 0x0000, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8, 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x03a3, 0x03a0, 0x03c0, 0x2321, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8, 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x0394, 0x00ab, 0x00bb, 0x2026, 0x0000, 0x0041, 0x0041, 0x004f, 0x0152, 0x0153, 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x2662, 0x00ff, 0x0178, 0x2044, 0x0000, 0x2039, 0x203a, 0x1278, 0x1279, 0x275a, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c5, 0x00ca, 0x0041, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, 0x004f, 0x004f, 0x0000, 0x004f, 0x0055, 0x0055, 0x0055, 0x007c, 0x02c6, 0x02dc, 0x02c9, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7};u8 * ucodeToChar;void * kernelBinData;void * windowBinData;GLuint fontTextures[8];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;}intload_bingzip(const string & fileName, void ** buf){ // load library u8 * buffer = NULL; int size = load(fileName, (void**)&buffer); // calc overall decompressed size and number of blocks int offset = 0; int output_size = 0; int output_count = 0; while (offset < size) {  int comp_size = get_u16le(buffer + offset + 0);  int uncomp_size = get_u16le(buffer + offset + 2);  offset += 6;  offset += comp_size;    output_size += uncomp_size;  output_count ++; }   // allocate enough memory for output buffer int bufsize = output_size + output_count * sizeof(u32); u32 * table = (u32*)malloc(bufsize);  // decompress all blocks with zlib z_stream s; memset(&s, 0, sizeof(z_stream)); s.next_out = (Bytef *)(table + output_count); s.avail_out = output_size; s.total_out = 0; offset = 0; int count = 0; int out_offset = output_count * sizeof(u32); while (offset < size) {  table[count++] = out_offset;  int comp_size = get_u16le(buffer + offset + 0);  int uncomp_size = get_u16le(buffer + offset + 2);  int unknown = get_u16le(buffer + offset + 4);  offset += 6;  s.next_in = buffer + offset;  s.avail_in = comp_size;  s.total_in = 0;  offset += comp_size;  out_offset += uncomp_size;    // compressed/uncompressed?  inflateInit2(&s, 16 | 15);  inflate(&s, Z_FINISH);  inflateEnd(&s); }  free(buffer);  *buf = table; return bufsize;}void build_font_textures(){ u32 * table = static_cast<u32*>(windowBinData); u8 * data = static_cast<u8*>(windowBinData);   glGenTextures(8, fontTextures);  u8 * fontData = data + table[1]; u32 id = get_u32le(fontData + 0); u32 type = get_u32le(fontData + 4); u32 clut_size = get_u16le(fontData + 16); u32 clut_count = get_u16le(fontData + 18); u32 pic_ofs = clut_size * clut_count * 2 + 20;  u32 width = get_u16le(fontData + pic_ofs + 8) * 4; u32 height = get_u16le(fontData + pic_ofs + 10);  u8 * bitmap = new u8[256 * 256 * 4]; for (unsigned int i=0; i<clut_count; i++) {  u8 clut[256 * 4];  for (unsigned int j = 0; j<clut_size; j++) {   u16 col = get_u16le(fontData + 20 + (i * clut_size + j) * 2);   clut[j * 4 + 0] = (col & 31) * 255 / 31;   clut[j * 4 + 1] = ((col >> 5) & 31) * 255 / 31;   clut[j * 4 + 2] = ((col >> 10) & 31) * 255 / 31;   clut[j * 4 + 3] = (col >> 15) * 255;  }    for (unsigned int y=0; y<height; y++) {   for (unsigned int x=0; x<width; x++) {    u8 pixel = fontData[pic_ofs + 12 + y * (width / 2) + x / 2];    int index = x & 1 ? pixel >> 4 : pixel & 15;        bitmap[(y * 256 + x) * 4 + 0] = clut[index * 4 + 0];    bitmap[(y * 256 + x) * 4 + 1] = clut[index * 4 + 1];    bitmap[(y * 256 + x) * 4 + 2] = clut[index * 4 + 2];    bitmap[(y * 256 + x) * 4 + 3] = clut[index * 4 + 3];   }  }  glBindTexture(GL_TEXTURE_2D, fontTextures[i]);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, bitmap); }  delete[] bitmap;}unsigned int getKernelStringCount(unsigned int i){ u32 * table = static_cast<u32*>(kernelBinData); u8 * data = static_cast<u8*>(kernelBinData); u8 * base = data + table[i + 9]; return get_u16le(base) / 2;}voidgetKernelString(unsigned int i, unsigned int j, wstring & s){ u32 * table = static_cast<u32*>(kernelBinData); u8 * data = static_cast<u8*>(kernelBinData); u8 * base = data + table[i + 9]; u8 * ptr = base + get_u16le(base + j * 2); if (*ptr != 0xFF) {  while (*ptr != 0xFF) {   if (*ptr == 0xf9) {    // simple string compression, reference an earlier substring    ptr++;    int dist = ((*ptr) & 0x3F)+2;    int count = ((*ptr) >> 6)*2+4;    for (int k=0; (k<count) && (*(ptr-dist+k)!=0xFF); k++) {     s += charMatrix[*(ptr-dist+k)];    }    ptr++;   } else if (*ptr == 0xf8) {    // unknown escape code..     ptr++;    ptr++;   } else {    s += charMatrix[*ptr];    ptr++;   }  } }}// build inverse lookup table from unicode to FF7 font indexvoidbuild_ucode_to_char_table(){ ucodeToChar = new u8[65536]; memset(ucodeToChar, 0, 65536); for (unsigned int i=0; i<sizeof(charMatrix)/sizeof(charMatrix[0]); i++) {  ucodeToChar[charMatrix[i]] = i; }}void drawString(int colour, int x, int y, const wstring & text){ u32 * table = static_cast<u32*>(windowBinData); u8 * data = static_cast<u8*>(windowBinData); u8 * widthTable = data + table[2]; glBindTexture(GL_TEXTURE_2D, fontTextures[colour]); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);   glBegin(GL_QUADS); for (wstring::const_iterator i = text.begin(); i != text.end(); i++) {  u8 glyph = ucodeToChar[*i];    int gx = (glyph % 21) * 12;  int gy = (glyph / 21) * 12;    glTexCoord2i(gx, gy);  glVertex2i(x, y);  glTexCoord2i(gx, gy + 12);  glVertex2i(x, y + 12);  glTexCoord2i(gx + 12, gy + 12);  glVertex2i(x + 12, y + 12);  glTexCoord2i(gx + 12, gy);  glVertex2i(x + 12, y);       x += widthTable[glyph] & 0x0F; } glEnd();}void ReshapeWindowFunc(int width, int height){ glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, width, height, 0.0, 0.0, 1.0);}void MainRenderLoop(void){ glClearColor(0.0f, 0.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  drawString(0, 8, 8, L"Kernel Strings:"); for (unsigned int i=0; i<getKernelStringCount(10); i++) {  wstring text;  getKernelString(10, i, text);   drawString(i&7, 16, i*12+20, text.c_str()); } glFlush();}void SpecialHandler(int key, int x, int y){}void KeyboardHandler(unsigned char key, int x, int y){ switch (key) {  case 27:   exit(0);   break; }}intmain(int argc, char * argv[]){ // glut stuff 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);  // opengl stuff glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); glViewport(0, 0, 640, 480); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(1.0f/256.0f, 1.0f/256.0f, 1.0f);  glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 640, 480, 0.0, 0.0, 1.0);  load_bingzip(string(ff7Path) + "/INIT/KERNEL.BIN", &kernelBinData); load_bingzip(string(ff7Path) + "/INIT/WINDOW.BIN", &windowBinData); build_font_textures(); build_ucode_to_char_table();  glutMainLoop();  delete[] ucodeToChar; return 0;}
Features:
- loads kernel.bin and window.bin
- converts font into textures
- converts ff7 strings into unicode
- draws unicode strings with ff7 font
- expands kernel strings
TODO:
- control codes for field text
- layout of text into a window
- decide on C++ or C and convert
- split into files
- you'll have to change the path to your ff7 directory (I'm using the PSX version)
 
Ok, here's something...

I've been reading a new book called "The Pragmatic Programmer" which tell you how to design OO programs.

Here's the thing.

It's the first book that doesn't tell me *how* to write OO programs, but *why* to write them. It explains *why* you should write accessors to classes and *why* you should have public vs pivate variables. It gives examples and compares them to other ways that are simply less elegent.

After looking at this, I think a C++ framework will be much better. I'm no good at setting up frameworks, simply because I don't know how to do it yet. But now I can at least get the concept of classes right. (Though I think they way they are expressed in C++ is still dumb)

I should be able to follow along...
 
After looking at this, I think a C++ framework will be much better. I'm no good at setting up frameworks, simply because I don't know how to do it yet.

Could you please register account on Sourceforge.net. We'll need CVS to work together.

And we need some auto documentation system (Doxygen is good http://www.doxygen.org/). It will be easier to use and expand framework if we have complete documentation on it.
 
Hmmm so you now understand it's not just some wacked out religious thing? ;)

Erstwhile I've nearly finished my ISO class for handling the images. Next will be the ISO_stream.

Cyb
 
Ok, here's something...

I've been reading a new book called "The Pragmatic Programmer" which tell you how to design OO programs.

Here's the thing.

It's the first book that doesn't tell me *how* to write OO programs, but *why* to write them. It explains *why* you should write accessors to classes and *why* you should have public vs pivate variables. It gives examples and compares them to other ways that are simply less elegent.

After looking at this, I think a C++ framework will be much better. I'm no good at setting up frameworks, simply because I don't know how to do it yet. But now I can at least get the concept of classes right. (Though I think they way they are expressed in C++ is still dumb)

I should be able to follow along...
I was a very strong supporter of C, but then things like STL (and especially std::string) won me over to C++.
But you'll actually have to start coding and improving yourself over time. And you'll have to spend time reading books (Design Patterns, Large Scale C++ Development, Effective C++...) and apply them to your own projects. It is nothing you can learn and then apply immediately, and I have seen absolutely terrible designs from C++ newbies... Use what you're most comfortable with.
 
Erstwhile I've nearly finished my ISO class for handling the images. Next will be the ISO_stream.

I'm working on Savemap. It's awfully big, so it will take a while =)
We need only one savemap in the game I believe?
 
That one savemap is the global variable holder, that's why I was so leary of C++. Globals are a no-no, but it's needed as it's the basis for most critical varible management in FF7.

=======

I have a sourceforge account. Give me a bit to fill it out.
 
I updated the loading/font rendering code on the previous page. That fixes the winding order of the quads for the glyphs, creates textures with an alpha channel and has some minor tweaks to the code.
Let me know if anyone gets it to work or has any problems. You'll most likely want to change the OpenGL and GLUT includes (to GL/gl.h, GL/glu.h and glut/glut.h), and change the path to your FF7 directory. Oh, and I'm using the PSX version.
I imagine you just want to use it as a guideline, but feel free to rip out whatever you need.
 
All right I've hit the first 'win32' versus POSIX issue.
FindFirst FindNext FindClose are used by Windows.
whereas POSIX uses opendir closedir readdir telldir seekdir.  There is no glob function that I can recall (IE you do your own file matching in this case) in POSIX.

Suggestions anyone? I could use scandir but that's a BSDism. However this is the same as 'doing your own file matching".

Why am I asking this? Well we want to access things the same weather it's an ISO image or CD. :D

Has anyone found any real file references in the script?
There are some file references in the executable.  These appear to be \MINT\DISKINFO.CNF;1 and \MINT\MOVIE_ID.BIN;1
These I suspect are just to be certain what disk is in the drive and get an absolute index for a movie. (MOVIE_ID.BIN has 5 UINT32 numbers per movie that appear to have sector and length information in them).  Although it's possible that DISKINFO.CNF may have the FF7 engine boot information (IE kernal loading etc.) The only thing I can find is "DISK0001<cr><lf>" and "FinalFantasy7 Disk1<cr><lf>"  The rest of the data is an enigma too me ;)
I can't seem to find Min:Sec:Frame indexs however either :/

Cyb
 
Has anyone found any real file references in the script?

Looking at the fieldscript, I'm afraid we are going to have to make a lookup table for them. The JUMPMAP command only refrenced field files by numbers.

MOVIE also only refrenced files by number, so it's kind of critical you have the correct disk in the drive when the fieldscript executes the movie or else the wrong movie plays.

Doing in-memory fieldscript hacking while the game is running will allow us to enumerate the files. (change the JUMPMAP number and look in the menu to see where you landed after the new file loads, the trick is linking that to what fieldscript we are in, but that can probably be done by looking at fieldscript dumps)

As for movie variables, there is a movie player in the debug rooms

Also, I'm leary of ISO reading unless we absolutly have to. For linux it's becuase some drives simply can't read the disk at all. Is there a reason why Windows needs the fuctionality? Can't they read the files fine? (With the exclution of reading the movie and sound files?)
 
Has anyone found any real file references in the script?

Looking at the fieldscript, I'm afraid we are going to have to make a lookup table for them. The JUMPMAP command only refrenced field files by numbers.

MOVIE also only refrenced files by number, so it's kind of critical you have the correct disk in the drive when the fieldscript executes the movie or else the wrong movie plays.

Doing in-memory fieldscript hacking while the game is running will allow us to enumerate the files. (change the JUMPMAP number and look in the menu to see where you landed after the new file loads, the trick is linking that to what fieldscript we are in, but that can probably be done by looking at fieldscript dumps)
Oh.. hmmm I wonder where the silly table is.. I think the DISKINFO.CNF;1 file might be the 'big' index (Index of indexs!). I suppose I need to make an ISO disk image map viewer (more stuff to do).
As for movie variables, there is a movie player in the debug rooms

Also, I'm leary of ISO reading unless we absolutly have to. For linux it's becuase some drives simply can't read the disk at all. Is there a reason why Windows needs the fuctionality? Can't they read the files fine? (With the exclution of reading the movie and sound files?)
With some low level IO manipulation yes it can be.  This is the problem.  Essentially in order to read the entire sector you have to by pass the normal windows VXD drivers.  This also happens to be drive specific.  In simple terms it's the most common problem with playing movies on playstation games.
 
For the record, Memory Hacking Software (http://www.memoryhacking.com/) comes with a FileWatcher plug-in that allows you to monitor all file activity in the target process.

You can set it to stop Final Fantasy VII when it loads any file or part of a file and step through with the debugger to see how the code is using the file, or, for your current purposes, how it came to load the file (the mythical “table”).

It also shows you every file that is opened, how they are opened (flags), when they are read, when bytes are written to them, and when they are closed.


Speaking of which, all of you can use this to watch how it opens files and decodes them.
We can decode all unfinished file formats this way…


It also comes with source so you can modify it how you please.


L. Spiro
 
Status
Not open for further replies.
Back
Top