ROM Addressing

From BindingForce Wiki
Jump to navigation Jump to search

There are several different ways to refer to data in memory in Zelda II. Which one you use depends on your reasoning for doing so. This page will explain where they're useful and how to translate between them.

ROM File

NES ROM files are in a format generally called iNES. Most ROMs (including Zelda 2 ROMs) are in iNES 1.0 format. The layout of a Zelda II ROM file is as follows (an MMC1 cartridge with 8 PRG ROM banks, 16 CHR-ROM banks, and 4KB of SRAM -- for more details see Data Crystal):

Type Number File Offset Size Contents
iNES Header 0x00000 16bytes (0x10)
PRG Bank 0 0x00010 16KB (0x4000)
1 0x04010 16KB (0x4000) Western Hyrule
2 0x08010 16KB (0x4000) Eastern Hyrule
3 0x0C010 16KB (0x4000) Towns(?)
4 0x10010 16KB (0x4000) Normal Palaces
5 0x14010 16KB (0x4000) Great Palace
6 0x18010 16KB (0x4000) Music(?)
7 0x1C010 16KB (0x4000) Global State (permanently mapped)
CHR Bank 0 0x20000 8KB (0x2000)
1 0x22000 8KB (0x2000)
2 0x24000 8KB (0x2000)
3 0x26000 8KB (0x2000)
4 0x28000 8KB (0x2000)
5 0x2a000 8KB (0x2000)
6 0x2c000 8KB (0x2000)
7 0x2e000 8KB (0x2000)
8 0x30000 8KB (0x2000)
9 0x32000 8KB (0x2000)
10 0x34000 8KB (0x2000)
11 0x36000 8KB (0x2000)
12 0x38000 8KB (0x2000)
13 0x3a000 8KB (0x2000)
14 0x3c000 8KB (0x2000)
15 0x3e000 8KB (0x2000)

Bank Offsets

Given an offset into a dumped ROM, you can find out what bank it's in by dividing the offset by 0x4000 and subtracting the size of the iNES header (0x10 or 16 bytes). For example:


And then you can use the remainder (or modulus) to get the offset within that bank:


From there you can determine the memory address it would be mapped into memory at, if you want, by figuring out where that bank would be mapped (for banks 0-6, they will be mapped at 0x8000 and for bank 7 they will be mapped at 0xc000):


For a bit more clarity on how that works, see the next section.


CPU Memory Map

When the game is running, the 16bit address space on the NES is mapped out roughly like so from the CPU's perspective:

Offset Size Area
0x0000 0x800 RAM
0x2000 0x2020 Hardware Registers
0x6000 0x2000 Cartridge SRAM
0x8000 0x4000 Low PRG Bank (swappable)
0xC000 0x4000 Upper PRG Bank (fixed to bank 7)

This memory map, which is dictated by the way the MMC1 memory mapper maps memory, means that the area of memory between 0x8000 and 0xC000 is switchable. Addresses in this range can refer to any of the 8 PRG banks in the ROM (though in practice, will only ever refer to the first 7). Addresses above 0xC000, however, will *always* map to the last bank (PRG Bank 7).

Bank And Offset

In order to describe a part of the cartridge's ROM, you can refer to it in terms of its bank number and offset within that bank. An address described this way could look like this:

5:0x1234 (or bank 5, offset 0x1234)

This allows for pretty easy conversion to other addressing styles. In order to get the offset into a dumped ROM, you can use the following formula: 0x10+(bank*0x4000)+offset. The above address would be found at 0x15244.

This is a pretty rarely used way to refer to locations, but is useful to understand anyways. You can always recognize this address format by the fact that it includes a bank number and another number that is less than 0x4000.

Bank And Memory Address

More convenient for working with addresses in memory, this representation is used a lot by emulator debugging interfaces in particular. As in #Bank And Offset, an address in this format starts with a bank number, but the second number is its address as mapped into RAM at runtime. So, for example, the above address would be:

5:0x9234 (bank 5, memory address 0x9234)

For Zelda II, all addresses in banks 0 through 6 will be represented as within the range 0x8000-0xBFFF in this format, while addresses in bank 7 will be in the range 0xC000-0xFFFF:

7:0xD234 (bank 7, memory address 0xd234)

Unfortunately, this format is more complicated to convert into ROM file offsets, or vice versa, because you have to know more about how the game maps memory. For Zelda II in particular, the formula for converting to a dumped ROM offset is 0x10+(bank*0x4000)+(address%0x4000) -- where % is modulus (or remainder).