Kid Icarus Revealed: 1-3
The fortress data starts with somekind of header. I call it header block, and I think I'm the first person that discovered it. Now I'l discuss what I found there.
Consider the first fortress area.
| Location | Level | Description |Size |
| 1B11A-1B12F | 1-4 | Header block | |
| 1B130-1B183 | 1-4 | Screen pointers | |
| ... | ... | ... | |
The Header block viewed in detail:
| Location | Level | Description |Size(d)|
| 1B109-1B10F | 1-4 | 2 jumps |6 |
| 1B10A-1B118 | 1-4 | Header code |10 |
| 1B119-1B119 | 1-4 | RTS instruction |1 |
| 1B11A-1B12F | 1-4 | Unknown Block |21 |
The six first bytes are two jumps. The first jump leads to the RTS instruction. The second jump leads to the beginning of fortresses code at $A801 with bank 6 mapped.
The bytes following the jumps, till the RTS, are code. I'm not sure of its real purpose at the moment, though I'll list the assembler code. This code end up with a RTS instruction, and then there's a strange block. Even though I tried, I don't know what it is used for. If you corrupt it, fortresses levels come out corrupted too, and platform collision detection screws up. They remind me of the FFFF line of the ordinal levels.
Room map should be conceptually seen as an 8x8 matrix. I'll refer to rooms with two coordinates, X and Y, that are the index of this matrix. This way, room (3,4) is to the right of room (2,4). But the rooms data are stored sequentially, from left to right, top to bottom. This way;
Room (0,0) is room 0.
Room (1,0) is room 1.
Room (2,0) is room 2.
Room (0,1) is room 8.
Room (7,7) is room 3F.
Rooms map sequential order:
0 1 2 3 4 5 6 7
8 9 A B C D E F
10 11 12 13 14 15 16 17
18 19 1A 1B 1C 1D 1E 1F
20 21 22 23 24 25 26 27
28 29 2A 2B 2C 2D 2E 2F
30 31 32 33 34 35 36 37
38 39 3A 3B 3C 3D 3E 3F
Apparently, starting room is always (3,3), which is 1B.
Rooms map table
This area reserves 2 bytes per room. The rooms are stores sequentially. After one room comes the one to the right, and if it is at the rightmost position, then, next room would be the leftmost of newt row. Just see the rooms map above.
- Byte 0 is room pointer.
The boss room uses room pointer 29h. And the second byte is always 00h.
- Byte 1 keeps information of room accesses
Bit 0: Top stairs
Bit 1: Right door
Bit 2: Bottom stairs
Bit 3: Left door
00h No access. Cool! So scary. :-)
02h Room with door on the right.
0Ah Room with both doors
0Fh Room with all accesses. These are the good ones :-)
This table for fortress 1 is:
0001b1b8h: 00 00 00 00 00 00 00 00 16 04 00 00 00 00 00 00
0001b1c8h: 00 00 00 00 07 06 03 0A 03 0B 0C 0C 00 00 00 00
0001b1d8h: 00 00 00 00 04 05 00 00 00 00 04 05 15 04 00 00
0001b1e8h: 00 00 02 06 08 0D 01 02 02 0A 03 0F 0C 0F 16 08
0001b1f8h: 00 00 03 05 03 03 03 0A 0A 0E 03 09 03 05 00 00
0001b208h: 28 02 12 0B 13 0A 02 0A 14 0B 13 0A 0E 0D 00 00
0001b218h: 00 00 00 00 00 00 00 00 00 00 00 00 0F 03 29 00
0001b228h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Each line represents one row of rooms. We see first 4 rooms empty. Then comes a room 16h with bottom stairs. This rooms is one of the two fortress' shops. From now fortresses map will be handy. You can download them from my web. They were made by Kenneth Brown.
Room enemy table
One byte per room.
Low nibble sets that particular enemy layout in the room. High nibble set enemy type.
Examples in first fortress are:
10h - blue skull
20h - red skull
3xh - kobil (34, 37)
4xh - red kobil (44, 46, 47)
5xh - spikes (50,51,52)
6xh - Eggplant Wizard (60, 61, 62)
F0h - Twinbellows.
Fortress 1's table is:
0001b238h: 00 00 00 00 00 00 00 00 00 00 51 61 60 36 00 00
0001b248h: 00 00 00 00 00 38 00 00 00 34 52 00 10 37 46 00
0001b258h: 00 37 00 37 35 37 47 00 00 32 50 20 62 50 41 00
0001b268h: 00 00 00 00 00 00 40 F0 00 00 00 00 00 00 00 00
We can see no enemies in the first row of rooms (rooms 00 to 07)
The first enemy we find is 51h, which stands for spikes layout 1. The room to the right contains eggplant wizards layout 1, and room to the next eggplant wizards layout 0.
Note: Serpents don't appear in this table. They always come out from "pitchers"
Enemy position table
I'm not sure how it works yet. But it stores the initial enemy position data, according to low nibble data of room enemy table.
Map and centurions table
Two bytes per room. But this time there's no:
- Byte 0 is room number.
- Byte 1 is the position inside the room.
High nibble: Y tile position
Low nibble: X tile position
The first 2-bytes group of this table is the position of the map item.
Then, centurion data comes.
This table seems variable length, ended with FF, ignoring subsequent bytes till palette comes.
Again, fortress 1 map and centurion table is:
0001b2c4h: 1D AD 0A 23 0B 45 0B 4A 0C 45 0C 4A 0D 27 0D 7E
0001b2d4h: 15 A1 19 71 1A AE 1A A1 1D A4 1D AE 1E 75 21 7E
0001b2e4h: 22 71 22 AE 23 37 24 A5 24 89 26 71 26 AE 2C 8A
0001b2f4h: 2D A9 2E 7E 2E AC 36 A3 36 AE FF 36 A3 36 AE 36
0001b304h: AE 36 AE
You can see that map item is located in room 1D (5,3). It is placed in tile (D,A). Then we see a centurion in room 0A, placed in tile (3,2). Room 0B has two centurions. And so on.
This table holds memory pointers to fortress' structure data. Structures used in all fortresses are stores in the shared fortress ROM area. It's the same as Structure pointers for ordinal levels, and it's been already discussed.
But I realized that these tables (fortresses' ones) are completely useless. I'm not sure weather the games does actually access them (I suppose it does), but you can edit all fortress' rooms without even know that these tables exist.
Why? Well, If you have a look at these tables, you'll realize that all 3 fortresses have the same Structure pointers, and so, their structure list is the same. It would have been enough to define one single structure pointer table in the shared fortress ROM area. No need to use 3 tables. So, it could be shared, as it happens with Structure data.
Why programmers decided to use three tables is unknown for me. But I have a guess. Probably their plans where more ambitious, and they wanted to use different structures for each fortress (maybe, even different graphics). Afterwards, during game development, due to any reason, they decided to simply use the same structures, to get things simpler. Maybe to finish up quicker? I found some more evidences in the ROM that lead me to think that something where just finished up quickly. Or maybe, they just did what they had to, no worrying to make code look pretty. And this is probably what happened.
Fortress structure pointers:
0001b184h: 5D A2 62 A2 6B A2 74 A2 79 A2 84 A2 8A A2 90 A2
0001b194h: 94 A2 9A A2 A3 A2 B8 A2 C1 A2 C4 A2 CB A2 CF A2
0001b1a4h: D5 A2 D8 A2 DD A2 E3 A2 E7 A2 F0 A2 F6 A2 F9 A2
0001b1b4h: 02 A3 08 A3
0001b478h: 5D A2 62 A2 6B A2 74 A2 79 A2 84 A2 8A A2 90 A2
0001b488h: 94 A2 9A A2 A3 A2 B8 A2 C1 A2 C4 A2 CB A2 CF A2
0001b498h: D5 A2 D8 A2 DD A2 E3 A2 E7 A2 F0 A2 F6 A2 F9 A2
0001b4a8h: 02 A3 08 A3
0001b74ch: 5D A2 62 A2 6B A2 74 A2 79 A2 84 A2 8A A2 90 A2
0001b75ch: 94 A2 9A A2 A3 A2 B8 A2 C1 A2 C4 A2 CB A2 CF A2
0001b76ch: D5 A2 D8 A2 DD A2 E3 A2 E7 A2 F0 A2 F6 A2 F9 A2
0001b77ch: 02 A3 08 A3
No secret rooms!
I usually compare ROM hacking with Archaeology. You search for things. You uncover mysteries. For some time, I was looking for any "treasure" hidden in the ROM, like a secret room, an unused routine or something. No luck so far.
Anyway, just to add some sugar, take a look the room below.
This room is stored in the ROM like all the others. It isn't a secret room, but is, some kind of a special room. It is actually one of the Twinbellows fortress' rooms, stored in the same exact way as the rest of them. Although Pit goes through it once, you never really enter an play in it. It all happends automatically, because this room is one of the end rooms that Pit goes through when he finishes a level.
By the way, and obviously, there's one room like this one in Hewdraw's and Pandora's fortresses too, because, as discussed previously, they all share same room data, just some macros change, due to exclusive tiles differing from one world to another.
I won't cover much of this now. But, of course, knowing how the game works, let's you play it different. For example, you can cheat becoming immortal, getting health point when you go into lava, or having unlimited number of feathers.
The basis are simple. Every dynamic data is stored in RAM. By dynamic data I mean all information that changes during the game, and needs to be managed. For example, health points, the number of items Pit has, or if he got any sacred weapon, his strength and endurance,... and also data needed for game engine, like platform collision detection, sprites position and speed, or counters.
All of this data is stored in some RAM location. Let's call them variables. If you know the address of the variable, then you can do many things. For example, look in the code for all 6502 instructions that decrement some value in one, and then store in life points variable. This will prevent Pit from getting damage.
Now, it may seem simple. It is. But, the problem is finding out what every RAM location means, and which ones are variables, and what do they store. RAM location $A6 does not say anything to me. Probably, not to you either. But I found that it's the life points variable. So now I can do what I just explained.
Other variables I found are:
$AA : Number of life points bars.
$12f: (World 1)
$130: (Level 1)
$131-$133: Score, 3 bytes.
$14A-$14B: Hearts, 2 bytes.
$14C-$14D: Credit card debt.
$14E: Credit card
$151: Barrels. Bit 6 is 1 when you have it. Lower bits hold
$152: Strength (number of arrows).
And some other more difficult to find, and used for game engine:
$B6 : Mapped bank
$FD : Scroll Y.
$FE : Scroll X
$FF : PPU port 2001.
$100: PPU port 2000
$385: World number * 2.
$4d3-$4d9: Collision detection with platforms.
Then, there're a lot of RAM locations that are used for specific purposes, and many other used for temporary data storing, while doing some processing. For example, a routine in bank 6 uses the following 4 bytes of RAM.
$104: Number of bytes to copy to VRAM
$105-$106: 16 bit VRAM destiny address.
$107: Bytes to copy to VRAM
Any thing to say, or things I discovered after huge amount of workWell, many interesting things, but just far too complex to really worth mentioning them all. For example, spending hours disassembling code, gave me a good idea of the programming techniques and style, used by the game programmers. Sure it should be of no interest for many people, but I like to uncover things. To see what was veiled.
If I find any of these interesting pieces of code, I'll share them with you in the next document I write. Now I just don't remember where I saw seen them.
Keep in mind that disassembling a 128Kb ROM is massive amount of work.
For example, bank 7, where main game engine resides, is more than 10000 assembler lines long. Bank 2 and bank 3 are also interesting, as they hold much code used in World 1,2 and 3 ordinal levels, decompression routines, and bank 5 has fortress' specific code. Even if you work only on bank 7, it can take a lot of time to get a general overview.
Code in bank 6 is still a mystery for me. It holds most of game's level data, but I know that the game also calls some routines from this bank, quite early from the beginning of its execution.
Well, this should be a fair chunk of information for the moment. Not much secrets about level data are out there. I'll update this document soon with more information on doors positioning data in levels.
Many things are still to be covered, like:
- Interesting code routines, I discovered.
- RAM location meanings, I discovered.
- Text translation.
- More on cheating.
That will be in the future. Sooner if someone is interested on it. If I hear no voices from anyone about this document, I might keep all in secret and take it to the tomb :-)
And remember, Kid Icarus Cult.
David Senabre Albujer. 31/07/06