Hello there
"Intro - ...duction..."I was debugging ff7.exe to find some information useful when trying to change font used in-game. Why would i do that for? Because a team from Poland - FF7-PL, is making a polish version of FF7 (which is my favourite game... again
). You know who M4v3r is, so I think I don't need to say anything else. The polish font in their release occupies some in-my-humble-opinion-very-important characters, so I started to make my own font. I don't know that for sure, but i think I found out some info, which wasn't posted here, on Qhimm's forum. So... that's what I've found out. Listen up...
"First chapter - Why mine is bigger than yours?"FF7 uses an array to see how much pixels each letter has. The address in memory (after loading ff7.exe EN v1.0):
- 0x0098F458
In that array, each byte corresponds to a single character. To decode the data stored, all you have to do is get the byte for a character, and look for the corresponding data in the array. After that:
- to get a character's width, AND a just-found-byte with 0x1F (00011111b)
- to get a character's padding (well I don't know if that's what it's called, but it's just a number of pixels before the character), SHR just-found-byte by 5
Example:
To get a quotation mark "values", we:
- get the byte for that character - it's stored in address 0x0098F458 (base address) + 0x1F (the hex value for quotation mark). It should be 0x27 (or 00100111b or 39);
- AND it with 1F, or modulo it by 0x20 (32) - we get 7
- SHR it (the byte read 0x27) by 5 (or divide by 32) - we get 1
And... that's it. Remeber that these values are in 320x240 resolution mode (not really sure about that), to get the size in the 640x480 mode multiply the results by 1.666667, and truncate the non-integer part (even if it's 4.9998, we get 4).
OK... We do know, how to get the character size. But how to change it? There are some methods. We can do it by changing the data stored in the memory for example. We get the immediate effect. To those who don't want it to be a temporary change, we have to change data in the file. Which file? Oh... that's the 3rd file of WINDOW.BIN pack-file. We have to unpack it, change it and repack it (the worst part
). It wasn't me who discovered, that the data is stored in that particular file (i just knew that it's in WINDOW.BIN, then I came here to see if it has already be decoded, and found out that I've just reinvented the wheel), so don't call me a leecher
"Second chapter - Oh mummie, that dog after some paintings looks cool"We all know, that the font itself is in menu_us.lgp file, but do we know how to change it? Well... You do
I didn't. Used Mirex's Biturn (omg, that's a good piece of work, THX Mirex for writing it), and just changed the font. Then i started to wonder... maybe i can write a program for quick replacing the font graphics and widths. I have a program to repack the modified file which contains the "width-data", I know the TEX format good enough... wait a minute... I didn't
After some debugging work, that's what i found out (i know, that some bytes where know for long, but that's what i have found out about reading TEX files by ff7):
TEX_FILE_HEADER is 0xEC long, and contains of 59 int-s. Some of them listed below (by offset):
0x00 - TEX file "version", if it's not 0x00000001, the game will not load it.
0x04 - zero... always... i think
0x2C - zero?
0x30 - MYSTERIOUS_DATA_NUM_OF_ENTRIES
0x3C - RES_X (already known...)
0x40 - RES_Y
0x44 - zero?
0x48 - zero?
0x4C - PALLETTE_ACTIVE (if it's set, then there is a pallete data right after the header, if it says zero, the pallette-data is missing from the file)
0x58 - PALLETE_NUM_OF_ENTRIES (to get pallete data width, multiply by 4)
0x60 - PALLETTE_PTR (Doesn't really matter. It's always zero-ed when loading the header, after reading pallette data here is where the pointer to that data is stored)
0x68 - BYTES_PER_PIXEL for the bitmap data (bitmap data comes in the file after the header and the pallette data)
(here some unknown data)
0xBC - MYSTERIOUS_DATA_ACTIVE (if it's set, then there should be some data after the bitmap part of the file)
0xC0 - MYSTERIOUS_DATA_PTR (same as PALLETTE_PTR, it could be 0 as well...)
0xC4 - It's set after loading the header (always with 0xFF... i think)
0xC8 - Set after loading the header (when debugging it was 0x04, mostly)
0xD4 - BITMAP_PTR (it's set after the memory allocation and reading the bitmap data, so... who cares)
0xD8 - don't know
(hmm... it's zero-ed like the pointers, but i didn't see it containing any data after loading the pallette... weird)
"Third chapter - Can you tell me HOW you DO IT?"How the game reads the TEX file?
- Allocates a memory (on the heap... or maybe not... forgot
) for a header and reads it into the memory.
- if 0x00 DWORD says 0x00000001 then keeps loading, otherwise stops reading that file
- if 0x4C DWORD is set, reads the pallette (4*0x58 DWORD) and stores the data pointer in the 0x60; if the pointer is NULL, ff7 stops reading that tex-file
- reads the bitmap data (0x3C DWORD * 0x40 DWORD * 0x68, or RES_X*RES_Y*BYTES_PER_PIXEL) and stores the pointer in 0xD4 DWORD; again, if the pointer is NULL, stops reading that file
- if the mysterious data is present (0xBC DWORD is set) reads the data (0x30 DWORD * 1) and stores it's pointer; if it's NULL... blah
After that, it does some mysterious and not really interesting things...
"Epilogue - Stupid talk..."Well... that's it for now
I hope it's gonna help someone (hmm... if you are good enough to decode my post, you ain't gonna need it, 'coz you're a super-human with abnormal abilities). When i get any other data which is somehow connected with ff7, I'll post it (or not... if I got banned before that). Have a nice life