Adding Text in a game help.

Share and discuss all facets of DKC ROM hacking...

Adding Text in a game help.

Postby Gaz » June 25th, 2012, 11:54 am

So, I was wondering how to change text from one piece of text (E.g.: Stop & Go Station) to another (E.G.: Stop and Go Station) in a ROM via a Hex editor (I use XVI32) without messing up the ROM. Any help please?
User avatar
Taster of Pork
Bananas received 47
Posts: 642
Joined: 2011

Re: Adding Text in a game help.

Postby Blaziken257 » June 29th, 2012, 12:25 pm

It involves editing pointers. Basically, pointers are integers that store the address of data, like the first letter in a string. Typically, there is a table of pointers either before or after the data; in DKC's case, it's before. Perhaps it will make more sense if I do an example.

The string "Stop & Go Station" starts at 0x38A6F1 in the ROM. Now, to calculate the pointer in an SNES game like DKC (I assume this is the case for all SNES games, although I haven't done much SNES hacking at all), you must cut off all but the last four nibbles (a nibble in hexadecimal is like a digit in decimal). So for here, 38A6F1 becomes A6F1.

But you're not done yet... Nintendo systems are, in general, little-endian, so you must reverse the bytes. Each byte is two nibbles long; so in this case, you switch A6 with F1 to get F1A6. There's your pointer.

Now how do you find it? Search for the hex string F1 A6 in a hex editor. In XVI32, you can search upwards; search once (in this case) and you'll find the pointer table; the pointer F1 A6 is at 0x38A320. How do you know it's a pointer table? You can see a little pattern here:

... C7 A6 D8 A6 E7 A6 F1 A6 02 A7 0E A7 1F A7 ...

The red is the pointer that you are searching for. The bold is meant to indicate a pattern. They are all similar to each other (they start out as A6 (at least from what I pasted here) and become A7, and so on), and the bytes just before the bold increase a little each time. Whenever you see something like this, chances are pretty good you found a pointer table.

Now, something important. If you want to change the text from "&" to "and", you'll have to expand this string. And by doing this, you are going to shift all the strings afterwards (in this case, two bytes). Therefore, to make the game search in the right spots, you'll have to adjust the pointers for any text that comes after "Stop & Go Station". So anything that comes after F1 A6, you'll have to increase the values of these pointers (in this case, by 2). Remember that pointers are little endian, so don't be confused! It's tedious, but it's certainly possible to do.
Now this part is a bit extra, but here's how to calculate pointers for GB/GBC and GBA games in case anybody's curious:

GBA: Unlike the SNES, pointers are four bytes instead of two (so basically it's ww xx yy zz instead of yy zz). However, you must add 0x8000000 to the address to make it a pointer. So an address of 0x123456 would become 0x08123456. And like before, GBA is little endian, so you must switch the bytes! So 0x08123456 becomes 56 34 12 08. (Although, I've heard of exceptions to this latter rule, but I haven't seen any.)

GB/GBC: There are 2-byte and 3-byte pointers. 2-byte pointers are limited in the area that you can address (only a range of 0x4000 bytes), but they're more common since they take up less space. 3-byte pointers can point to anything in the ROM. I'll go over 2-byte pointers first.
- 2-byte pointers: Obviously, these are two bytes long. Like the SNES, you must only have the last two bytes (123456 becomes 3456, for example). However, there's something tricky here! If this new address is outside the range of 0x4000-0x7FFF, you must add or subtract by a multiple of 0x4000 to make it fit in this range! So basically, the formula is:

pointer = (address mod 0x4000) + 0x4000

Another way to think of it is:

- If the two-byte address is from 0x0000-0x3FFF, add 0x4000.
- If the two-byte address is from 0x4000-0x7FFF, do nothing.
- If the two-byte address is from 0x8000-0xBFFF, subtract 0x4000.
- If the two-byte address is from 0xC000-0xFFFF, subtract 0x8000.

So for example, if the two-byte address is 0x3456, you add 0x4000 to make it 0x7456.

And of course... like other Nintendo systems, Game Boy and Game Boy Color are little endian. So switch the bytes! For example, 0x7456 becomes 56 74. However, there are exceptions, such as Donkey Kong Land 2 and Donkey Kong Land III. These are rare, and I don't know of any others.

- 3-byte pointers: This is similar, except there's another byte you have to have before the normal two bytes. And no, it's not as simple as truncating the address to three bytes. You must find the ROM bank of the address. It's simple, just divide by 0x4000 and discard the remainder. So for example, if you have an address of 0x123456, the ROM bank is (0x123456/0x4000)=0x48. That's your first byte.
The last two bytes are calculated the same way as before, so it would be 74 56. The full three-byte pointer would be 48 74 56.
If that was all confusing, then this may help instead:
Treasure Hunter
Bananas received 108
Posts: 333
Joined: 2008

Return to ROM Hacking

Who is online

Users browsing this forum: No registered users and 2 guests