An in-progress RAM map to aid in custom assembly and ROM disassembly.
0000-3FFF: 16KB ROM Bank (fixed - bank 0) 4000-7FFF: 16KB ROM Bank (swappable) 8000-9FFF: 8KB Video RAM A000-BFFF: 8KB Save RAM C000-DFFF: 8KB Work RAM E000-FDFF: Echo RAM (unused) FE00-FE9F: OAM FEA0-FEFF: Not usable FF00-FF7F: I/O Ports FF80-FFFE: High RAM FFFF: Interrupt enable register
8000-97FF: VRAM tiles 8000-87AF: Samus 8080-9F: Arm cannon 8B00-8EFF: Enemies 0x8C00-8E2F: Characters if room has message box (probably loaded with chozo?) 9000-97FF: Background 9800-9FFF: VRAM tilemap 9800-9BFF: Background 9C00-9FFF: Window 9C00: Status bar 9C20: Message
A000-A03F: File 1 + 00-07: 0123456789ABCDEF + 08: Samus' Y position + 0A: Samus' X position + 0C: Screen Y position + 0E: Screen X position + 10: Enemy tiles source address (2 bytes) + 12: Background tiles source bank + 13: Background tiles source address (2 bytes) + 15: Metatile definitions source address (bank 8, 2 bytes) + 17: Source address of data for $DC00..FF (bank 8, 2 bytes) + 19: Bank for current room + 1A: Samus passable block threshold + 1B: Enemy passable block threshold + 1C: Projectile passable block threshold + 1D: Samus' equipment + 1E: Samus' beam + 1F: Samus' energy tanks + 20: Samus' health + 22: Samus' max missiles + 24: Samus' missiles + 26: Direction Samus is facing + 27: Acid damage + 28: Spike damage + 29: Real number of Metroids remaining + 2A: Song for room + 2B: In-game timer, minutes + 2C: In-game timer, hours + 2D: Number of Metroids remaining A040-A07F: File 2 A080-A0BF: File 3 A0C0: Last used save slot A800-ACE2: Written to in credits [$6:7920..7E02] B000-B1BF: File 1 Item/Metroid data (0x40 bytes per map) B200-B3BF: File 2 Item/Metroid data (verify) B400-B5BF: File 3 Item/Metroid data
C000-9F: OAM buffer (gets copied by the sprite DMA) + 0: Y position + 1: X position + 2: Tile number + 3: Attributes 10: Palette 20: X flip 40: Y flip 80: Priority (set: behind background) C203: Tile Y (see $22BC) C204: Tile X (see $22BC) C205: Scroll Y C206: Scroll X C215: Tilemap address of ([$C204], [$C203]) (see $22BC) C308-37: Ch slots of 4 bytes according to $3:6E36 + 3: XOR'd with 10h in $6E36 every fourth frame C3A1: Scroll X for LCD interrupt handler type = 1 C3A8: X position of Metroid Queen's head on screen C3A9: Y position of Metroid Queen's head on screen C3AA: A two-byte pointer to LCD interrupt data C3D2: Background palette for LCD interrupt handler type = 1 C3D3: Metroid Queen's health C3EF: Set to 1 in $3:6E36 if 0 < [Metroid Queen's health] < 32h, probably an aggression flag C3F1: Set to 1 in $3:6E36 if 0 < [Metroid Queen's health] < 64h, probably an aggression flag C407: Set to [$D069] in $2:4000 C40F: bottom-most visible metatile row index in map * $10 (big-endian word). C411: top-most visible metatile row index in map * $10 (big-endian word). C413: right-most visible metatile column index in map * $10 (big-endian word). C415: left-most visible metatile column index in map * $10 (big-endian word). C418: Set to [$D058] in $2:4000 C422: Cleared by $2EE3, set to 1 by $1FF5 C423: Value for $D00F in $2EE3, cleared by $1FF5 C424: Read by $2EE3, set to [$D078] by $1FF5 C430: Used as index for pointer table at $1:5AB1 C432: Scroll Y two frames ago (according to $3:4000) C433: Scroll Y one frame ago (according to $3:4000) C434: Scroll X two frames ago (according to $3:4000) C435: Scroll X one frame ago (according to $3:4000) C44B: Checked and set in $2:4000, previous value for $C458 in $239C C459: Used by $1:7A6C (when saving to SRAM), decides where in C540.. to process for $C900 C45C: Used as index for table at $1:729C, value for $FFEA C500-FE: Object spawn states (map-specific) C500-C53F: Non-persistent object (e.g. enemy) spawn states 01: Spawned in object table ("visible") 02: Dead/acquired FF: Not spawned C540-7F: Persistent object (e.g. item, Metroid) spawn states C600..C7FF: Enemy data. 20h byte slots according to $30BB, current address is kept in $D05E + 0: Flags. If bits 0-3 clear, $30BB executes $30EA on slot. If bit 7 is set sprite is invisible (blinking). + 1: Y coordinate. Value for $FFB7 in $30EA + 2: X coordinate. Value for $FFB8 in $30EA + 3: Metasprite number. Value for $FFB9 in $30EA + 4: Priority bit ($80) for sprites. Value for $FFBF in $30EA + 5: Sprite flip flags ($20 for horizontal, $40 for vertical) + 6: Low nibble is blink frames remaining. Bit 4 is sprite palette flag. + A: Frozen frame counter. Increments by 2 every 4 frames. 0 is not frozen, 1-$C4 is frozen, $C5-$D0 is thawing. + B: Health + 1D: Map object slot index C900-CABF: Item/Metroid data bytes (0x40 per map, gets saved to SRAM) CEC0-CFFF: Audio data CEC0: Tone/sweep channel sound effect CEC0: Tone/sweep channel sound effect to play 0: Nothing 1: Jumping 2: Hi-jumping 3: Screw attacking 4: Uncrouching / turning around / landing 5: Crouching / unmorphing 6: Morphing 7: Shooting beam 8: Shooting missile 9: Shooting ice beam Ah: Shooting plasma beam Bh: Shooting spazer beam Ch: Picked up missile drop Dh: Spider ball Eh: Picked up energy drop Fh: Shot missile door with beam 10h: 11h: 12h: 13h: Bomb laid 14h: 15h: Option select / missile select 16h: Shooting wave beam 17h: 18h: Samus' health changed 19h: No missile dud shot 1Ah: 1Bh: Metroid cry 1Ch: Saved 1Dh: 1Eh: Unpaused CEC1: Tone/sweep channel sound effect playing CEC3: Tone/sweep channel sound effect timer CEC7: Tone channel sound effect CEC7: Tone channel sound effect to play 0: Nothing 1: Nothing 2: Nothing 3: Metroid Queen cry 4: Baby Metroid hatched / clearing blocks 5: Baby Metroid cry 6: Metroid Queen hurt cry 7: CEC8: Tone channel sound effect playing CECA: Tone channel sound effect timer CECE-CED4: Would be the wave channel sound effect, but is unused (only cleared) and CEE6 is exclusively used instead. CED5: Noise channel sound effect CED5: Noise channel sound effect to play 0: Nothing 1: Enemy shot 2: Enemy killed 3: 4: Shot block destroyed 5: Metroid hurt 6: Samus hurt 7: Acid damage 8: Shot missile door with missile 9: Metroid Queen cry Ah: Metroid Queen hurt cry Bh: Samus killed Ch: Bomb detonated Dh: Metroid killed Eh: Fh: 10h Footsteps 11h: 12h: 13h: 14h: 15h: 16h: Baby Metroid hatched / clearing blocks 17h: Baby Metroid cry 18h: 19h: 1Ah: CED6: Noise channel sound effect playing CED8: Noise channel sound effect timer CEDC: Song to play 0: Nothing 1: Baby Metroid 2: Metroid Queen battle 3: Chozo ruins 4: Main caves 5: Sub caves 1 6: Sub caves 2 7: Sub caves 3 8: Final caves 9: Metroid hive Ah: Item-get Bh: Metroid Queen hallway Ch: Metroid battle Dh: Sub caves 4 Eh: Earthquake Fh: Killed Metroid 10h: Nothing 11h: Title 12h: Samus fanfare 13h: Reach the gunship 14h: Chozo ruins, same as 3 15h: Main caves, no intro 16h: Sub caves 1, no intro 17h: Sub caves 2, no intro 18h: Sub caves 3, no intro 19h: Final caves, same as 8 1Ah: Metroid hive, same as 9 1Bh: Item-get, same as Ah 1Ch: Metroid Queen hallway, same as Bh 1Dh: Metroid battle, same as Ch 1Eh: Sub caves 4, no intro 1Fh: Metroid hive with intro 20h: Missile pickup CEDD: Song playing CEDE: Isolated sound effect to play 0: Go to $42EA 1: Go to $432B, play item-get music 3: Go to $4390 (restores some audio state) 5: Go to $4335, play missile pickup music 8: Go to $43FB Eh: Go to $433F, play earthquake music FFh: $CEDE = 0, $CEDF = 0, go to $42FA Otherwise: Go to $42FA CEDF: Isolated sound effect playing If [$CEDE] = 0: 2: Go to $43C4 (set by isolated sound effect to play = 3, restores some audio state) 8: Go to $4418 Otherwise: Go to $42FA CEE4: Current tone/sweep channel sound effect CEE5: Current tone channel sound effect CEE6: Low health beep / wave channel sound effect 0: Samus' health >= 50 1: Samus' health < 20 2: Samus' health < 30 3: Samus' health < 40 4: Samus' health < 50 CEE7: Current noise channel sound effect CF00-60: CF00: Music note offset. Set to [$5F30 + ([song to play] - 1) * 2] & ~1 in $48A0 CF01: Pointer to value for $CF34/$CF36. Set to [$5F30 + ([song to play] - 1) * 2 + 1] in $48A0 CF03: Working sound channel (1/2/3/4) CF04: Set to 1 if [$CF38] != 0 in $48A0 CF05: Set to 2 if [$CF41] != 0 in $48A0 CF06: Set to 3 if [$CF4A] != 0 in $48A0 CF07: Set to 4 if [$CF53] != 0 in $48A0 CF08: Checked to mirror $CF0B/0C to $CF10/11 in $497A CF09: Pointer to wave pattern data, 10h bytes CF0B: Working sound channel sweep / enable CF0C: Working sound channel sound length / wave pattern duty CF0D: Working sound channel envelope / volume CF0E: Working sound channel frequency / noise channel polynomial counter CF0F: Working noise channel counter control CF10-23: Audio channel options (which conveniently correspond with FF10-23) CF10: Tone/sweep channel sweep CF11: Tone/sweep channel sound length / wave pattern duty CF12: Tone/sweep channel envelope CF13: Tone/sweep channel frequency CF15: Unused CF16: Tone channel sound length / wave pattern duty CF17: Tone channel envelope CF18: Tone channel frequency CF1A: Wave channel enable CF1B: Wave channel sound length CF1C: Wave channel volume CF1D: Wave channel frequency CF1F: Unused CF20: Noise channel sound length CF21: Noise channel envelope CF22: Noise channel polynomial counter CF23: Noise channel counter control CF26: Song tone/sweep channel instruction pointer CF28: Song tone channel instruction pointer CF2A: Song wave channel instruction pointer CF2C: Song noise channel instruction pointer CF2E: A 12 frame timer CF2F-37: Working song sound channel options CF2F: Instruction pointer F1 ee ss ll: For non-wave channels. Working sound channel envelope = ee, working sound channel sweep = ss, working sound channel sound length / wave pattern duty = ll F1 pppp vv: For the wave channel. Pointer to wave pattern data = pppp, working sound channel volume = vv F2 pppp: $CF01 = pppp F3 oo: Add oo to any played music notes (sets $CF00) F4 nn: Repeat from after this instruction nn times |: (sets $CF31/$CF33) F5: Repeat :| (decrements $CF31) CF31: Repeat count CF33: Repeat point CF35: Sound envelope / volume CF37: Sound length (according to song instruction F1h) CF38-40: Song tone/sweep channel options CF38: Set to [$5F30 + ([song to play] - 1) * 2 + 3] in $48A0 CF3F: Set to 1 in $48A0 CF41-49: Song tone channel options CF41: Set to [$5F30 + ([song to play] - 1) * 2 + 5] in $48A0 CF48: Set to 1 in $48A0 CF4A-52: Song wave channel options CF4A: Set to [$5F30 + ([song to play] - 1) * 2 + 7] in $48A0 CF51: Set to 1 in $48A0 CF53-5B: Song noise channel options CF53: Set to [$5F30 + ([song to play] - 1) * 2 + 9] in $48A0 CF5A: Set to 1 in $48A0 CF5C: Set to D0h by [$CEDE] == 8 (timer), sets $CF3E = $CF47 = $CF59 = $CF5D = $CF5E = [a] 0: Song play = isolated sound effect to play = 0, disable sound channels 10h: a = 13h 30h: a = 25h 70h: a = 45h, $CF07 = 0, $CF50 = $CF5F = 60h A0h: a = 65h CF5D: Set to [$CF3E] by [$CEDE] == 8 CF5E: Set to [$CF47] by [$CEDE] == 8 CF5F: Set to [$CF50] by [$CEDE] == 8 CF60: Tone channel frequency tweak. Set to 1 if [$5F30 + ([song to play] - 1) * 2] & 1 in $48A0 CF61-C1: Mirror of $CF00-60? CFC5: Backup of song playing during isolated sound effect CFC7: 1: Go to $4801 2: Go to $4846. Set when unpausing: plays unpaused sound effect Otherwise: $4819 CFC8: Flag to go to $4852, set to 40h by $4801 CFC9: Mirror of $CF10? (tone/sweep channel sweep) CFE3: Mirror of $CF09? CFE5: Low health beep / wave channel sound effect to play CFE6: Low health beep / wave channel sound effect playing CFE7: Mirror of $CFE6? CFEC: Mirror of $CFED? CFED: Audio channel output stereo flags CFEE: Quickly guessing wave pattern timer D008: Metatile top-left D009: Metatile top-right D00A: Metatile bottom-left D00B: Metatile bottom-right D00C: Samus' previous Y position D00E: Door transition direction 1: Right 2: Left 4: Up 8: Down D00F: Set to [$C423] by $2EE3, set to 1 by escaping Metroid Queen / in Metroid Queen's mouth D010: Counter for spin-jumping D011: Nothing. Only cleared D012: Value for $D060 in $31F1 D020: Samus' pose 00: Standing 01: Jumping 02: Spin-jumping 03: Running (set to 83h when turning) 04: Crouching 05: Morphball 06: Morphball jumping 07: Falling 08: Morphball falling 09: Starting to jump 0A: Starting to spin-jump 0B: Spider ball rolling 0C: Spider ball falling 0D: Spider ball jumping 0E: Spider ball 0F: Knockback 10: Morphball knockback 11: Standing bombed 12: Morphball bombed 13: Facing screen 18: Being eaten by Metroid Queen 19: In Metroid Queen's mouth 1A: Being swallowed by Metroid Queen 1B: In Metroid Queen's stomach 1C: Escaping Metroid Queen 1D: Escaped Metroid Queen D022: += 3 in $08FE during door transition D023: Direction of screen movement 10: Right 20: Left 40: Up 80: Down D027: Samus X position D029: Samus Y position D02B: Direction Samus is facing, mirrored from $D81E at save load. 0: Left 1: Right D02C: Samus turning animation counter D035: Screen right velocity D036: Screen left velocity D037: Screen up velocity D038: Screen down velocity D039: Set to 0 by load title screen D03B: Samus' Y position on screen D03C: Samus' X position on screen, checked for <= A0h in $08FE D03D: Spider ball direction 0: In air 1: On bottom-left corner of ledge 2: On top-left corner of ledge 3: On left-facing wall 4: On bottom-right corner of ledge 5: On ceiling 6: Unused 7: On meet of left-facing wall and ceiling 8: On top-right corner of ledge 9: Unused Ah: On floor Bh: On meet of left-facing wall and floor Ch: On right-facing wall Dh: On meet of right-facing wall and ceiling Eh: On meet of right-facing wall and floor D045: Samus' equipment, mirrored from $D815 at save load. 01: Bombs 02: Hi-jump 04: Screw attack 08: Space jump 10: Spring ball 20: Spider ball 40: Varia suit D046: Debug screen selector index D047: Tiles update flag (see $FFB1..B6, $2BA3, $27BA) D04D: Weapon equipped. 0: Normal 1: Ice 2: Wave 3: Spazer 4: Plasma 8: Missile D04E: Bank D050: Samus' max energy tanks, mirrored from $D817 at save load. D051: Samus' health, mirrored from $D818 at save load. D052: Samus' filled energy tanks, mirrored from $D819 at save load. D053: Samus' missiles(upper nybble tens, lower nybble ones), mirrored from $D81C at save load. D054: Samus' missiles(upper nybble thousands, lower nybble hundreds), mirrored from $D81D at save load. D055: Samus' beam. Saved to SRAM, mirrored from $D816 at save load. 0: Normal 1: Ice 2: Wave 3: Spazer 4: Plasma D056: Samus passable block threshold D057: Room sprite priority 0: Sprites over BG 1: BG over sprites D058: Bank for current room D059: Death sequence timer. Used as index into offset table for dest address in $2FE1 D064: Used in $239C as new OAM stack pointer, set to OAM stack pointer in $04DF D065: VRAM DMA bank (see $FFB1-B6, $2BA3) D066: Used in v-blank handler. Timer for fade in. Set to 40h by $0CA3, set to 2Fh by $239C when type = Ah, set to A0h by game mode Ah, set to FFh by reached the gunship D067: Used in title. Set to 01h by $0CA3 and game mode Ah D069: Enemy passable block threshold D06E: Highest OAM stack pointer D073: Two byte pointer, data for [$C215] before subtracting 21h; pointer to SRAM? Compared with F0h to enable $D09F, probably credits text D076: Used in v-blank handler. Flag to go to $5:403D; set every few frames during credits D077: Acid damage. Saved to SRAM D078: Spike damage. Saved to SRAM D079: Flag to load characters. But also used in facing screen as a flag to check if buttons are pressed D07A: Save slot option selected 0: Start 1: Clear D07B: Used in title. Y position of stars? D07C: Used in title. X position of stars? D07E: BG palette D07F: Object 0 palette D080: Object 1 palette D081: Samus' max missiles(upper nybble tens, lower nybble ones), mirrored from $D81A at save load. D082: Samus' max missiles(upper nybble thousands, lower nybble hundreds), mirrored from $D81B at save load. D083: Read in $1:7A34, adjusts sprite Y position in $1:4DDF D084: Samus' health for display, mirror of $D051/D818? D086: Samus' missiles for display, mirror of $D053/$D81C? D089: Real number of Metroids remaining D08A: Projectile passable block threshold D08B: Metroid Queen's room flag 11h: In Metroid Queen's room (set by screen transition command 8) D08D: Value for $D05D in $31F1 D08E: Index of screen transition command set. Set to [$4300 + ([screen Y position high] * 10h + [screen X position high]) * 2] & ~800h by set up door transition D090: Metroid Queen eating pose Sets Samus pose = escaping Metroid Queen when 7, checked for 5/20h and set to 6 in in Metroid Queen's mouth 0: Otherwise 1: Samus entering mouth 2: Mouth closing 3: Mouth closed 5: Samus escaping mouth 6: Swallowing Samus 7: 8: Samus escaping stomach 10h: Paralysed (can enter mouth) 20h: 22h: Dying D091: Set to 3 in $8:7EBC if killed a target number of Metroids or 1 if only Metroid Queen is remaining D092: Song for room D096: Metroids remaining shuffle timer D097: Index for $5:5620 jump table (first call in credits) D098: In-game timer, minutes D099: In-game timer, hours D09A: Number of Metroids remaining D09B: Fade in timer D09E: Checked and cleared in $2:4000, value for $FFC9 in $0C37 D09F: Flag to display in-game time in credits D0A0: Debug flag D0A2: In-game timer, 256-frame periods (roughly 14ths of a minute) D0A3: Save slot D0A4: Show clear save slot option flag D0A7: Metroids remaining in area D700-3F: Screen transition commands D800-25: Save data. Data loaded from $1:4E64-89 by game mode Bh, loaded from $A008-2D + save slot * 40h by game mode Ch D800: Samus' Y position D802: Samus' X position D804: Screen Y position D806: Screen X position D808: Enemy tiles source address (2 bytes) D80A: Background tiles source bank D80B: Background tiles source address (2 bytes) D80D: Metatile definitions source address (bank 8, 2 bytes) D80F: Source address of data for $DC00-FF (bank 8, 2 bytes) D811: Bank for current room D812: Samus passable block threshold (>= this tile index is passable, < is impassible) D813: Enemy passable block threshold D814: Projectile passable block threshold D815: Samus' equipment at save load. D816: Samus' beam at save load. D817: Samus' max energy tanks at save load. D818: Samus' health at save load. D819: Samus' filled energy tanks at save load. D81A: Samus' max missiles at save load. Upper nybble tens, lower nybble ones. D81B: Samus' max missiles at save load. Upper nybble thousands, lower nybble hundreds. D81C: Samus' missiles at save load. Upper nybble tens, lower nybble ones. D81D: Samus' missiles at save load. Upper nybble thousands, lower nybble hundreds. D81E: Direction Samus is facing at save load. D81F: Acid damage D820: Spike damage D821: Real number of Metroids remaining D822: Song for room D823: In-game timer, minutes D824: In-game timer, hours D825: Number of Metroids remaining D900-FF: 10h byte slots? The first byte of which each is cleared when saving DA00-DBFF: Metatile definitions DC00-FF: Tile properties 1: Viscous. Reduces jumping and detaches spider ball on movement. Also causes morph ball sound effect glitch. 2: Jump-through block. Passable when jumping, impassable in all other states (in all directions). 4: Fall-through block. Passable when falling, impassable in all other states (in all directions). 8: Spike 10h: Acid 20h: Destructible by shot/bomb 40h: Destructible by bomb 80h: Save pillar DD00-FF: Projectile RAM DE00-FF: Metatile update entries + 0: Dest. address. $0000 terminates update + 2: Top-left tile + 3: Top-right tile + 4: Bottom-left tile + 5: Bottom-right tile DF00-FF: Stack
FF80: Buttons 01: A 02: B 04: Select 08: Start 10: Right 20: Left 40: Up 80: Down FF81: New buttons FF82: V-blank handled flag FF8D: OAM stack pointer FF97: Frame counter FF98: Sprite tile number (see $5:4015). Mirror of sprite Y position (see $30BB). Door scroll flags (see $08FE): [$4200 + [screen Y position, screen] * 16 + [screen X position, screen]] FF99: Two sprite tile numbers (see $5:4000). Mirror of sprite X position (see $30BB). Door thing (see $08FE): [Samus' Y position] - [$FFC8] + 60h FF9B: Game mode 0: Boot 1: Title screen 2: Loading save 2 3: Loading save 3 4: In-game 5: Dead 6: Dying 7: Game over 8: Paused 9: Save to SRAM Ah: Unused Bh: Start new game Ch: Load from save Dh: RET Eh: RET Fh: Unused. Identical to 7, set by game mode Ah 10h: Unused. Game cleared 11h: Unused. Functionally identical to 7, set by game mode 10h 12h: Reached the gunship 13h: Credits FFA0-A9: OAM DMA routine FFAA: VRAM tilemap metatile update address. $FFAA = $9800 + ([row block to update] * 32 + [column block to update]) * 2 FFAC: Index of screen for metatile update. $FFAC = [row screen to update] * 16 + [column screen to update] FFAD: Index of block for metatile update. $FFAD = [row block to update] * 16 + [column block to update] FFAE: Number of blocks to update FFAF: Stack pointer for metatile update entries FFB1: VRAM DMA source address FFB3: VRAM DMA dest address, also source offset from $CE20 when [$D08C] is set FFB5: VRAM DMA size FFB7-BB: Energy tank graphics, other stuff too though FFB7: Offset for interval for [$FF98] in $30EA FFB8: Offset for interval for [$FF99] in $30EA FFB9: Table index for offset data in $30EA FFBA: Start of interval for [$FF98] in $30EA FFBB: End of interval for [$FF98] in $30EA FFBC: Start of interval for [$FF99] in $30EA FFBD: End of interval for [$FF99] in $30EA FFBF: Flags to negate values in $30EA FFC0: Samus' Y position FFC2: Samus' X position FFC4: Sprite Y position (see $5:4015) FFC5: Sprite X position (see $5:4015) FFC6: Sprite set FFC7: Sprite attributes (see $5:4015) FFC8: Screen Y position FFCA: Screen X position FFCC: Row to update (in pixels) FFCE: Column to update (in pixels) FFE0-FFF5: Used by active enemies (??) FFFE: Counts every other in-game frame