First, I'm going to tell a little story. This is how the story text works in the game.
Rival Schools uses a relative pointer system. This means that each line of dialog has a piece of code that tells the game where that dialog is. It's like an address to find a particular string. It stores all of these codes in a pointer table, which is basically just an address book of all the text in teh game. In order to find a pointer for the text, you need two pieces of information: the text start location and an offset used to calculate the pointer value. Once you know a pointer value, you can search the binary data for it to (hopefully) discover the pointer address. To find the pointer offset, you need to know the difference of the text start position in the file, vs the text start position in the PSX RAM once that file is loaded. For Rival Schools, the story data begins at
0x81C in the game data file (CDEMOXX.BIN). The RAM address is 0x9C81C. So, the offset is 0x9C81C - 0x81C = 0x9C00Knowing the offset, we can calculate the pointer value. The first line of dialog that uses this is Taiyo's story after the intro text, and that adress actually starts at
0x8FD. So first, we add the offset to this address.0x930 + 0x9C000 = 9C930Next, you remove the high-bits to get a 2 byte address, so we're left with this:
0xC930.We now have to swap the endianness, so jus swap the low and high end bytes.
0x30C9This is the pointer value for that first line of dialog. Searching for this hex in the data file, we find that value at address
0x3A68. Each pointer is actually a full 4 byte string. It looks like every pointer just ends with 0x09 0x80 in this table, so you can now rewrite the entire pointer table if you know the address where each line of dialog starts. Pretty cool, huh?0x00. This way, the game knows to stop reading in characters when drawing them to the screen. The in the ending file all end with 0x01 instead. Additionally, there are 3 bytes of data after that. Batsu's bad ending, for instance, has 0x01 0x02 0x00 0x02 after his first line of dialog. His second line ends with 0x01 0x03 0x00 0x02. These appear to be commands to end the string and to play an audio track (or two). The bytes following the string terminator are index for which audio file to play next. This set of commands is ended with a
0x02. So to use Batsu's ending again, 0x01 0x02 0x00 0x02
0x01 = end the string.
0x02 = load play the second audio file
0x00 = don't play another audio file.
0x02 = end of audio file commands.
There are some cases where 2 audio files are played, so that second to last byte isn't guaranteed to be
0x00. The bytes between the final dialog from one ending and the start of the next ending are as follows.0x00 0x10 0x00 0x00 0x00 0x01 0x00 0x3CI'm not sure what all of these mean though. I think the first
0x00 is just to terminate the ending itself. I'm pretty sure the 0x01 near the end is to play the first audio file in the list. I don't know why or what the 0x3C is. I've tried overwriting a couple endings to see if it just works if I have the right bytes in place, and it almost works. Kyosuke's ending is actually first in the file followed by Batsu's. I wrote the Kyosuke ending in Indonesian and then copied the data above and immediately wrote Batsu's Indonesian ending. The first line of Batsu's ending is a simply '.', and I think it played the wrong audio, but the second line and audio all appeared correctly. So, I don't think the endings work off of pointers at all. It's purely positional and decoding these commands. I just need to figure out what the meaning is behind each one.| Process | Progress |
|---|---|
| Translation | 14% |
| Proof reading | 0% |
| Insertion | 5% |
| Testing | 0% |

Comments
Post a Comment