God Hand DAT Files - akitotheanimator/God-Hand-Tools GitHub Wiki

God hand has DAT files. Which each one store files inside, like a ZIP file. However, God hand doesn't stablish a format for it. the DAT files may vary a lot depending on the DAT type.

This wiki is NOT programmer friendly.

This wiki assumes you're a experienced programmer and that you know what you're doing.

Determining the DAT type

There's several DAT types that GOD HAND utilizes. Some for models, some for maps. Here's some of the differences.

Type 0 (GPF)

  • The first 4 bytes of the file measures how much files are packed.
  • Offset 4 return a adress that doesn't point to blank uint32 bytes.
  • The offsets list start from offset 4.

Type 1 (MPF)

  • The first 4 bytes of the file counts how many elements after the header contains. But these aren't the file adresses. i have no clue what the offsets are.
  • Offset 4, 8 and 12 returns a adress that point to blank uint32 bytes.
  • The offsets list start from offset 16.
  • The packed files measure has to be calculated from the adress that offset 16 points to.

Type 2 (PEF)

  • I have no clue what the first 4 bytes are.
  • The offset 4 points to the start of the MOT Adresses.
  • The offset 8 points to a string section which tells the el DATs used in the MOT's.
  • The offset 12 points to the end of the string section.
  • The offset 16 points to the start of the MOT Files datas.
  • The offset 28 points to the end of the MOT Files datas.

With these informations, you can calculate and determine the type of each dat.

Now that you know which type is the DAT you're using in, we can check how they're calculated.

DAT Type 0

The most common type for a DAT. It is encountered on Game Model dats.

0
FL (UInt32)

Where :

  • FL is how much files the .DAT contains. The adresses from all of the files in the container is gathered like this:
SO = 4 + FO
EO = (FL * 4) + SO

Where :

  • SO is the Starting Offset
  • EO is the Ending Offset.
  • FO is the file start. in type 0, it is equals 0.

and while iterating though the offsets, it gathers the containing file offsets using the following formula:

for(int i = SO; i < EO; i+=4)
   OFFSETS_ADRESSES.add(ReadUInt32(i))

Where

  • OFFSETS_ADRESSES is a UInt List where all the offsets are stored
  • i is the current file offset. ReadUInt32 is a fictional function to return the UInt32 Value from the dat file at offset i.

each added uint on OFFSETS_ADRESSES returns is the offset where the file starts. now, to get where the file ends, it's quite simple.

for(int i = 0; i < OFFSETS_ADRESSES.Count-1, i+=1)
  OFFSETS_END_ADRESSES.add(OFFSETS_ADRESSES[i+1])
OFFSETS_END_ADRESSES.add(DFL);

Where :

  • OFFSETS_END_ADRESSES is a UInt List where all the end of the offsets are stored
  • i is the current file offset.

The file formats are identified, but there's no names for them, because dat files it's based on indexing. TO get the file format, you gotta iterate again.

for(int i = SO + (FL * 4); i < EO + (FL * 4); i+=4)
   OFFSETS_STRING.add(GetString(i,4))

Where :

  • OFFSETS_STRING is a String List were all the file formats are stored. the file formats always store a 4 length string.

DAT Type 1

The dat type 1 is used to store maps and so. DATs type 1 are just like DATs type 0, but with some changes.

0
NULL
FRO(UInt32)

Where:

  • FRO is the adress that the dat offsets starts.

After determining the FRO value, the rest of the process is the same of DAT Type 0. But with the FO of type 0 DAT being the value of FRO.

DAT Type 2

The dat type 1 is used to store animation events, like cutscenes. Wildly different from both type 0 and type 1.

0 (Byte) 1 (Byte) 2 (Byte) 4 (Int32) 8 (Int32) 12 (Int32)
NULL FGMQ(Byte) GEQ(Byte) MSO(UInt32) SSSO(UInt32) SSEO(UInt32)
FSPO(UInt32) NULL NULL NS NS FEPO(UInt32)

Where:

  • GMQ is the Fist Group MOT Quantity, the quantity of mots that is given before the elements field.
  • GEQ is the Given Element Quantity, the quantity of Elements the file has.
  • MSO is the MOT Start Offset, the offet where the mot adresses are given.
  • SSSO is the String Section Start Offset, which is the offset that the utilized .dats names list starts.
  • SSEO is the String Section End Offset, which is when the string section stops.
  • FSPO is the File Start Position Offset, which is where the MOT datas starts to be given.
  • FEPO is the File Ending Position Offset, which is where the MOT datas ends to be given.
  • NS is the Offsets that are not set to a specific value, sometimes it's value is blank, but sometimes it can point to a .SEQ.

The type 2 DAT doesn't give you the packed file types, so you will need to find them by your own. Luckly, the only two "important" files in type 2 is the MOT's and the SEQ's.

  • 16 to MSO = SEQ Files.
  • MSO to SSSO = MOT Files.
  • SSEO to FSPO = MOT Files.
  • FEPO to FILE_SIZE_OR_MOT = other/misc/unrecognized.

After gathering these values, you will need to apply a series of rules to sucesfully gather all the offsets.

To gather the .SEQ files offsets, iterate from offset 16 until offset MSO, adding 4 to each iteration.

for(int i = 16; i < MSO; i+=4)

Now, read each i offset and check if the value is higher than 1, and if the readen value of i is not equals FEPO

if(ReadUInt32(i) > 0 && ReadUInt32(i) != `FEPO`)

that's how you gather the offsets of the SEQ files.

To gather the .MOT files offsets, you will need to make two iterations. Firstly, iterate from offset MSO until offset SSSO, adding 4 to each iteration.

for(int i = MSO; i < SSSO; i+=4)

Apply the same rule of "if > 0"

if(ReadUInt32(i) > 0)

Secondly, iterate from offset SSEO until offset FSPO

for(int i = SSEO; i < FSPO; i+=4)
  if(ReadUInt32(i) > 0)

that's how you gather the offsets of the MOT files.

FEPO is already a adress, so nothing need to be done. To finish, Sort all of the adresses you've gathered based on offset number i.e:

  • if offset[0] = 46
  • and offset[1] = 29 then the sort should be like this:
  • 29
  • 46 and after gathering and sorting all the adresses correctly, you can save the files.

Saving the files

To save the files, you do this operation:

for(int i = 0; i < OFFSETS_ADRESSES; i+=1)
   saveFile(OFFSETS_ADRESSES[i], OFFSETS_ADRESSES[i + 1], OFFSETS_STRING[i]);

Where :

  • OFFSETS_ADRESSES is a array containing all of the adresses you just gathered.
  • OFFSETS_STRING is a array containing all of the file formats as string you just gathered.
  • saveFile is a function that saves all the bytes of the .dat in a file, reading bytes from adress A to adress B with the format name of C.