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.


Topics - Cyberman

Pages: 1 [2]
26
Hmmm I don't remember having this problem before but some of the models vertexs are huge and producing rather anoying results.

Example 1 <ENEMY000> looks fine, it has only one object in the data.

Example 2 <ENEMY059> looks oddly mutant.. really :D

Example 3 <TIFA> is OK but not OK :D


The only thing I can think of I am misaligning the data I'm reading however, why does it work so nicely for a single boned object?  The vertex values get inexplicably huge for some reason.

Cyb

27
Scripting and Reverse Engineering / FF7 and lighting
« on: 2005-09-17 15:46:41 »
Well people have speculated weather FF7 has any lights or not.
It does as a matter of fact in the field scenes, and they are used. They are different colors the most pronounced use of them is the sector 5 slums in the room below where turtles paradise pamphlet 1 is found.

It's not dynamic lighting obviously :D

Cyb

28
I've been looking at these of late (like within the last 2 weeks to be precise)
I modified my program to dump these little images of the structure.

We currently know a few things about these.
1 The first 7 Double Words are pointers to the playstations memory
2 The first section of the 7 sections of this file is the script section.

I'm not sure how to deliniate the sections properly myself.  So as a GUESS I took the pointers and assumed they were a certain amount apart. IE the data is decoded and dumped into memory directly.  I suspect this is not entirely true.

<removed cute cudely images of DATA!>

The sections aren't properly aligned with the pointer information AND all the pointer informat is DWORD aligned. The data is not aligned acording to that it appears. So the only thing I can think of is it's decompressed and a header is parsed to determine the locations the locations the real data gets stuffed into memory.  Since we know what the file is and where it's supposed to be in memory a little debugging I suspect will find the data using a PS1 emulator that should be aligned at these locations.  That's my new plan at least :D

I suspect that section 1 may have some other information in it to find the beginings and ends of these sections. IE Section 1 does not start immediately :lol: so back to the drawing board.

For reference I am using \FIELD\4SBWY_1.DAT file to work on this.

Any thoughts on this anyone?

Cyb

29
I've been twiddling with some code to get these to work, however my main problem appears to be
[list=1]Misalignment of textured sections while processing the UV information
Incorrect palettes being selected[/list:o]
Here is an example of the TIM from STAGE001.LZS decoded it's kind of nasty looking in my humble opinion.  So what should it look like first of all?
Micky's palette selection:

Cyb's palette selection:

They both look wrong to be honest. However Zangan doesn't have lighting and too much camera control so Hmmm.  Anyhow I'm pretty sure I have the pallete selection wrong for both cases.

Code: [Select]
  BM = Image1->Picture->Bitmap;
   Image1->Width = 256;
   Image1->Height= 256;
   BM->Width = 768;
   BM->Height= 256;
   TIM(BM, Dat + Offsets[*Sections - 1]);
   Image1->Width = BM->Width;
   Image1->Height= BM->Height;
   XOff = 0;
   for(Index = 0; Index < 3; Index++)
   {
      if(Textures[Index].ImageData != NULL)
      {
         delete Textures[Index].ImageData;
      }
      // create 256x256 textures
      Textures[Index].ImageData = (GLubyte *)new RGBA[256*256];
   }
   // we use 3 seperate textures
   for (Index = 1; Index < (*Sections -1); Index++)
   {
      VertC =        (int *)(Dat + Offsets[Index]);
      Verts =        (PSX_FF7_VERTEX *)(VertC + 1);
      TriP =         (PSX_FF7_PCNT *)&Verts[*VertC/8];
      TTriangles =   (PSX_FF7_TTRI *)(TriP + 1);
      QuadP =        (PSX_FF7_PCNT *)&TTriangles[TriP->Count];
      TQuads =       (PSX_FF7_TQUAD *)(QuadP + 1);
      XOff = ((TriP->TPage & 0x0E) - 6)<<7;
      for (PIndex = 0; PIndex < TriP->Count; PIndex++)
      {
         TTri = TTriangles[Index];
         TX = TTri.U0;
         TY = TTri.V0;
         TW = TX;//TTri.U0;
         TH = TW;//TTri.V0;
         //if (TTri.U0 < TX) TX = TTri.U0;
         if (TTri.U1 < TX) TX = TTri.U1;
         if (TTri.U2 < TX) TX = TTri.U2;
         //if (TTri.U0 > TW) TW = TTri.U0;
         if (TTri.U1 > TW) TW = TTri.U1;
         if (TTri.U2 > TW) TW = TTri.U2;
         //if (TTri.V0 < TY) TY = TTri.V0;
         if (TTri.V1 < TY) TY = TTri.V1;
         if (TTri.V2 < TY) TY = TTri.V2;
         //if (TTri.V0 > TH) TH = TTri.V0;
         if (TTri.V1 > TH) TH = TTri.V1;
         if (TTri.V2 > TH) TH = TTri.V2;
         // Micky's method
         //PalIdx = (TTri.PAL >> 6) & 7;
         // Cyb's Method
         PalIdx = (TTri.PAL >> 7) & 7;
         if (PalIdx != CPal)
            CPal = PalIdx;
         //TW+=XOff;
         //TX+=XOff;
         TIM(
            BM,
            Dat + Offsets[*Sections - 1],
            &Textures[XOff>>8],
            //(GLubyte *)NULL,//Textures[0].ImageData,
            TX + XOff, TY,
            TW + XOff, TH
            //TY + XOff, TX,
            //TH + XOff, TW
            );
         //Model->Add
      }
      XOff = ((QuadP->TPage & 0x0E)-6) << 7;
      for (PIndex = 0; PIndex < QuadP->Count; PIndex++)
      {
         TQuad = TQuads[Index];
         TX = TQuad.U0;
         TY = TQuad.V0;
         TW = TX;//TQuad.U0;
         TH = TY;//TQuad.V0;
         //if (TQuad.U0 < TX) TX = TQuad.U0;
         if (TQuad.U1 < TX) TX = TQuad.U1;
         if (TQuad.U2 < TX) TX = TQuad.U2;
         if (TQuad.U3 < TX) TX = TQuad.U3;
         //if (TQuad.U0 > TW) TW = TQuad.U0;
         if (TQuad.U1 > TW) TW = TQuad.U1;
         if (TQuad.U2 > TW) TW = TQuad.U2;
         if (TQuad.U3 > TW) TW = TQuad.U3;
         //if (TQuad.V0 < TY) TY = TQuad.V0;
         if (TQuad.V1 < TY) TY = TQuad.V1;
         if (TQuad.V2 < TY) TY = TQuad.V2;
         if (TQuad.V3 < TY) TY = TQuad.V3;
         //if (TQuad.V0 > TH) TH = TQuad.V0;
         if (TQuad.V1 > TH) TH = TQuad.V1;
         if (TQuad.V2 > TH) TH = TQuad.V2;
         if (TQuad.V3 > TH) TH = TQuad.V3;
         // Micky's method
         //PalIdx = (TQuad.PAL >> 6) & 7;
         // Cyb's Method
         PalIdx = (TQuad.PAL >> 7) & 7;
         if (PalIdx != CPal)
            CPal = PalIdx;
         //TW+=XOff;
         //TX+=XOff;
         TIM(
            BM,
            Dat + Offsets[*Sections - 1],
            &Textures[XOff>>8],
            //(GLubyte *)NULL,//Textures[0].ImageData,
            TX + XOff, TY,
            TW + XOff, TH
            //TY + XOff, TX,
            //TH + XOff, TW
            );
      }
   }

30
Alright.. this has been a frustration for a few of us. So this is my thread to put the Coup De Grat to this nusance I mean .. problem :D

First What I know:
[list=1]
  • The playstation version Model is Section 0
  • The playstation version Bone data and visual data is in Section 0
  • The tim section location is NOT PREDICTABLE in the playstation version. That is there is no reference to where it should be. It must be found by inspecting the 'Magic#'  information for each section.
  • Using Cloud as the 'reference' model for everything. There are EXACTLY 95 sections between Section 0 and the TIM
  • There are 94 Animations in Cloud in the PC Version
  • [/list:o]
    What does this mean?
    Section one does not resemble anything of interest and isn't the same block size as anything on the PC.
    SECTION 2 hower.. is almost IDENTICAL to the first animation block on the PC
    Clues?
    Ignore the 16 byte header of the PC version (more on this later :D ).
    SECTION 2's next 7 bytes (starting at offset 0 of section 2)
    Are exactly the same as the PC's data

PC
Code: [Select]
00000000   5E 00 00 00  18 00 00 00  14 00 00 00  5C 03 00 00
00000010   14 00 56 03  00 00 00 DD  2E 00 00 00  00 00 00 0C
00000020   00 38 61 00  F8 2F 73 46  A0 2B 0C 82  2B 38 2F 02
00000030   AE 61 86 40  12 2D 35 41  53 65 6E 53  00 00 00 02

PS1 SECTION 2
Code: [Select]
00000000   14 00 56 03  00 00 00 FE  2E 00 00 00  00 00 00 0C
00000010   00 EC E0 00  F8 2F E5 E8  A0 BB 0C 82  BC EC 2F 02
00000020   AE 61 86 40  12 C1 35 41  E4 EE 6E 53  00 00 00 02

This reveals the data to be almost identical save for one little discrepency at offset
( relative to MATCHING data in the PS1) 7 it's 0xDD in the PC and 0xFE in the Playstation otherwise everything else is identical.

SECTION ONE IN THE PLAYSTATION I suspect is critical to revealing something in the PC as well :)

Also of note there are 4 byte sections in the animation data of cloud
They all read
Code: [Select]
30 1A 00 00
I believe the best way to decode these sections is to call them
Code: [Select]
typedef struct {
 unsigned short ZZ;
 unsigned short length;
} anim_header;

Cyb <Jubulent>

31
Could someone dump the data that's in one of the character models in there PC version of FF7 for the first animation frame? I think this will be useful for me to find the animation data in the playstation version.  Hopefully at least. Yuffie Cloud I care not which you pick!

I just need the raw numbers or if you just hand me the file I suppose I can decode it myself.
I plan on finding the numbers in the character data. It's likely the rotation information is not identical (in fact it WON'T be).  This is because the PC and PS1 have different 'scales' used. (PS1 is all integer).  The PS1 uses 16bit signed ints for the rotation matrices.  FF7 on the playstation may compute the sine and cosine information then create the matrix in the GTE's registers (relatively speaking this is easy as they only need to compute a matrix for each rotation angle then multiplying each matrix  by each other the end result is a single matrix needed for all rotations).  
I think PS1 FF7 uses 1:15 format for its numbers (IE a signed int whole number), I'm sure the rotation information is likely identical between the two systems in terms of the actual numbers but probably not the storage (would take to long on the playstation to unpack all that data is what I base this idea on).  So I just need the #'s :)

Cyb

32
Scripting and Reverse Engineering / FF7 PSX Battle Scenes
« on: 2003-04-05 17:35:37 »
For those who are curious:

PSX battle scene data is located in "\BATTLE\SCENE.BIN"

Appears to be 33 8K blocks of data (compressed?) This coresponds the the 33
battle scenes in FF7 for the PC.
each block begins with 16 32 bit integers.

typedef struct
{   Reference[16];
}
BTL_BLK_HDR;
The first integer is always
0x00000010
This is because 0x0040 is the begining of data.
Each reference is multiplied by 4 to reach it's offset within the block.
Unused references are set to -1 or 0xFFFFFFFF. Unused parts of each section data are filled with 0xFF as well.
The data follows the 16 references of the header.
Each data chunk appears to begin with
1F 8D 08 00-00 00 00 00-02 03 ED
The data in each section is unknown.. but does change some.

That's all I've been able to decipher.  If anyone recognizes the begining sequence of the data for each section of the block let me know!


Cyb

33
Ok now that I don't have your attention (grin).

I've been examining the PSX battle model files (not battle scenes) and here is what I have of the file structure.

Each file is LZS compressed (I know exciting) then the file consists of the following information.
long int ObjectCount;
long int Index[ObjectCount];
<start of data>

Anyhow this is what I've been able to gather, I can only assume that the information in the file has tags or is structured in someway to decipher it, have any Ideas?

Cyb

34
I'm still having problems decompressing the LZS compressed files using the algorhythm Fice has give.  I also do have a small 'update' to the documentation for it, LZOFFSET is 18 for the following reason 3 is your minimum length 18 is your maximum length.  The makers of the format likely surmized that if you can't go back at LEAST your maximum length and read all that data you will end up trying to read from unwritten data on the output (a bad thing) so they put that in to alleviate potention errors.

If I find the background files I'll be happy (smirk) either they are MIM BSX or DAT my guess is DAT or MIM.  Anyhow here is what I am using to decompress LZS (pardon the lack of commments).
Code: [Select]
#define  LZLEN    3
#define  LZOFFSET 18
AnsiString  TMain::LZSDec(AnsiString FName)
{
   fstream     File;
   fstream     Out;
   AnsiString  Return;
   char        Ctrl;
   short int   CtrlBits;
   unsigned short Ref;
   int         Offset, Len, DestLen, FileEnd;
   int         Pos, NewP, Result;
   char        OutB[64];

   File.open(FName.c_str(), fstream::in | fstream::binary);
   Return = "temp";
   Out.open(Return.c_str(), fstream::out | fstream::in | fstream::binary);
   if (File.is_open())
   {
      File.seekg(0, SEEK_END);
      FileEnd = File.tellg();
      File.seekg(0, SEEK_SET);
      if (Out.is_open())
      {
         DestLen = 0;
         CtrlBits = 0;
         Ctrl = 0xFF;
         while ((File.tellg() < FileEnd) && !File.eof())
         {
            if (CtrlBits == 0)
            {  // read more control bits here
               File.read(&Ctrl, 1);
               CtrlBits = 8;
            }
            if ((Ctrl & 0x01) == 0)
            {
               File.read((char *)&Ref, 2);
               Offset = (Ref & 0x00FF) << 4;
               Offset+= (Ref & 0x0F000) >> 12;
               Len = ((Ref & 0xF) >> 8) + LZLEN;
               Pos = Out.tellg();
               // the new position is
               // the current position - 18 - Offset
               NewP = Pos - LZOFFSET - Offset;
               // and the result with 0xFFF
               NewP &= 0x0FFF;
               if (NewP == 0)
                  break;
               // if the Offset position is <=
               // the current Output position
               if (NewP <= Pos)
               {  int I;

                  Offset = Len / NewP;
                  // the resulting position is within the file
                  Out.seekg(Pos - NewP, SEEK_SET);
                  // the Length is greater than the offset
                  if (Offset > 0)
                  {  // read the New Position bytes
                     Out.read(OutB, NewP);
                     // now write the data (Length / Offset) times
                     for (I = 0; I < Offset; I++)
                     {  // write out data here :)
                        Out.write(OutB, NewP);
                     }
                  }
                  else
                  {  // read len bytes
                     Out.read(OutB, Len);
                        // move back to our position
                     Out.seekg(Pos, SEEK_SET);
                     // write len bytes
                     Out.write(OutB, Len);
                  }
               }
               else
               {  // it's beyond the begining of the file
                  // so we just write out 0's
                  memset(OutB, 0, Len);
                  Out.write(OutB, Len);
               }
               DestLen += Len;
            }
            else
            {  // copy the byte
               File.read(OutB, 1);
               Out.write(OutB, 1);
               DestLen ++;
            }
            Ctrl >>=1;
            CtrlBits--;
         }
         Out.close();
      }
      File.close();
   }
   return Return;
}

35
General Discussion / Alhexx: is your site having troubles?
« on: 2003-03-28 16:54:32 »
I keep getting
500 Internal Server Error

An internal server error occurred. Please try again later

Each time I attempt to access your page..
http://www.alhexx.com right? I get the page 'name' but seems the server might be having 'issues' thought you might want to know :)

Cyb

36
Warning this contains CODE :)
These are the record structures.. almost verbatum save a few small changes.
Code: [Select]

typedef struct  { // [0x0044] Descriptions; no actual game data
BYTE level; // [0x0000] Lead character's level
BYTE party[3]; // [0x0001] Party
char name[16]; // [0x0004] Lead character's name (ff7 text)
USHORT curHP; // [0x0014] Lead character's current HP
USHORT maxHP; // [0x0016] Lead character's base HP
USHORT curMP; // [0x0018] Lead character's current MP
USHORT maxMP; // [0x001A] Lead character's base MP
UINT gil; // [0x001C] Amount of gil
UINT time; // [0x0020] Total number of seconds played
char location[32]; // [0x0024] Save location (ff7 text)
} FF7DESC;

typedef struct  { // [0x0084] Character info
BYTE id; // [0x0000] Character id (used by Sephiroth/Vincent slot)
BYTE level; // [0x0001] Level (0-99)
BYTE strength; // [0x0002] Strength (0-255)
BYTE vitality; // [0x0003] Vitality (0-255)
BYTE magic; // [0x0004] Magic (0-255)
BYTE spirit; // [0x0005] Spirit (0-255)
BYTE dexterity; // [0x0006] Dexterity (0-255)
BYTE luck; // [0x0007] Luck (0-255)
_UNKNOWN z_1[6];
BYTE limitlevel; // [0x000E] Current limit level (1-4)
BYTE limitbar; // [0x000F] Current limit bar (0xFF = limit break)
char name[12]; // [0x0010] Name (ff7 text)
BYTE weapon; // [0x001C] Equipped weapon
BYTE armor; // [0x001D] Equipped armor
BYTE accessory; // [0x001E] Equipped accessory
BYTE flags[3]; // [0x001F] Character flags
// [0:0x10] 1: Sadness
// [0:0x20] 1: Fury
// [1:0x01] 1: Front row  0: Back row
USHORT limits; // [0x0022] Learned limit skills
USHORT kills; // [0x0024]
USHORT timesused; // [0x0026]
_UNKNOWN z_3[4];
USHORT curHP; // [0x002C] Current HP
USHORT baseHP; // [0x002E] Base HP (before materia alterations)
USHORT curMP; // [0x0030] Current MP
USHORT baseMP; // [0x0032] Base MP (before materia alterations)
_UNKNOWN z_4[4];
USHORT maxHP; // [0x0038] Maximum HP (after materia alterations)
USHORT maxMP; // [0x003A] Maximum MP (after materia alterations)
UINT exp; // [0x003C] Current EXP
UINT materia[16]; // [0x0040] Materia slots (0-7=weapon,8-15=armor)
UINT expNext; // [0x0080] EXP to next level
}  FF7CHAR;


typedef struct  { // [0x0010] Chocobo
USHORT speed; // [0x0000] Sprint speed
USHORT maxspeed; // [0x0002] Max Sprint speed
USHORT sprintspd; // [0x0004] Speed
USHORT maxsprintspd; // [0x0006] Max Speed
_UNKNOWN z_1[2];
BYTE intelligence; // [0x000A] Intelligence
_UNKNOWN z_2[2];
BYTE raceswon; // [0x000D] Number of races won
BYTE sex; // [0x000E] Sex (0=male,1=female)
BYTE type; // [0x000F] Type (Yellow,Green,Blue,Black,Gold)
} FF7CHOCOBO;


typedef struct  {
USHORT x;
USHORT y;
USHORT z;
} FF7XYZ;




typedef struct
{
   char  UNUSED[0x200];
USHORT checksum; // [0x0200] Checksum
_UNKNOWN z_1[2];
FF7DESC desc; // [0x0204:44] Slot description
BYTE colors[4][3]; // [0x0248] Window colors (RGB)

FF7CHAR chars[9]; // [0x0254:84] The nine characters (Cl,Ba,Ti,Ae,Re,Yu,Ca,Vi,Ci)
BYTE party[3]; // [0x06F8] Party members
_UNKNOWN z_2;
USHORT items[320]; // [0x06FC] Items (320 slots)
UINT materia[200]; // [0x097C] Materia (200 slots)
_UNKNOWN z_3[224];
UINT gil; // [0x0D7C] Party gil
UINT time; // [0x0D80] Total number of seconds played
_UNKNOWN z_4[16];    // [0x0D82]
USHORT mapid; // [0x0D92] Current map
USHORT locationid; // [0x0D94] Current location
_UNKNOWN z_5[2];     // [0x0D96]
FF7XYZ coord; // [0x0D98] Current coordinates (world map)
_UNKNOWN z_6[7];     // [0x0D9E]
struct {   // [0X0DA5] Love points
BYTE aeris;
BYTE tifa;
BYTE yuffie;
BYTE barret;
} love;
_UNKNOWN z_7[5];     // [0x0DA9]
USHORT battles; // [0x0DAE] Number of battles fought
USHORT runs; // [0x0DB2] Number of escapes
BYTE timer[4]; // [0x0BB4] Game timer (HH:MM:SS:TT)
_UNKNOWN z_8[44];
// [0x0BBC] Number of times used (Curse Ring)
BYTE keyitems[8]; // [0x0BE4] Key items
_UNKNOWN z_9[258];
USHORT gp; // [0x0CEE] Party GP (0-10000)
_UNKNOWN z_10[12];
BYTE stables; // [0x0CFC] Number of chocobo stables owned
_UNKNOWN z_11;
BYTE stablesoccupied; // [0x0CFE] Number of occupied stables
BYTE chocobomask; // [0x0CFF] Mask of occupied stables
_UNKNOWN z_12[196];
FF7CHOCOBO chocobos[6]; // [0x0DC4] Chocobo slots
_UNKNOWN z_13[128];
BYTE disc; // [0x0EA4] Current CD
_UNKNOWN z_14[31];
char chocobonames[6][6];// [0x0EC4] Chocobo names
USHORT chocostaminas[6];// [0x0EE8] Chocobo staminas
_UNKNOWN z_15[24];
char location[24]; // [0x0F14] Name of location
_UNKNOWN z_16[436];
// [0x0F63] Number of times used (Curse Ring)
// [0x0F29][0x08] Map instructions shown

    BYTE battlespeed; // [0x10D8] Battle speed, 0=fastest FF=slowest
    BYTE battmsg; // [0x10D9] Battle message speed
    USHORT flags; // [0x10DA] Flag bits
    _UNKNOWN z_17[16];
    BYTE msgspeed; // [0x10EC] Field message speed
    _UNKNOWN z_18[7];
    _UNKNOWN END_REC;
    //_UNKNOWN END_REC[3340];
} FF7_GAME;


As you can see nothing much was changed except the first 512 bytes are ignored in the save state here is the code I'm using for calculating the CRC, it's pretty much identical only I use where the END of the record is to terminate the loop (END_REC).

Code: [Select]

//---------------------------------------------------------------------------
void TJenovaForm::CheckSum(void)
{
char     *Buffer,
            *Termination;
int       temp, Bit;
long     Result = 0xFFFF;//,
            //length = 4336;
long     Mask = 0x8000;

    //temp = sizeof(FF7_GAME);
    Buffer =       (char *)&Game->desc;
    Termination =  (char *)&Game->END_REC;
while( Buffer < Termination)
{
temp = *Buffer;
Result ^= temp << 8;
for(Bit=0; Bit<8; Bit++)
{
if( Result & Mask )
Result = ( Result << 1 ) ^ 0x1021;
else
Result <<= 1;
    Result &= 0xFFFF;
}
      Buffer++;
}
    Result = ~Result;
    Result &= 0x0000FFFF;
Game->checksum = Result;
}

If I make changes however, I've no way to verify the CRC is correct save using Jenova (laugh) of your creation by exporting it to PC then running Jenova on it then exporting (hopefully with proper CRC changes?) I'm wondering if this is a problem for both Jenova and my toy.. hmm.

37
Hmmm I'm porting Jenova (well it's more like rewritting Jenova but I digress) to a DLL for editing PSX memcards, Qhimm you have a clue what region of the card the CRC calculation is over?  I've diddled a while and it's got me stumped.. I've tried from just past the CRC word to message speed
This doesn't seem to work (File Ruined error).  I assume you haven't messed with the PSX version, but the CRC calculation is identical (that might be assuming a lot LOL).

Cyb

38
Scripting and Reverse Engineering / PSX file sets for FF7
« on: 2002-12-19 05:58:26 »
Hmmm are the files similiar between the PC and PSX for all the background settings? I'm not sure what format they are in.  I've found 3 files per 'scene' in FF7 BSX DAT ad MIM.  MIM are my guess the background image information and BSX and DAT are likely to being the extra 'scene' objects (IE things you can walk behind etc.)

Cyb (curious CYB strikes back)

39
I've a few additions to the Griever save file format (ala PSX) it should be relatively easy to migrate to the PC (minor changes).

Code: [Select]

#ifndef _FF8_
#define _FF8_

#include <vcl.h>
/////////////////////////////////////////////////////////////////
// Final Fantasy VIII codes

// If you can find a way to make the enum 1 byte in size, uncomment
/*
enum FF8CHARID {
Squall,
Zell,
Irvine,
Quistis,
Rinoa,
Selphie,
Seifer,
Edea,
Laguna,
_zz1,
_zz2,
_blank,
Griever,
MiniMog,
Chicobo,
Angelo,
None = 0xFF
};
*/

#define CHAR_SQUALL        0
#define CHAR_ZELL          1
#define CHAR_IRVINE        2
#define CHAR_QUISTIS       3
#define CHAR_RINOA         4
#define CHAR_SELPHIE       5
#define CHAR_SEIFER        6
#define CHAR_EDEA          7
#define CHAR_LAGUNA        8
#define CHAR_KIROS         9
#define CHAR_WARD          10

#define CHAR_GRIEVER       12
#define CHAR_MINIMOG       13
#define CHAR_CHICOBO       14
#define CHAR_ANGELO        15
#define CHAR_NONE          0xFF


typedef BYTE FF8CHARID;
//#define FF8CHARID BYTE
//#define BYTE unsigned char


struct _FF8ITEM {
BYTE type;
char *name;
};

struct _FF8ABILITY {
BYTE type;
BYTE ap;
char *name;
};

struct _FF8MAGIC {
char *name;
};

#define CARD(t,l,r,b) { 0x##t,0x##l,0x##r,0x##b }

#define NONE -1
#define FIRE 0
#define ICE 1
#define THUNDER 2
#define EARTH 3
#define POISON 4
#define WIND 5
#define WATER 6
#define HOLY 7

#define SIMPLE 0
#define BOSS 1
#define GF 2
#define PLAYER 3


struct _FF8CARD {
char *name;
struct _FF8CARDVALUES {
char top;
char left;
char right;
char bottom;
} values;
char element;
char border;
};

struct _FF8CARDLOCATION {
char *name;
};

struct _FF8LOCATION {
char *name;
};

typedef BYTE _FF8INNATEABILITY;


/////////////////////////////////////////////////////////////////
// Final Fantasy VIII item/magic/ability lists
#define LOCCOUNT 200

extern _FF8ITEM dbItems[200];
extern _FF8ABILITY dbAbilities[120];
extern _FF8MAGIC dbMagic[60];
extern _FF8CARD dbCards[110];
extern _FF8CARDLOCATION dbCardLocations[256];
extern _FF8LOCATION dbLocations[LOCCOUNT];
extern _FF8INNATEABILITY dbInnateAbilities[16][21];
extern char *dbJuncNames[];
extern char *dbWeapons[];
extern int const GF_Level[16];
/////////////////////////////////////////////////////////////////
// Final Fantasy VIII save file structures


// Unknown data
struct UNKNOWN {
UNKNOWN () { data = 0xFF; }
BYTE data;
};

// FF8 text identifier
typedef char FF8STR;


// Save file description block
struct FF8DESC {
USHORT checktag; // Tag - must be 0x0FF8
USHORT location; // Current location
UNKNOWN zz0[4];
USHORT saves; // Number of saves
UINT gil; // Gil
UINT seconds; // Game time
BYTE level; // Lead character's level
FF8CHARID party[3]; // [3] Current party
};



// Guardian Force block
struct FF8GF {
FF8STR name[12]; // [10] GF name
//UNKNOWN zz1[2];
UINT exp; // GF EXP
UNKNOWN zz2;
BYTE found; // Has GF been found?
USHORT hp; // Current HP
BYTE abilities[16]; // [16] Learned abilities (bLearned[i] = abilities[i/8] & (1 << (i%8)))
BYTE ap[21]; // [21] Ability APs
UNKNOWN zz3[3];
USHORT kills; // Number of enemies killed
USHORT ko; // Number of KOs
BYTE learning; // Ability being learnt
BYTE forgotten[3]; // Abilities forgotten
};

// Magic block
struct FF8MAGIC {
BYTE type;
BYTE amount;
};

// Character block
struct FF8CHAR {
USHORT hp; // Current HP
USHORT basehp; // Base HP
UINT exp; // EXP
FF8CHARID id; // Character id
BYTE weapon; // Current weapon
BYTE str; // Strength
BYTE vit; // Vitality
BYTE mag; // Magic
BYTE spr; // Spr
BYTE spd; // Speed
BYTE luck; // Luck
FF8MAGIC magic[32]; // [32] Magic library (stock)
BYTE ab_command[3]; // [3] Command abilities
UNKNOWN zz;
BYTE ab_char[4]; // [4] Character abilities
USHORT gf; // Junctioned GFs
UNKNOWN zz2[2];
BYTE junction[19]; // [19] Junctions
// 00: HP Junction (Magic Type)
// 01: Str Junction (Magic Type)
// 02: Vit Junction (Magic Type)
// 03: Mag Junction (Magic Type)
// 04: Spr Junction (Magic Type)
// 05: Spd Junction (Magic Type)
// 06: Hit Junction (Magic Type)
// 07: Eva Junction (Magic Type)
// 08: Luck Junction (Magic Type)
// 09: Elem-Atk Junction (Magic Type)
// 10: ST-Atk Junction (Magic Type)
// 11: Elem-Def Junction 1 (Magic Type)
// 12: Elem-Def Junction 2 (Magic Type)
// 13: Elem-Def Junction 3 (Magic Type)
// 14: Elem-Def Junction 4 (Magic Type)
// 15: ST-Def Junction 1 (Magic Type)
// 16: ST-Def Junction 2 (Magic Type)
// 17: ST-Def Junction 3 (Magic Type)
// 18: ST-Def Junction 4 (Magic Type)
UNKNOWN zz3;
USHORT compat[16]; // [16] GF compatibility
USHORT kills; // Number of enemies killed
USHORT ko; // Number of KOs
BYTE stats; // Battle metere stats?
UNKNOWN zz4;
USHORT status; // Status effects
//   1: ?Death?
//   2: Poison
//   4: Petrify
//   8: Darkness
//  16: Silence
//  32: Berserk
//  64: Zombie
// 128: ?Sleep?
                        // 256: ?Slow?
                        // 512: ?Stop?
                        //1024: ?Curse?
                        //2048: ?Confuse?
                        //4096: ?Drain?
//UNKNOWN zz5;
};

// Item block
struct FF8ITEM {
BYTE type;
BYTE amount;
};

// Card identifier
typedef BYTE FF8CARD; // 0x80: Collected    0x7F: Amount
// Rare cards: Location

struct FF8CONFIG {
BYTE spd_battle; // Battle speed (0=fast,4=slow)
BYTE spd_battlemsg; // Battle message speed (0=fast,4=slow)
BYTE spd_fieldmsg; // Field message speed (0=fast,4=slow)
BYTE soundvolume; // Sound volume (0-100(%))
BYTE options; // Misc. options
//   1: ATB - 1:Wait 0:Active
//   2: ??? 0:Stereo 1: Mono
//   4: Cursor - 1:Memory 0:Initial
//   8: ???
//  16: ???
//  32: Controller - 1:Customize 0:Normal
//  64: ???
// 128: ???
BYTE scan; //   1: Scan - 1:Always 0:Once
BYTE camera; // Camera movement (0=100%,4=0%)
UNKNOWN zz1;
UNKNOWN buttons[12]; // [12] Button configuration (?)
};


// Chocobo World data
struct FF8CHOCOBO {
UNKNOWN zz[64];
};

// limit structure
struct FF8LMT
{
   unsigned short Quistis;
   unsigned short Zell;
   BYTE           Irvine;
   BYTE           Selphie;
};

// Save file block
struct FF8BLOCK {
UNKNOWN zz1[384];

USHORT checksum1; // Checksum
FF8DESC desc; // Save block description

FF8STR squall[12]; // [12] Squall's name
FF8STR rinoa[12]; // [12] Rinoa's name
FF8STR angelo[12]; // [8] Angelo's name
FF8STR chicobo[12]; // [4] Chicobo's name
BYTE disc; // Current disc (zero based)
UNKNOWN zz[3];
UINT saves; // Number of times saved (*2?)

FF8GF gf[16]; // [16] GF blocks

FF8CHAR chars[8]; // [8] Character blocks
                           // 0 - Squall
                           // 1 - Zell
                           // 2 - Irvine
                           // 3 - Quistis
                           // 4 - Rinoa
                           // 5 - Selphie
                           // 6 - Siefer
                           // 7 - Edea

UNKNOWN zz2[400];

FF8CONFIG config; // Configuration
FF8CHARID party[3]; // [3] Party
UNKNOWN zz22[5];
FF8STR griever[12]; // [8] Griever's name

UNKNOWN zz23[4];
UINT gil; // Gil
UNKNOWN zz24[4];

   FF8LMT   limits;
// BYTE limits[6]; // [6] Learned limit breaks
// [0]-[1] Quistis
// [2]-[3] Zell
// [4] Irvine
// [5] Selphie
BYTE combine_compl; // Rinoa's Combine: Angelo Abilities Completed
BYTE combine_known; // Rinoa's Combine: Angelo Abilities Known
BYTE combine_left[8]; // [8] Rinoa's Combine: Points left to learn different abilities
// [0] 'Angelo Rush' (max 10)
// [1] 'Angelo Recover' (max 30)
// [2] 'Angelo Reverse' (max 40)
// [3] 'Angelo Search' (max 60)
// [4] 'Angelo Cannon' (max 80)
// [5] 'Angelo Strike' (max 120)
// [6] 'Invincible Moon' (max 140)
// [7] 'Wishing Star' (max 160)

BYTE b_items[32]; // [32] Order of battle items
FF8ITEM items[198]; // [198] Items

UINT seconds; // Game time
UNKNOWN zz28[8];
UINT battleswon; // Number of battles won
UNKNOWN zz29[2];
USHORT battlesescaped; // Number of battles escaped
UNKNOWN zz30[60];
BYTE limit_options; // Limit break options (1:Renzokuken Auto, 2:Duel Auto)
BYTE limit_indicator; // Renzokuken indicator (128)
BYTE information0; // Bit 0 Party isolated / Dream world (1)
                           // Bit 1 Have Odin
                           // Bit 2 Have Phoenix
                           // Bit 3 Have Gilgamesh
                           // Bit 4 Rinoa can't summoon Angelo
                           // Bit 5 Rinoa can use Angle wings
                           // Bit 6 Unknown
                           // Bit 7 Unknown
BYTE information[9]; // [9] Information (bitmask)
// [0]1-8: Location information
// [2]1-8: Location information
// [3]1-4: Location information
// [3]5-8: Term information
// [4]1-8: Term information
// [5]1-6: Term information
// [5]7-8: People information
// [6]1-5: People information
// [6]6-8: Character reports
// [7]1-4: Character reports
// [8]3-3: Term information
// [8]4-6: Report information
UNKNOWN zz31;
BYTE gf_reports[3]; // [3] GF reports

UNKNOWN zz3[3];
BYTE testlevel; // Current written test level
UNKNOWN zz39[4];
FF8CHARID party_field[3]; // [3] Current field party ([0] = leader)
UNKNOWN zz395[7];
USHORT location; // Current location
USHORT location_last; // Last location (?)
UNKNOWN zz4[30];
UINT steps; // Number of steps taken
USHORT payslip; // Payslip steps
UNKNOWN zz5[6];
USHORT seedlevel; // SeeD Level
UNKNOWN zz55[66];

UNKNOWN zz550[2];
// USHORT location_last; // Last location ?
UNKNOWN zz551[186];

BYTE tt_rules[8]; // [8] Region game rules
BYTE tt_traderules[8]; // [8] Region trade rules
BYTE tt_lastrules[2]; // [2] Last game rules remembered ([1] = second to last)
BYTE tt_lastregion[2]; // [2] Last region remembered ([1] = second to last)
UNKNOWN zz555;
BYTE tt_currules; // Current game rule
BYTE tt_curtraderule; // Current trade rules
BYTE tt_cardqueen; // Card Queen's location
BYTE tt_traderating_region; // Region for trade rating
BYTE tt_traderating; // Trade rating

UNKNOWN zz6[1110];
FF8CARD cards[77]; // [77] Cards (bit 8=collected, bit 1-7=amount)
BYTE card_locations[33]; // [33] Card locations
BYTE cards_rare[5]; // [5] Rare cards found (bFound[i] = cardsfound[i/8] & (1 << (i%8)))
UNKNOWN zz7[9];

USHORT test1;
USHORT test2;
FF8CHOCOBO cw; // Chocobo World data
USHORT checksum2; // Checksum (identical to checksum1)
BYTE padding[2782]; // Padding, makes save block 8192 bytes
};

#endif


Have fun .. with this .. the changes are realtively small but make it easier to read.  the information bit fields still have a way to go.. namely I have to go through the game and watch every tutorial and do everything in the game etc. (sigh).

Cyb

Pages: 1 [2]