ROM REVERSE ENGINEERING

Battle City (Namco, 1985) — Famicom / NES

ROM IDENTIFICATION

FieldValue
Filebattlecity_famicom.nes (BattleCity (Japan).nes)
FormatiNES
CPUMOS 6502 (2A03)
Mapper0 (NROM-128) — 16 KB PRG mirrored at $8000–$BFFF and $C000–$FFFF
CHR-ROM1 × 8 KB — 512 tiles, fixed pattern table
MirroringHorizontal
VectorsRESET = $C070   NMI = $D400   IRQ = $C070
File size24,592 bytes (16-byte iNES header + 16 KB PRG + 8 KB CHR)
A separate VS System ROM (mapper 99, 32 KB PRG) also exists — the arcade board ran a modified version with coin/credit handling, DIP-switch lives, and palette remapping. This analysis covers the Famicom version.

MEMORY MAP

CPU RangeSizeContents
$0000–$00FF256 BZero-page — heavily used for game state, entity coords, timers
$0100–$01FF256 BStack
$0200–$02FF256 BOAM shadow — 64 sprite entries (Y, tile, attr, X)
$0300–$03FF256 BGame state: bullet slots, SFX flags, entity status
$0400–$05FF512 BNametable RAM shadow — 30 rows × 32 cols BG tile indices
$8000–$FFFF16 KBPRG-ROM (mirrored — $8000 = $C000)
PPU $0000–$0FFF4 KBCHR PT0 — background tiles
PPU $1000–$1FFF4 KBCHR PT1 — sprite tiles (8×16 mode)

SCREEN LAYOUT

The PPU outputs 256×240 pixels (NTSC). Real CRT TVs hid ~8 px top and bottom (overscan); the web port replicates this crop.

RegionPixelsTiles
Top bordery 0–152 rows — gray border tile $FC
Left borderx 0–152 cols — gray border
Playfieldx 16–223, y 16–22326×26 CHR tiles = 13×13 metatiles (16 px each)
Right HUDx 224–2554 cols — enemy tank count, lives, stage#
Bottom bordery 224–2392 rows — gray border

KEY SUBSYSTEMS

Stage data — $F000 LoadStageData / $F07A StageDataTable

Entity system

Movement — $DD30 MoveGridSnap

AI — $DC7C EntityMovementAI

Bullet terrain collision — $E604 BulletTerrainCollision

Power-ups — $EA7E

CHR / graphics

Score & HUD

TOOLS BUILT

ScriptPurpose
instruction_set.pyComplete 6502 opcode database with cycle counts and addressing modes
dis.pyTargeted disassembler — reads labels.csv + comments.csv, annotates output inline
extract_tiles.pyDecode 2bpp CHR-ROM → PNG tile sheet (32×16 grid, 9px cells)
extract_level_maps.pyDecode nibble-encoded stage data → tile type arrays
render_screen.pyComposite full screens from nametable + CHR + palette data
search_bytes.pyByte-pattern search with context and optional inline disassembly
xref.pyFind all call/jump/load references to a given address
decode_tables.pyFlat and two-level pointer table decoder