Kid Icarus Revealed: 2-1

An introduction to ROM hacking and NES architecture.


It’s been more than half a year that I wrote PART 1, and I really wanted to go on with this article. Many many things remain to be untold. So, after explaining how the game works, I’ll give some info about how it stores data.

Text on Kid Icarus

Let’s hunt text string

So, so easy. Anyone with some knowledge would have no problem working this out. But, as I’m going as deep as I can with this ROM, I’ll also speak about it.

Finding text location is simple, as Kid Icarus ROM stores them in plain format, non compressed or encoded in any way.

You can find most of the text string by using a simple relative searcher. But I’ll explain another way of doing it, for those who might not fully understand it, but also because some strings won’t be found using relative search.

If you take a look at both pattern tables while in the start menu, you will necessarily see the font characters, as no tile can be displayed on screen if not loaded in the PPU memory. Using FCEUXD emulator, which is great, by the way, you can view the pattern tables seen below.

As you might know, left pattern table is used in game sprites, while right pattern table is used in backgrounds, and it’s the one we are interested in, because, most times, static text which does not dynamically change or move, is drawn in the background, and not as sprites. Ok, ok, we could have worked this out by simply realizing that left pattern table does not contain font characters apart from numbers. But it is good to understand where things come from.

So, “START” and “CONTINUE” strings can only be in background at this time, because they are constituted by patterns loaded in the background pattern table. Anyway, that would be the only reasonable option, as it has no sense to create at this point 5 sprites (one for each character in START) and 8 more sprite (one for each character in CONTINUE), when none of them will move neither change.

But there is one sprite in this screen, the arrow (marked with a green square below) which points the selected option, because it must move in response of the player action.

In short, text strings will be in the background the vast majority of times.

Now, how can we find these strings in the ROM?
Go back to the pattern table and find the position of ‘S’ inside this table. You’ll find it is 40, or $28 (in hex). If you do the same for all the rest of characters, you get that:

  START is a sequence $28 $29 $16 $27 $29
  CONTINUE is a sequence $18 $24 $23 $29 $1E $23 $2A $1A

We can try and see if these strings are stored in the ROM using the same value for each letter that each of them will have in the pattern table.

If you search in an hex editor for $28 $29 $16 $27 $29 you get two occurrences, in addresses 0x67E4 and 0x11122.

Let’s see what we find in 0x67E4.

This one looks just great. A few bytes after the values we suspect could be START (in yellow), there’s $18 $24 $23 $29 $1E $23 $2A $1A (in red), which corresponds to the sequence CONTINUE.

This is what we where looking for.

Let’s change some text

To change the string we just found, just change the values of each letter, for the value corresponding to the letter you want to turn it into. Example.

Imagine you want to change START into SUPER.
If you look up in the pattern table the values for U ($2A), P ($25) and E ($1A), change,

$28 $29 $16 $27 $29 into $28 $2A $25 $1A $27

And this works, as you can see.

What we CAN NOT do

This was an easy task. It’s great that programmers store text strings in such a simple way. Keep in mind, though, that this does not happen in other ROMs, where other more sophisticated methods are used, especially when lots of text has to be stored.

Anyway, in this ROM we were lucky. But not everything is good about it. An obvious limitation is that you can’t make words longer than they were, because you if you go further, you will overwrite data that was stored after the end of the word. You can make a string shorter, by turning the ending characters to value $12, which in this case stands for an empty pattern.

Imagine you want to change START into GO PIT.
GO PIT has 6 characters (the space is pattern like any other).
But START has only 5 characters.

It’s easy to see that you can’t replace
$28 $29 $16 $27 $29
$1C $24 $12 $25 $1E $29

You need one more byte.
You can’t go on replacing bytes further that the end of the original string. If you do it, you will overwrite the byte after it, and could cause a disaster, depending on what it was stored there.

What would happen in this example?
Last $29 overwrites a $04 that was stored there (marked in red).

And it happens that the value stored in that position was crucial for the ROM to work, and you get a nice black screen.

You might think on just inserting value $29 between $1E and $04. You just CAN’T do this and walk again as if nothing happened, because you would shift all data after the inserted byte by one position, and thus, make the ROM unusable.

Hope you were not thinking on this, because if you did, you might need to learn a few more things on ROM basics. This is something everyone who wants to play around with ROMs must know. A general rule is “never insert bytes”, ROMs don’t like this, except if you know very well what you’re doing… as I’ll show next.

How we CAN do it

Yes, it can be done.

Doing this (I’ll explain now).

By some reason, some bytes after CONTINUE string seem to not affect the game, and they can be overwritten (I guess what they may be, but I’ll not discuss it now, to help keep things clear). So, what you need to do is insert the value $29 (in green) between $1E and $04, and then, delete one byte after CONTINUE (the one after $1A, in red), so all bytes after it go back to its original position

Step by step.
Find original START string.

Replace START with GO PI

Insert $29, that is T. Notice how all bytes after it are shifted forward one position

Now we delete the byte after $1A. See how all bytes after it go back to its original position.

Now, even though this will work, and not crash, you will only see,

We need to make one more change. Change the byte just before the string GO PIT, from 05 to 06 (marked in red, in the image below). This value tells the game about the number of characters that the string coming next has.

Now we’ve got it

You can do the same for the string CONTINUE, to turn it into a longer string. I tried to add up to 4 characters using this method, and the game seemed to work fine.

Keep in mind that this I’ve just done, will probably not work in other situation, because most of the times, you just can’t overwrite bytes. In this particular situation, I found, by ROM corruption trial and error, that the game would still be happy if we slay a few bytes after CONTINUE string.

List of string found using the simple method shown here.

67E4   START    (28 29 16 27 29)
67ED   CONTINUE (18 24 23 29 1E 23 2A 1A)

1E706   HEART     (1D 1A 16 27 29)
1E70F   ENDURANCE (1A 23 19 2A 27 16 23 18 1A)
1E71C   STRENGTH  (28 29 27 1A 23 1C 29 1D)
1E72F   WEAPONS   (2C 1A 16 25 24 23 28)
1E73A   TREASURES (29 27 1A 16 28 2A 27 1A 28)
1E784   M A P     (22 12 16 12 25 12 12)
        M A P A   (22 12 16 12 25 12 16)
1E78C   TOTAL     (28 24 29 16 21)
1E791   SCORE     (28 18 24 27 1A)
1E796   STAGE     (28 29 16 1C 1A)
When you defeat Pandora

ED26   PIT        (25 1E 29)
ED2A   EQUIPPED   (1A 26 2A 1E 25 25 1A 19)
ED33   HIMSELF    (1D 1E 22 28 1A 21 1B)
ED40   WITH THE   (2C 1E 29 1D 12 29 1D 1A)
ED48   TREASURES! (29 27 1A 16 28 2A 27 1A 28 0E)

Password input screen

6B6F   ENTER  (1A 23 29 1A 27)
6B75   SACRED (28 16 18 27 1A 19)
6B7C   WORDS  (2C 24 27 19 28)

There’s another SACRED WORDS but I don’t know where it appears in the game 

1C331   WORDS

(The following PUSH START BUTTON is not the one appearing at the beginning of the game  Don’t know yet where it is displayed) 

1111a   PUSH   (25 2A 28 1D)
11122   START  (28 29 16 27 29)
11128   BUTTON (17 2A 29 29 24 23)

Title Screen is diferent

While in the title screen, only a few letters are loaded into the pattern table, and they’re scattered across it. So, their values in the ROM are expected to change. The pattern table looks like:

12, stands for ‘space’ again. And the numbers 0..9 are in the same position.
But now, letters have the following positions:

P = 31
U = 5D
H = 64
B = 65
L = 7B
E = 9F
N = A6
A = A7
Y = AF
G = B5
R = B6
O = B7
D = BF
S = D0
T = C3
. = 0B

Let’s try to find PUSH START BUTTON

According to the above table, this strings should be coded as
PUSH = 31 5D C0 64
START = C0 C3 A7 B6 C3
BUTTON = 65 5D C3 C3 B7 A6

Searching the ROM for it PUSH leads us to a unique coincidence.

Very nice! We’re right again! As you can see, we can be sure we found it, because just after PUSH come the other 2 strings, separated by a 12 (space), just as we see it on screen. Let’s play around, turning spaces into dots (replace 12 by 0B)

Offset 0x62F8
PUSH      (31 5D C0 64)
START     (C0 C3 A7 B6 C3)
BUTTON    (65 5D C3 C3 B7 A6)

If you want to translate this into Spanish (PULSA BOTON START), you would change above values into;

31 5D 7B C0 A7 12 65 B7 C3 B7 A6 12 C0 C3 A7 B6 C3

What we CAN NOT do

Again, we are not able to just make the sentence longer. You can show up to eighteen maximum characters. Of course, you can make the sentence shorter, by using ‘space’ (12).

Remember how the code originally was

If you take space from the bytes after the last 12 (marked in blue, in the image above), the game seems to be unaffected. Even if you overwrite 80 AA after them, nothing seems to happened. But it is better to leave things as God made them. To do these changes is not the way to succeed.

David Senabre Albujer. 2007