User Tools

Site Tools

“Working to make user-friendly hacking tools since 2020.”

metroid:pointers

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

metroid:pointers [2015/02/28 22:59] (current)
Line 1: Line 1:
 +======Pointers In Metroid======
 +This document explains how pointers work in Metroid and how to convert from a pointer value to a ROM offset and vice-versa. ​
  
 +An NES pointer is usually written as a four-digit hex number preceded by a dollar sign, e.g. $ABCD. NES pointers are little-endian. A pointer with the value $1234 would appear as 34 12 in a hex editor.
 +
 +====Memory Map====
 +The table below lists the memory addresses a pointer may refer to in Metroid.
 +    $0000 - $00FF  RAM (zero-page)
 +    $0100 - $01FF  RAM (stack)
 +    $0200 - $07FF  RAM
 +          -
 +    $2000 - $401F  Hardware Registers
 +          -
 +    $8000 - $BFFF  Swappable ROM bank
 +    $C000 - $FFFF  Fixed ROM bank
 +===Zero Page===
 +Zero page is a special section of memory that can be accessed with 8-bit pointers. The reason for this is that instructions that use 8-bit pointers execute faster and take less space in the ROM. This section of memory is often referred to with a two-digit value, such as $76, rather than a four-digit value like $0076, but $76 and $0076 refer to the same memory location.
 +
 +===Banks===
 +Metroid is divided into banks of 16 KB. The original game contains 8 banks of data, numbered 0 through 7. An expanded ROM contains 16 banks of data, numbered 0 through F. Metroid always has two banks loaded at a time. One bank is loaded at $8000-$BFFF and another is loaded at $C000-$FFFF.
 +
 +This table shows what each bank is used for in an unexpanded ROM
 +  0 - Title Screen, Password Entry, Game Over, Ending
 +  1 - Brinstar
 +  2 - Norfair
 +  3 - Tourian
 +  4 - Kraid'​s Hideout
 +  5 - Ridley'​s Hideout
 +  6 - Graphics
 +  7 - Game Engine
 +
 +This table shows what each bank is used for in an expanded ROM
 +  0 - Title Screen, Password Entry, Game Over, Ending
 +  1 - Brinstar
 +  2 - Norfair
 +  3 - Tourian
 +  4 - Kraid'​s Hideout
 +  5 - Ridley'​s Hideout
 +  6 - ????
 +  7 - ????
 +  8 - Brinstar screen data
 +  9 - Norfair screen data
 +  A - Tourian screen data
 +  B - Kraid screen data
 +  C - Ridley screen data
 +  D - Not used
 +  E - Used by Editroid
 +  F - Game Engine
 +  ​
 +===Swappable Bank===
 +The bank at $8000-$BFFF is swappable. Metroid stores the data for each level in a different bank, and keeps the appropriate bank loaded for the level the player is in. So, for instance, when the player is in Brinstar, bank 1 will always be accessible at $8000-$BFFF.
 +===Fixed Bank===
 +The bank at $C000-$FFFF is fixed. The last bank in the ROM is always loaded here. This is where Metroid stores data and code common to every level (i.e. the game engine). In the original game, bank 7 will always be loaded here. In an expanded ROM, bank F will always be loaded here.
 +====Pointer To ROM offset====
 +ROM offsets (the location of a piece of data in the ROM file) are usually represented in hex. While a pointer is usually written as $1234, a ROM offset can be written $1234, 0x1234, or for bonus confusion, sometimes just 1234. In this article, ROM offsets will always use the 0x representation.
 +
 +An NES ROM contains a sixteen ($10) byte header which is followed by all the game's banks. Metroid uses 16 KB ($4000 byte) banks, so the first bank starts at 0x10, the second bank starts an 0x4010, the third bank starts at 0x8010, and so on. The table below shows the offset of all the banks.
 +  0 -    0x10
 +  1 -  0x4010
 +  2 -  0x8010
 +  3 -  0xC010
 +  4 - 0x10010
 +  5 - 0x14010
 +  6 - 0x18010
 +  7 - 0x1C010
 +  8 - 0x20010
 +  9 - 0x24010
 +  A - 0x28010
 +  B - 0x2C010
 +  C - 0x30010
 +  D - 0x34010
 +  E - 0x38010
 +  F - 0x3C010
 +To convert a pointer to a ROM offset, subtract the bank's base address from the pointer, and add the ROM offset of the bank. The base address is $8000 for pointers between $8000 and $BFFF. The base address is $C000 for pointers between $C000 and $FFFF.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +For example, a pointer with the value of $ABCD falls between $8000 and $BFFF, so base address is $8000. Assuming this is a pointer for Brinstar, we would be working with bank 1, which is at 0x4010. The pointer $ABCD would point to 0x6BDD in the ROM.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +             = ABCD    - 8000         + 4010
 +             = 6BDD
 +If the pointer were for Norfair instead, we would be using Bank 2 at 0x8010. The pointer would point to 0xABDD in the ROM.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +             = ABCD    - 8000         + 8010
 +             = ABDD
 +A pointer with the value of $DEAD falls between $C000 and $FFFF, which is the fixed bank. The base address of the fixed bank is $C000. Pointers between $C000 and $FFFF will always point to the last bank. In an unexpanded ROM this is bank 7, located at 0x1C010 in the ROM, so $DEAD would point to 0x1DEBD.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +             = DEAD    - C000         + 1C010
 +             = 1DEBD
 +In an expanded ROM, the last bank is bank F, which is located at 0x3C010, so $DEAD would point to 0x3DEBD in the ROM.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +             = DEAD    - C000         + 3C010
 +             = 3DEBD
 +With some practice, the conversions can be done in your head, especially when it comes to the fixed bank.
 +
 +A pointer with a value of less than $8000 points to RAM or a hardware register, and can't be mapped to a ROM offset.
 +====ROM Offset to Pointer====
 +To convert a ROM offset to a pointer, simply reverse the process above.
 +  Pointer = Rom Offset - Bank Offset + Base Address
 +Suppose you put some new data at 0x8775 in the Norfair bank and want to change a pointer to point to this data. The bank offset is 0x8010. This bank would be loaded as the swappable bank, so the base address is $8000.
 +  Pointer = Rom Offset - Bank Offset + Base Address
 +          = 8775       - 8010        + 8000
 +          = 8765
 +To reference the data at 0x8775 in the ROM, we would use the pointer $8765.
 +
 +Suppose you need a pointer to $1F01D (in an unexpanded ROM). This falls within the game engine bank, which is loaded as the fixed bank at $C000-$FFFF,​ so the base address is $C000.
 +  Pointer = Rom Offset - Bank Offset + Base Address
 +          = 1F01D      - 1C010       + C000
 +          = F00D
 +          ​
 +====BB:AAAA Format====
 +A pointer by itself doesn'​t tell you which bank it refers to. $B00B could refer to any bank, and you have to guess based on the circumstances. To make things clearer, a pointer can be paired with a bank number using the format BB:AAAA (BB = bank, AAAA = address). 01:B00B refers to the address $B00B and bank 1. You still convert this pointer to and from a ROM offset the same way.
 +  Rom Offset = Pointer - Base Address + Bank Offset
 +             = B00B    - 8000         + 4010
 +             = 701B
metroid/pointers.txt ยท Last modified: 2015/02/28 22:59 (external edit)