# Donkey Kong (JU) — Pass 2/3 Complete, Promoted ROM: `Donkey Kong (JU).nes` (24,592 bytes, iNES). Status: **Pass 2/3 complete, promoted to top level 2026-10-19 — whole ROM rebuilds byte-identically.** `prg.s` contains a classified disassembly with 6,014 instructions (76.3% code / 12,505 bytes), **1,145 label definitions and zero `Label_` residue**, and **175 named data tables** (see the Pass 3 data-table inventory below). `make` verifies header + PRG + CHR against `rom.nes` (a relative symlink that survives the `git mv`). This is the Famicom/NES conversion of Nintendo's 1981 arcade *Donkey Kong* (the cement-factory stage was dropped). Phase 1 is the girder stage with the rolling barrels, phase 2 (the factory) was cut and its slot is reused by the title screen, phase 3 is the 75M conveyor-belt stage with moving platforms, and phase 4 is the 100M rivet stage with the flame enemies ("fireballs"). **Relationship note:** separate title from the already-disassembled `Donkey Kong Jr. (JU)` and `Donkey Kong 3 (JUE)` — do not reuse their symbols. ## Power-on flow analysis Derived from the disassembly by `_tools/derive_poweron.py`; the call graph is walked from the reset entry. **RESET** is at `$C79E` (`Reset`). The CPU comes here out of reset with the PPU and APU in their power-on state and the zero page and RAM uninitialised. The reset path calls: | Address | Routine | |---------|---------| | `$C7A8` | `SubCC7A8_OnZero` (falls through) | | `$C7B9` | `SubCC7B9_OnNonzero` (falls through) | | `$C7E7` | `InitPPURegisters` | | `$C7E1` | `MainGameLoop` (falls through) | | `$CBAE` | `ClearSpritePatterns` | | `$CBB7` | `HideBackgroundAndClearNametable` | | `$F4ED` | `UpdateRandomSeed` | | `$C7E1` | `MainGameLoop` | | `$F092` | `SetSpritePatternParams` | | `$D19A` | `HideBackground` | | `$F1B4` | `ClearNametable` | **NMI** is at `$C85F` (`NmiHandler`). It is the per-frame handler; what it calls: | Address | Routine | |---------|---------| | `$F228` | `FlushPpuBuffer` | | `$F50E` | `ReadControllers` | | `$FA48` | `UpdateSoundEngine` | | `$CE7C` | `ClearApuFrameCounterWhenSpriteActive` | | `$C8D7` | `SubCC8D7_Loop` | **IRQ** is at `$FFF0` (`IrqHandler`) - a different address from RESET. ## ROM Facts | Property | Value | |----------|-------| | Mapper | 0 (NROM) — from the iNES header | | PRG | 16 KB (header claims map at CPU $C000–$FFFF) | | CHR | 8 KB | | Mirroring | Horizontal | | Battery-backed flag | clear | | ROM SHA-256 | `f9f026fd3560eeb03be9f6d1efa329b4c71d562caf06d4a5a691e5342f8da8e6` | | PRG SHA-256 | `2952648e8a6eea65b7f388af8fce9ef33a9cb07178835fea6674db75d2623c49` | ## Interrupt Vectors (taken from PRG $3FFA–$3FFF) | Vector | Target | Note | |--------|--------|------| | NMI | `$C85F` | per-frame heartbeat | | RESET | `$C79E` | non-$C000 entry, like `Donkey Kong Jr. (JU)` | | IRQ | `$FFF0` | lands in the vector-page padding — unused placeholder | ## Project folder contents | File | Purpose | |------|---------| | `rom.nes` | relative symlink → `../Donkey Kong (JU).nes` (space-free link name, per convention) | | `prg.bin` / `header.bin` / `chr.bin` | split image, produced by `_tools/splitnes.py` | | `header.s` / `chr.s` | one-line `.incbin` of `header.bin` / `chr.bin` (added at promotion) | | `prg.s` | Pass 1/2/3: classified code/data split, 6,014 instructions, 1,145 labels (zero `Label_` residue), 173 named data tables, audit comments on every emission | | `symbols.inc` | shared NES hardware constants (PPU/APU/controller) | | `locals.inc` | 145 zero-page slot definitions with neutral `ZpXX` names (behavioral naming not yet assigned) | | `linker.cfg` | HEADER (16 bytes) + PRG at $C000 (16 KB) + CHR (8 KB) | | `Makefile` | links `reconstructed.nes` (header + PRG + CHR) and `cmp`s it against `rom.nes` | | `reconstructed.nes` | build output from the last verified build | | `dk_full_map.tsv` | complete Pass 2 label map (919 applied rows) plus 407 `zp` proposals that were never applied | | `dk_label_map.tsv` | superseded first-draft map (219 label rows), kept for provenance | | `dk_gameplay.cdl` | Mesen Code-Data-Logger capture used to re-split Pass 1 (2026-10-21) | ## Build ```bash cd "NROM/Donkey Kong (JU)" make # → cmp reconstructed.nes rom.nes → "Byte-identical ROM verified." ``` ## Pass 2 Details (2026-10-19) All **919** remaining address-derived `Label_XXXX` definitions were replaced; `prg.s` now carries **1,015** labels and **zero `Label_` residue**. - **319 of the 919** were routine entry points (`jsr`/`jmp` targets): - **102** were named from observed behaviour — e.g. `LoadSpriteInitPointerToZp00` ($C807), `CopyVramDataToBuffer` ($CBDF), `UpdateObjectListZp5D` ($DA16), `CheckSpriteListCollision` ($D8AD), `UpdateRandomSeed` ($F4ED), `ReadControllers` ($F50E), `UpdateSoundEngine` ($FA48). - **217** stayed address-based as `SubC` (`SubCC24`, `SubCE130`, …) — honest residue where the body is too context-dependent to name without guessing. This matches sibling practice (`Golf (JU)`: 108, `Mario Bros (JU)`: 223). **All 217 of these were named on 2026-10-21** — see "Entry-point naming" below. - The **77** entry points already named in earlier passes were left untouched. - **600** internal branch targets were named `_Block` / `_Block_n` in address order within their owning routine (the `Donkey Kong Jr. (JU)` / `Balloon Fight (JU)` convention). Ownership is control-flow containment: an internal label is attributed to the routine whose body actually reaches it, not merely the nearest preceding entry (this matters for loops that physically precede their own entry, e.g. `FlushPpuBuffer_Block` at $F1EC under the entry at $F228). - Two name collisions in the raw proposals were disambiguated by the indexing zero-page slot — `UpdateObjectListZp5D`/`DispatchObjectStateZp5E` ($DA16/$DA4C, index Zp5D/Zp5E) versus `UpdateObjectListZpAE`/`DispatchObjectStateZpAF` ($E1E9/$E250, index ZpAE/ZpAF). - `jsr`/`jmp` operands stay **numeric** (`jsr $F228`), matching `Wild Gunman (U)`; only branch operands are symbolic, so the call graph is read from the labels. - Applied with `_tools/pass2.py apply` (919 definitions + 2,622 references rewritten, comments re-aligned to the file's column convention); `make` still prints **byte-identical** — labels only, no byte or audit-comment content change. - **Residue:** the 145 zero-page slots in `locals.inc` (neutral `ZpXX`), and the 407 unapplied `zp` proposals in `dk_full_map.tsv`. ## Entry-point naming (2026-10-21) The 358 address-derived entry points (`SubC`) that the Pass 2 map left behind are now named. Every one of them is a `jsr`/`jmp` target, and every one now carries a name that says what the code does **in Donkey Kong**, taken from the routine's own body and from the caller that reaches it: | Old | New | What the code shows | |-----|-----|----------------------| | `SubCC7E1` | `MainGameLoop` | `jsr UpdateRandomSeed` / `jmp` to itself - the endless frame loop | | `SubCC7E7` | `InitPPURegisters` | writes `$10` to PPUCTRL, `$06` to PPUMASK and zeroes both scrolls | | `SubCCA30` | `UpdateGameObjects` | the per-frame step called from the NMI handler: updates the timers, then dispatches on the game-state byte | | `SubCCBAE` | `ClearSpritePatterns` | `lda #$00 / sta Zp04 / lda #$FF / jmp SetSpritePatternParams` - hides every sprite | | `SubCCBB7` | `HideBackgroundAndClearNametable` | clears PPUMASK bit 3 and then calls `ClearNametable` | | `SubCCBBD` | `QueueHudCounterWrite` | queues a byte at VRAM `$20B5` indexed by the HUD counter | | `SubCC807` | `LoadSpriteInitPointerToZp00` | loads a 16-bit pointer out of the Kong-frame table and flushes the PPU buffer | | `SubCC815` | `LoadObjectPointerToZp02AndDraw` | loads a VRAM-stream pointer and calls `DrawVramBlock` | | `SubCC9B1` | `InitGameState` | clears the per-player RAM blocks and sets up the two players | | `SubCD28B` | `GrabLadder` | reads `Phase25MLadderTable`/`Phase25MLadderHitboxes` and tests Jumpman against the ladder box | | `SubCEB89` | `DrawKongHitChestLeftHand` | draws the `Tilemap_DonkeyKong_HitChestLeftHand` stream | | `SubCEBA1` | `DrawKongSideToss` | draws the `Tilemap_DonkeyKong_SideToss` stream | | `SubCF23C` | `DrawLevelBlocks` | redraws the level's block graphics | | `SubCF1B4` | `ClearNametable` | clears a nametable | | `SubCF2D7` | `DrawVramBlock` | copies a VRAM byte stream to the screen | | `SubCF4AC` | `UpdateTimers` | the frame timer | | `SubCF50E` | `ReadControllers` | reads the joypads | | `SubCFA48` | `UpdateSoundEngine` | the APU driver's frame step | | `SubCFBF2` | `ProcessSoundCommands` | the sound command queue | | `SubCFD67` | `InitSoundEffect` | starts a sound effect | **Residue: 0 entry points remain address-derived.** The names cover the whole `jsr`/`jmp` target set, so every call in the file now names a routine whose role the dump establishes. What is *not* covered is the separate set of internal branch labels of the form `SubC_` (654 of them, e.g. `SubCC8A5_Loop`). Those are branch targets rather than entry points, and the project map `dk_full_map.tsv` already carries a semantic name for 602 of them; applying that map to the branch labels is the next piece of work. ## Pass 3 data-table inventory The tracer leaves **eight** data blocks in `prg.s`; each is listed below, and the big `$C000-$C79D` block is broken down into the individual tables it holds. Every row says what the bytes *are* and which instruction of this dump reads them. Rows whose "Read by" column names a pointer table are reached **indirectly**: the pointer table itself is named and has its own row with the instruction that reads it. The byte-level evidence for every structure below is in the dump itself: the records are fixed-size, the terminators (`$FE`) are explicit, and the pointer tables resolve to addresses inside the same block. ### `$C000-$C79D` — the phase and level data block (1950 bytes) | Address | Size | Name | Structure | Read by | |---------|------|------|-----------|---------| | `$C000-$C00F` | 16 | `ScoreLabelVramPositions` | 4 x 4-byte records `[VRAM high][VRAM low][attribute][unused]`: the nametable addresses of the TOP, 1P, 2P and BONUS labels ($2070, $2064, $2078, $20B7) | `lda $C000,y` at `$F256` — the routine at `$F24E` walks the block as a 4-byte record table, index = label number x 4 | | `$C010-$C013` | 4 | `ScoreLabelVramSpareRecord` | a fifth record of the same 4-byte layout ($20BC); the routine can address it with index 4, which only bit 0 of the mask at `Zp00` selects | `lda $C000,y` at `$F256` (index 4 only) | | `$C014-$C027` | 20 | `DemoInputScript` | 20 x 8-bit controller/command bytes driving the attract-mode demo (`$01`=right, `$02`=left, `$08`=up, `$05`=jump, `$00`=no input) | `lda $C014,x` at `$EC1F` (index = the demo step counter `$050E`) | | `$C028-$C03B` | 20 | `DemoInputTimings` | 20 x 8-bit frame counts, one per demo step: how long each entry of `DemoInputScript` is held | `lda $C028,x` at `$EC19` | | `$C03C-$C043` | 8 | `DonkeyKongFramePointerTable` | 4 x 16-bit LE pointers to Kong's sprite tilemaps (side-toss `$C63E`, stationary `$C657`, "remove II" `$C6E1`, ending tile-erase `$C760`) | `lda $C03C,x` / `lda $C03D,x` at `$C816`/`$C81B`, `$C824`/`$C829`, `$C832`/`$C837`, `$C848`/`$C84D`, `$C854`/`$C859` | | `$C044-$C05B` | 24 | `EndingSequencePointerTable` | 9 x 16-bit LE pointers to the ending cutscene's VRAM streams and to Kong's defeated frames | `lda $C044,x` / `lda $C045,x` at `$C83C`/`$C841` | | `$C05C-$C05D` | 2 | - | a 16-bit pointer into RAM at `$0460`; the table it belongs to is filled in by the unreached routine at `$D650` and is never read | not referenced by any instruction | | `$C05E-$C063` | 6 | `PhaseHitboxPointerTable` | 3 x 16-bit LE pointers to the 25M platform, 25M gap and broken-ladder hitboxes | reached indirectly through `PhaseTilemapPointerTable` at `$C066`, which no instruction reads | | `$C066-$C08B` | 38 | `PhaseTilemapPointerTable` | 19 x 16-bit LE pointers to the per-phase hitbox and tilemap streams (moving-platform hitbox, Jumpman's hitboxes, hammer hitbox, barrel bounce tables, Kong's frames, the palettes, the "Player I/II" and "GAME OVER" screens) | not referenced by any instruction | | `$C08C-$C0BB` | 48 | `Phase25MPlatformCollisionTable` | 8 x 6-byte platform descriptors `[base X][base Y][collision-table offset][X step between elevations][number of elevation bits][terminator]`; the collision data of the 25M girder stage | `lda $C08C,x` at `$D940`, `$D946`, `$D94C`, `$D959`, `$D95F`, `$D97B` | | `$C0BC-$C0C2` | 7 | `Phase25MPlatformYPositions` | 7 x 8-bit screen Y positions, one per 25M platform (top to bottom); `$FF` marks the lowest platform | reached through `StagePlatformYPositionPointers` at `$C493` (read by `lda $C493,x` at `$E01F`) | | `$C0C3-$C0CA` | 8 | `Phase25MPlatformHitboxes` | 2 x 4-byte hitboxes `[X offset][Y offset][width][height]`: the extended part of the lowest 25M platform ($80 pixels wide) and the raised platform bits ($18 pixels) | reached through `PhasePlatformHitboxPointerTable` at `$C473` (read by `lda $C473,x` at `$D307`) | | `$C0CB-$C0CE` | 4 | - | two 2-byte hitbox fragments for two-tile-wide elevations; the platform code uses the wider hitboxes at `$C0C3` instead | not referenced by any instruction | | `$C0CF-$C0DE` | 16 | `Phase25MPlatformEndAreas` | 5 x 3-byte records `[X][Y][collision-table offset]` for the ledge ends Jumpman can fall off, plus the `$FE` terminator | reached through `PhasePlatformPointerTable` at `$C46B` (read by `lda $C46B,x` at `$D2FD`) | | `$C0DF-$C0E2` | 4 | `Phase25MFallAreaHitbox` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` for the fall areas | reached through `PhaseHitboxPointerTable` at `$C05E` | | `$C0E3-$C10A` | 40 | `Phase25MLadderTable` | 13 x 3-byte records `[X][Y][collision-table offset]` for every ladder of the 25M stage, plus the `$FE` terminator | reached through `PhaseLadderTablePointers` at `$C47B` (read by `lda $C47B,x` at `$D2A0`) | | `$C10B-$C126` | 28 | `Phase25MLadderHitboxes` | 7 x 4-byte ladder hitboxes `[X offset][Y offset][width][height]` (every ladder is 8 pixels wide) | reached through `PhaseLadderHitboxPointers` at `$C483` (read by `lda $C483,x` at `$D2AA`) | | `$C127-$C142` | 28 | `Phase25MLadderTopPositions` | 9 x 3-byte records `[X][Y][unused]` for the top of each climbable ladder, plus the `$FE` terminator (broken ladders have no top) | reached through `PhaseLadderTopPointers` at `$C48B` (read by `lda $C48B,x` at `$D519`) | | `$C143-$C146` | 4 | `Phase25MLadderTopHitbox` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` at the top of a ladder | reached through `PhaseLadderTopPointers` at `$C48B` | | `$C147-$C154` | 14 | `JumpmanClimbOntoPlatformFrames` | 7 x 2-byte sprite frame pairs used for Jumpman's animation as he climbs over the top of a platform | `lda $C147,x` at `$D3D6`, `$D47C` | | `$C155-$C158` | 4 | - | four spare frames of the same 2-byte shape; the animation never selects them | not referenced by any instruction | | `$C159-$C15E` | 6 | `JumpmanLadderClimbFrames` | 2 x 3-byte sprite frame triplets used while Jumpman climbs a ladder | `lda $C159,x` at `$D3FF`, `$D4A5` | | `$C15F-$C160` | 2 | - | two spare bytes of the same shape | not referenced by any instruction | | `$C161-$C16D` | 13 | `BrokenLadderTable` | 4 x 3-byte records `[X][Y][unused]` for the broken ladders of the 25M stage, plus the `$FE` terminator | reached through `PhaseLadderTablePointers` at `$C47B` | | `$C16E-$C171` | 4 | `BrokenLadderHitbox` | 1 x 4-byte hitbox `[left][top][right][bottom]` shared by every broken ladder | reached through `PhaseHitboxPointerTable` at `$C05E` | | `$C172-$C176` | 5 | `BarrelLadderDropYPositions` | 5 x 8-bit Y positions a barrel must reach when it rolls down the first ladder it can take | `ldy $C172,x` at `$E0F6` | | `$C177-$C17B` | 5 | `BarrelLadderDropXPositions` | 5 x 8-bit X positions of those ladders | `cmp $C177,x` at `$E0F9` | | `$C17C-$C180` | 5 | `BarrelLadderDropYPositionsAlt` | 5 x 8-bit Y positions for the second ladder check | `ldy $C17C,x` at `$E0FE` | | `$C181-$C185` | 5 | `BarrelLadderDropXPositionsAlt` | 5 x 8-bit X positions for the second ladder check | `cmp $C181,x` at `$E101` | | `$C186-$C189` | 4 | `JumpmanHitboxDimensions` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` for Jumpman standing on a platform | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C18A-$C18D` | 4 | - | a 4-byte hitbox one pixel higher than `JumpmanHitboxDimensions`; the ROM always uses the latter | not referenced by any instruction | | `$C18E-$C191` | 4 | `JumpmanAirborneHitboxDimensions` | 1 x 4-byte hitbox for Jumpman while he is jumping or falling (2 pixels higher than the grounded one) | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C192-$C1A1` | 16 | - | four 4-byte hitbox-shaped records (`$C192`, `$C196`, `$C19A`, `$C19E`); only the unreferenced pointer table at `$C066` points at three of them, and the fourth is pointed at by nothing | not referenced by any instruction | | `$C1A2-$C1A7` | 6 | `JumpmanHammerWalkFrames` | 6 x 8-bit sprite frames: Jumpman's walk/stand cycle while he carries the hammer | `lda $C1A2,x` at `$D756` | | `$C1A8-$C1AF` | 8 | `HammerPickupPlatformHeights` | 4 x 2-byte pairs `[platform height low][platform height high]`; one pair per phase says at which platform height the hammer lies (phase 2 is unused, phase 3 has no hammer) | `cmp $C1A8,x` at `$D83B`, `$D841` | | `$C1B0-$C1B3` | 4 | `HammerPickupHitbox` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` of the 8x8 hammer | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C1B4-$C1BB` | 8 | `ScreenBoundaryPositions` | 4 x 2-byte pairs `[left X][right X]`: the walkable X range of each phase | `lda $C1B4,x` at `$D9A2`, `$D9B5` | | `$C1BC-$C1C3` | 8 | `PowerOfTwoValues` | 8 x 8-bit values `$01,$02,$04,$08,$10,$20,$40,$80`: the single-bit masks the entity code ORs into its flag byte | `lda $C1BC,x` at `$D9FE`, `$DA0A`, `$E000`, `$E00C`, `$E81E`, `$E82A`, `$EAB7`, `$EAC3` | | `$C1C4-$C1CC` | 9 | `Phase25MPlatformShiftXPositions` | 9 x 8-bit X positions of the 25M platforms' left edges, used to decide whether a barrel or a flame enemy climbs up or down an elevation | `lda $C1C4,x` at `$E06A`, `$E07B`, `$E603`, `$E611` | | `$C1CD-$C1CE` | 2 | `BarrelDropEdgeXPositions` | 2 x 8-bit X positions where a barrel that reached no ladder drops to the platform below | `lda $C1CD,x` at `$E0A1` | | `$C1CF-$C1D4` | 6 | `FallingBarrelLandingYPositions` | 6 x 8-bit Y positions a falling barrel checks to find the platform it lands on, `$FE` = end | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C1D5-$C1DA` | 6 | `FallingBarrelBounceYPositions` | 6 x 8-bit Y positions a barrel tossed straight down bounces off, `$FE` = end | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C1DB-$C1E0` | 6 | - | the same shape of table for the diagonal bounce pattern, which this ROM does not use | not referenced by any instruction | | `$C1E1-$C1E6` | 6 | `FallingBarrelBounceYPositionsAlt` | 6 x 8-bit Y positions a barrel tossed left or right bounces off, `$FE` = end | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C1E7-$C1EA` | 4 | - | a 4-byte record; only the unreferenced pointer table at `$C066` points at it | not referenced by any instruction | | `$C1EB-$C1EB` | 1 | `BarrelBounceOffset` | a single byte, `$19`: the Y offset applied to a bouncing barrel | `lda $C1EB` at `$DFA8` | | `$C1EC-$C1F5` | 10 | `EnemyDestructionFrames` | 10 x 8-bit sprite frames for the explosion that plays when the hammer destroys a barrel or a flame enemy | `lda $C1EC,x` at `$EE3F` | | `$C1F6-$C1F9` | 4 | `MaxFlameEnemiesPerPhase` | 4 x 8-bit maxima (2 in 25M and 75M, 4 in the unused 50M and in 100M) | `cmp $C1F6,x` at `$E22F`, `$ED4F`, `$EDA5` | | `$C1FA-$C1FC` | 3 | `PhaseCompletePlatformIndex` | 3 x 8-bit platform indices: the platform Jumpman must reach to finish the phase (phase 2 is unused) | `lda $C1FA,x` at `$D05B` | | `$C1FD-$C1FE` | 2 | `MaxEntityCount` | 2 x 8-bit maxima for the number of entities the game will process at once | `cmp $C1FD,x` at `$EC9F` | | `$C1FF-$C202` | 4 | `SpringboardSpawnXPositions` | 4 x 8-bit X positions a springboard can appear at | `lda $C1FF,x` at `$EA3D` | | `$C203-$C206` | 4 | - | four spare X positions of the same shape | not referenced by any instruction | | `$C207-$C20A` | 4 | `InitialBonusScoreHundreds` | 4 x 8-bit starting bonus values in hundreds (5000, 6000, 7000, 8000) | `lda $C207,y` at `$CB9B` | | `$C20B-$C20B` | 1 | - | a single byte, `$90`: the unused fifth bonus value | not referenced by any instruction | | `$C20C-$C24B` | 64 | `Phase75MPlatformTable` | 21 x 3-byte records `[X][Y][collision-table offset]` for the 75M conveyor-belt stage's platforms, plus the `$FE` terminator | reached through `PhasePlatformPointerTable` at `$C46B`, `PhaseLadderTablePointers` at `$C47B` and `StagePlatformYPositionPointers` at `$C493` | | `$C24C-$C251` | 6 | `Phase75MPlatformYPositions` | 6 x 8-bit Y positions of the 75M platforms, `$FF` = lowest | reached through `StagePlatformYPositionPointers` at `$C493` | | `$C252-$C26D` | 28 | `Phase75MPlatformHitboxes` | 7 x 4-byte hitboxes `[X offset][Y offset][width][height]`, one per 75M platform | reached through `PhasePlatformHitboxPointerTable` at `$C473` | | `$C26E-$C28C` | 31 | `Phase75MLadderTable` | 10 x 3-byte records `[X][Y][collision-table offset]` for the 75M ladders, plus the `$FE` terminator | reached through `PhaseLadderTablePointers` at `$C47B` | | `$C28D-$C2A4` | 24 | `Phase75MLadderHitboxes` | 6 x 4-byte ladder hitboxes | reached through `PhaseLadderHitboxPointers` at `$C483` | | `$C2A5-$C2C3` | 31 | `Phase75MLadderTopPositions` | 10 x 3-byte records `[X][Y][unused]` for the tops of the 75M ladders, plus the `$FE` terminator | reached through `PhaseLadderTopPointers` at `$C48B` | | `$C2C4-$C2C7` | 4 | - | two 2-byte hitbox fragments; the moving platforms use the hitbox at `$C2C8` | not referenced by any instruction | | `$C2C8-$C2CB` | 4 | `MovingPlatformHitbox` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` of the 75M moving platforms (18 pixels wide, 1 pixel high) | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C2CC-$C2D1` | 6 | `MovingPlatformOamSlots` | 6 x 8-bit OAM slot indices, one per moving platform | `ldy $C2CC,x` at `$D336`, `$E86A`, `$E8C4`, `$E91F`, `$E94C` | | `$C2D2-$C2D6` | 5 | `Phase75MFlameLadderIndexRanges` | 5 x 8-bit values: the ladder indices a flame enemy may use on each 75M platform (the first byte is a spare) | reached through `PhaseFlameLadderIndexPointers` at `$C49D` | | `$C2D7-$C2D7` | 1 | - | a single spare byte | not referenced by any instruction | | `$C2D8-$C2EF` | 24 | `Phase75MFlameLadderData` | 8 x 3-byte records `[ladder X][ladder end Y][state to enter]`; the state byte selects the flame enemy's ladder-up or ladder-down state | reached through `PhaseFlameLadderDataPointers` at `$C4A3` | | `$C2F0-$C2FF` | 16 | `Phase100MPlatformTable` | 5 x 3-byte records `[X][Y][collision-table offset]` for the 100M rivet stage's platforms, plus the `$FE` terminator | reached through `PhasePlatformPointerTable` at `$C46B` | | `$C300-$C305` | 6 | `Phase100MPlatformYPositions` | 6 x 8-bit Y positions of the 100M platforms, `$FF` = lowest | reached through `StagePlatformYPositionPointers` at `$C493` | | `$C306-$C315` | 16 | `Phase100MPlatformHitboxes` | 4 x 4-byte hitboxes, one per 100M platform | reached through `PhasePlatformHitboxPointerTable` at `$C473` | | `$C316-$C340` | 43 | `Phase100MLadderTable` | 14 x 3-byte records `[X][Y][collision-table offset]` for the 100M ladders, plus the `$FE` terminator | reached through `PhaseLadderTablePointers` at `$C47B` | | `$C341-$C348` | 8 | `Phase100MLadderHitboxes` | 2 x 4-byte ladder hitboxes (the 100M ladders come in only two lengths) | reached through `PhaseLadderHitboxPointers` at `$C483` | | `$C349-$C373` | 43 | `Phase100MLadderTopPositions` | 14 x 3-byte records `[X][Y][unused]` for the 100M ladder tops, plus the `$FE` terminator | reached through `PhaseLadderTopPointers` at `$C48B` | | `$C374-$C379` | 6 | `Phase100MFlameLadderIndexRanges` | 6 x 8-bit ladder-index bounds for the 100M platforms | reached through `PhaseFlameLadderIndexPointers` at `$C49D` | | `$C37A-$C3CD` | 84 | `Phase100MFlameLadderData` | 28 x 3-byte records `[ladder X][ladder end Y][state to enter]` for the 100M stage's flame enemies | reached through `PhaseFlameLadderDataPointers` at `$C4A3` | | `$C3CE-$C3DD` | 16 | `Phase100MFlameSpawnPositions` | 8 x 2-byte pairs `[X][Y]`: where a flame enemy appears in the 100M stage | `lda $C3CE,x` at `$E57D`, `lda $C3CF,x` at `$E582` | | `$C3DE-$C3E1` | 2 | `Phase100MGapEdgeXPositions` | 2 x 8-bit X positions of the gaps in the 100M platforms that the flame enemies must not walk off | `lda $C3DE,y` at `$E789`, `lda $C3DF,y` at `$E796` | | `$C3E2-$C3E5` | 4 | `FlameEnemySpeedThresholds` | 2 x 2-byte pairs `[X threshold][Y threshold]`: the horizontal and vertical speed a flame enemy gets | `cmp $C3E2,x` at `$E39D`, `cmp $C3E4,x` at `$E3A2` | | `$C3E6-$C3E7` | 2 | `Phase25MFlameRightLimit` | 2 x 8-bit X limits for the flame enemies on the second 25M platform | `cmp $C3E6,y` at `$E6ED` | | `$C3E8-$C3E9` | 2 | `Phase25MFlameLeftLimit` | 2 x 8-bit X limits for the flame enemies on the lowest 25M platform | `cmp $C3E8,y` at `$E6F5` | | `$C3EA-$C3EB` | 2 | `Phase75MFlameLeftLimit` | 2 x 8-bit X limits: 75M platform level 2, left platform | `cmp $C3EA,y` at `$E70C` | | `$C3EC-$C3ED` | 2 | `Phase75MFlameRightLimit` | 2 x 8-bit X limits: 75M platform level 2, right platform | `cmp $C3EC,y` at `$E711` | | `$C3EE-$C3EF` | 2 | `Phase75MFlameLowerLeftLimit` | 2 x 8-bit X limits: lower 75M platform, left | `cmp $C3EE,y` at `$E723` | | `$C3F0-$C3F1` | 2 | `Phase75MFlameLowerRightLimit` | 2 x 8-bit X limits: lower 75M platform, right | `cmp $C3F0,y` at `$E728` | | `$C3F2-$C3F3` | 2 | `Phase100MFlameSpeedStep` | 2 x 8-bit values: the flame enemy's horizontal speed step in the 100M stage | `lda $C3F2,x` at `$E744` | | `$C3F4-$C3F7` | 4 | `Phase25MFlameLadderMovePattern` | 2 x 16-bit LE bit masks: the frames on which a flame enemy moves along a ladder in the 25M stage (up = every 3rd frame, down = every 4th) | `lda $C3F4,x` at `$E429`, `lda $C3F5,x` at `$E42E` | | `$C3F8-$C3FB` | 4 | `Phase100MFlameLadderMovePattern` | 2 x 16-bit LE bit masks: the same thing for the 100M stage | `lda $C3F8,x` at `$E441`, `lda $C3F9,x` at `$E446` | | `$C3FC-$C406` | 11 | `BarrelBounceXPositionsRight` | 11 x 8-bit X positions at which a bouncing barrel's Y speed changes when it bounces to the right | `cmp $C3FC,x` at `$DCF3` | | `$C407-$C411` | 11 | `BarrelBounceYSpeeds` | 11 x 8-bit Y speed deltas, matching `BarrelBounceXPositionsRight` and `BarrelBounceXPositionsLeft` | `adc $C407,x` at `$DD16` | | `$C412-$C41C` | 11 | `BarrelBounceXPositionsLeft` | 11 x 8-bit X positions at which a bouncing barrel's Y speed changes when it bounces to the left | `cmp $C412,x` at `$DD06` | | `$C41D-$C41F` | 3 | `FlameEnemySpawnXPositions` | 3 x 8-bit X positions where flame enemies are spawned | `cmp $C41D,y` at `$DE90` | | `$C420-$C422` | 3 | `FlameEnemySpawnYPositions` | 3 x 8-bit Y positions where flame enemies are spawned | `cmp $C420,y` at `$DE95` | | `$C423-$C42A` | 8 | `MiscHitboxPositions` | 4 x 2-byte pairs `[X][Y]`: the oil barrel's flame, the (unused) phase-2 flame, the top-left lift end, and Donkey Kong himself | `lda $C423,x` at `$EDE1`, `lda $C424,x` at `$EDE6` | | `$C42B-$C432` | 8 | `MiscHitboxDimensionPointers` | 4 x 16-bit LE pointers to the hitbox dimensions of the four things above | `lda $C42B,x` at `$EDD7`, `lda $C42C,x` at `$EDDC` | | `$C433-$C436` | 4 | `OilBarrelFlameHitbox` | 1 x 4-byte hitbox `[X offset][Y offset][width][height]` of the lit oil barrel's flame | reached through `MiscHitboxDimensionPointers` at `$C42B` | | `$C437-$C43A` | 4 | - | the same 4-byte hitbox for the unused phase-2 flame | not referenced by any instruction | | `$C43B-$C43E` | 4 | `LiftEndHitbox` | 1 x 4-byte hitbox of the top-left lift end | reached through `MiscHitboxDimensionPointers` at `$C42B` | | `$C43F-$C442` | 4 | `DonkeyKongHitbox` | 1 x 4-byte hitbox of Donkey Kong | reached through `MiscHitboxDimensionPointers` at `$C42B` | | `$C443-$C447` | 5 | `BarrelThrowTimers` | 5 x 8-bit frame counts: how long until Donkey Kong throws the next barrel, one per difficulty | `lda $C443,x` at `$DA38` | | `$C448-$C44C` | 5 | `BarrelHorizontalSpeedTimers` | 5 x 8-bit frame counts for the barrel's horizontal movement, one per difficulty (all `$88`) | `lda $C448,x` at `$DB78` | | `$C44D-$C451` | 5 | `VerticalBarrelTossTimers` | 5 x 8-bit frame counts for Donkey Kong's vertical barrel toss, one per difficulty | `lda $C44D,x` at `$DAFA` | | `$C452-$C456` | 5 | - | five unused timer values of the same shape | not referenced by any instruction | | `$C457-$C45B` | 5 | `SpringboardSpawnTimers` | 5 x 8-bit frame counts until the next springboard spawns, one per difficulty | `lda $C457,x` at `$EA59` | | `$C45C-$C460` | 5 | `MovingPlatformMovePatternA` | 5 x 8-bit bit masks: the frames on which the 75M moving platforms move, one per difficulty | `lda $C45C,x` at `$E837` | | `$C461-$C465` | 5 | `MovingPlatformMovePatternB` | 5 x 8-bit bit masks: the second half of the moving platforms' move pattern | `lda $C461,x` at `$E83C` | | `$C466-$C46A` | 5 | `Phase100MFlameSpawnTimers` | 5 x 8-bit frame counts between flame enemy spawns in the 100M stage, one per difficulty | `lda $C466,x` at `$E21A` | | `$C46B-$C472` | 8 | `PhasePlatformPointerTable` | 4 x 16-bit LE pointers to the per-phase platform tables (25M uses `$C08C`, 75M `$C20C`, 100M `$C2F0`) | `lda $C46B,x` at `$D2FD`, `lda $C46C,x` at `$D302` | | `$C46F-$C476` | 8 | - | a second copy of the platform pointer table; no instruction reads it | not referenced by any instruction | | `$C473-$C47A` | 8 | `PhasePlatformHitboxPointerTable` | 4 x 16-bit LE pointers to the per-phase platform hitbox tables | `lda $C473,x` at `$D307`, `lda $C474,x` at `$D30C` | | `$C477-$C47E` | 8 | - | a second copy of the platform hitbox pointer table; no instruction reads it | not referenced by any instruction | | `$C47B-$C482` | 8 | `PhaseLadderTablePointers` | 4 x 16-bit LE pointers to the per-phase ladder tables | `lda $C47B,x` at `$D2A0`, `lda $C47C,x` at `$D2A5` | | `$C483-$C48A` | 8 | `PhaseLadderHitboxPointers` | 4 x 16-bit LE pointers to the per-phase ladder hitbox tables | `lda $C483,x` at `$D2AA`, `lda $C484,x` at `$D2AF` | | `$C48B-$C492` | 8 | `PhaseLadderTopPointers` | 4 x 16-bit LE pointers to the per-phase ladder-top tables | `lda $C48B,x` at `$D519`, `lda $C48C,x` at `$D51E` | | `$C493-$C49A` | 8 | `StagePlatformYPositionPointers` | 4 x 16-bit LE pointers to the per-phase platform Y position tables | `lda $C493,x` at `$E01F`, `lda $C494,x` at `$E024` | | `$C49B-$C49C` | 2 | `PhaseFlameLadderIndexPointer` | 1 x 16-bit LE pointer to the flame enemy's ladder-index table for the current phase | `lda $C49B,y` at `$E7B5`, `lda $C49C,y` at `$E7BA` | | `$C49D-$C4A0` | 4 | `PhaseFlameLadderIndexPointers` | 2 x 16-bit LE pointers to the 75M and 100M ladder-index tables | reached through `PhaseFlameLadderIndexPointer` at `$C49B` | | `$C4A1-$C4A2` | 2 | `PhaseFlameLadderDataPointer` | 1 x 16-bit LE pointer to the flame enemy's ladder-data table for the current phase | `lda $C4A1,y` at `$E7D6`, `lda $C4A2,y` at `$E7DB` | | `$C4A3-$C4A6` | 4 | `PhaseFlameLadderDataPointers` | 2 x 16-bit LE pointers to the 75M and 100M ladder-data tables | reached through `PhaseFlameLadderDataPointer` at `$C4A1` | | `$C4A7-$C4B2` | 12 | `ScreenLayoutPointers` | 6 x 16-bit LE pointers to the VRAM layout streams: 25M stage (`$F55B`), title screen (`$F8D9`), 75M stage (`$F7CD`), 100M stage (`$F71C`), title screen again, and the HUD (`$FA1B`) | `lda $C4A7,x` at `$C808`, `lda $C4A8,x` at `$C80D`; the pointer is then streamed to VRAM by `lda (Zp00),y` at `$F22D` | | `$C4B3-$C4F5` | 67 | `Phase25MEntityInitData` | 11 x 6-byte entity initialisation records `[X][Y][first tile][rows/columns][OAM slot][drawing mode]` plus the `$FE` terminator; they place Pauline, the barrels, the two hammers and Jumpman and clear the sprites the stage does not use | reached through `PhaseEntityInitPointers` at `$C5A6` | | `$C4F6-$C568` | 115 | `Phase75MEntityInitData` | 19 x 6-byte entity initialisation records of the same shape, plus the `$FE` terminator; they also place the six moving platforms | reached through `PhaseEntityInitPointers` at `$C5A6` | | `$C569-$C5A5` | 61 | `Phase100MEntityInitData` | 10 x 6-byte entity initialisation records of the same shape, plus the `$FE` terminator | reached through `PhaseEntityInitPointers` at `$C5A6` | | `$C5A6-$C5AD` | 8 | `PhaseEntityInitPointers` | 4 x 16-bit LE pointers to the per-phase entity initialisation records | `lda $C5A6,x` at `$CCC8`, `lda $C5A7,x` at `$CCCD` | | `$C5AE-$C5B7` | 10 | `Phase100MCollectibleYPositions` | the Y positions of the two collectibles (the handbag and the umbrella) of the 100M stage; the code addresses them with an index base of 8 | `lda $C5AE,x` at `$EE95`, `$EEF7` | | `$C5B8-$C5B8` | 1 | - | a single byte between the two position tables | not referenced by any instruction | | `$C5B9-$C5C0` | 8 | `Phase100MBoltYPositions` | 8 x 8-bit Y positions of the rivets (bolts) of the 100M stage | `lda $C5AE,x` at `$EE95`, `$EEF7` (index 11-18) | | `$C5C1-$C5C1` | 1 | - | a single byte between the two position tables | not referenced by any instruction | | `$C5C2-$C5CB` | 10 | `Phase100MCollectibleXPositions` | the X positions of the two collectibles of the 100M stage (index base 8) | `lda $C5C2,x` at `$EE8D`, `$EEFF` | | `$C5CC-$C5CC` | 1 | - | a single byte between the two position tables | not referenced by any instruction | | `$C5CD-$C5D4` | 8 | `Phase100MBoltXPositions` | 8 x 8-bit X positions of the rivets of the 100M stage | `lda $C5C2,x` at `$EE8D`, `$EEFF` (index 11-18) | | `$C5D6-$C5D8` | 3 | `Phase100MEraseVramLowBytes` | 3 x 8-bit low bytes of the VRAM address of the tile erased when a bolt or a collectible is removed | `lda $C5D6,x` at `$EF42` | | `$C5D9-$C5DF` | 7 | - | seven bytes of mixed small values between the erase-address tables; nothing reads them | not referenced by any instruction | | `$C5E0-$C5E8` | 9 | - | nine bytes of mixed small values; nothing reads them | not referenced by any instruction | | `$C5E9-$C5EC` | 4 | `Phase100MEraseVramHighBytes` | 4 x 8-bit high bytes of the same erased-tile VRAM address | `lda $C5E9,x` at `$EF47` | | `$C5ED-$C5F3` | 7 | - | seven bytes of mixed small values; nothing reads them | not referenced by any instruction | | `$C5F4-$C5F9` | 6 | - | six bytes of mixed small values; nothing reads them | not referenced by any instruction | | `$C5FA-$C5FB` | 2 | `PhaseCollectibleIndexBase` | 2 x 8-bit index bases (8 and 23) into the collectible position tables, selected by the phase number | `ldx $C5FA,y` at `$EEF2` | | `$C5FC-$C5FE` | 3 | - | three spare bytes; nothing reads them | not referenced by any instruction | | `$C5FF-$C5FF` | 1 | `BoltCheckCount` | a single byte, `$0B`: the index of the first rivet the collision check starts from | `ldx $C5FF` at `$EE8A` | | `$C600-$C603` | 4 | `ScorePointAwards` | 4 x 8-bit score awards in hundreds (100, 300 (unused), 500, 800) | `lda $C600,x` at `$D016` | | `$C604-$C607` | 4 | `ScoreSpriteTiles` | 4 x 8-bit CHR tile indices for the score pop-ups "1", "3", "5", "8" | `lda $C604,x` at `$CFE7` | | `$C608-$C60B` | 4 | `DonkeyKongVramLowByte` | 4 x 8-bit low bytes of the VRAM address of Kong's picture, one per phase (the high byte is always the same) | `lda $C608,x` at `$CB4C`, `$EB19` | | `$C60C-$C624` | 25 | `Tilemap_DonkeyKong_PickupBarrel` | a VRAM update stream: `[columns][tile rows...]` — the 6x4 tile grid of Kong picking up a barrel | reached through `DonkeyKongFramePointerTable` at `$C03C` and `PhaseTilemapPointerTable` at `$C066` | | `$C625-$C63D` | 25 | `Tilemap_DonkeyKong_HoldingBarrel` | a VRAM update stream: the 6x4 tile grid of Kong holding a barrel | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C63E-$C656` | 25 | `Tilemap_DonkeyKong_SideToss` | a VRAM update stream: the 6x4 tile grid of Kong tossing a barrel to the side | reached through `DonkeyKongFramePointerTable` at `$C03C` | | `$C657-$C66F` | 25 | `Tilemap_DonkeyKong_Stationary` | a VRAM update stream: the 6x4 tile grid of Kong standing still | reached through `DonkeyKongFramePointerTable` at `$C03C` | | `$C670-$C688` | 25 | `Tilemap_DonkeyKong_HitChestLeftHand` | a VRAM update stream: the 6x4 tile grid of Kong hitting his chest with his left hand | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C689-$C6A1` | 25 | `Tilemap_DonkeyKong_HitChestRightHand` | a VRAM update stream: the 6x4 tile grid of Kong hitting his chest with his right hand | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C6A2-$C6A5` | 4 | `FlameEnemyThreatenedPalette` | a palette upload: `[count][$2C][$16][$13]`, the sprite-2 palette the 100M flame enemies use while Jumpman holds the hammer | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C6A6-$C6A9` | 4 | `FlameEnemyPalette` | a palette upload: `[count][$16][$30][$37]`, the normal sprite-2 palette of the flame enemies | reached through `PhaseTilemapPointerTable` at `$C066` | | `$C6AA-$C6C1` | 24 | `Tilemap_PlayerScreen` | a VRAM update stream: the attributes and the " PLAYER I " / " PLAYER II " text of the two-player start screen | `lda $C6AA,y` at `$CBDF` | | `$C6C2-$C6E0` | 31 | `Tilemap_GameOver` | a VRAM update stream: the attributes and the " GAME OVER " message | `lda $C6C2,y` at `$CBF7` | | `$C6E1-$C6E3` | 3 | `Tilemap_RemovePlayerII` | a VRAM update stream: two blank tiles that erase the "II" of the two-player screen | reached through `DonkeyKongFramePointerTable` at `$C03C` | | `$C6E4-$C6F0` | 13 | `EndingScoreEraseStream` | a VRAM update stream: the tiles that erase the score and the stat rows during the ending | reached through `EndingSequencePointerTable` at `$C044` | | `$C6F1-$C707` | 23 | `EndingPlatformEraseStream` | a VRAM update stream: the tiles that erase the platforms during the ending, then Kong's sprite palette | reached through `EndingSequencePointerTable` at `$C044` | | `$C708-$C718` | 17 | `EndingKongEraseStream` | a VRAM update stream: the tiles that erase Kong during the ending | reached through `EndingSequencePointerTable` at `$C044` | | `$C719-$C71B` | 3 | `EndingDefeatedKongAttributes` | a VRAM update stream: the two attribute bytes of the defeated-Kong frames | reached through `EndingSequencePointerTable` at `$C044` | | `$C71C-$C734` | 25 | `Tilemap_DonkeyKong_Defeated1` | a VRAM update stream: the 6x4 tile grid of Kong's first defeated frame | reached through `EndingSequencePointerTable` at `$C044` | | `$C735-$C74D` | 25 | `Tilemap_DonkeyKong_Defeated2` | a VRAM update stream: the 6x4 tile grid of Kong's second defeated frame | reached through `EndingSequencePointerTable` at `$C044` | | `$C74E-$C752` | 5 | `EndingPlatformStream` | a VRAM update stream: the platform Jumpman and Pauline stand on during the ending | reached through `EndingSequencePointerTable` at `$C044` | | `$C753-$C75F` | 13 | `EndingBottomPlatformStream` | a VRAM update stream: the three platforms drawn along the bottom of the screen during the ending | reached through `EndingSequencePointerTable` at `$C044` | | `$C760-$C77C` | 29 | `EndingTileEraseStream1` | a VRAM update stream: the umbrella, handbag and platform tiles erased in the first half of the DK-defeat cutscene | reached through `DonkeyKongFramePointerTable` at `$C03C` and `EndingSequencePointerTable` at `$C044` | | `$C77D-$C799` | 29 | `EndingTileEraseStream2` | a VRAM update stream: the remaining umbrella and ladder tiles erased in the second half of the cutscene | reached through `EndingSequencePointerTable` at `$C044` | | `$C79A-$C79B` | 2 | `CommonSpeedTableA` | 2 bytes ($FF, $01) added to the high byte of an entity's sprite pointer; the routine at `$E6C6` picks this table when the entity's flag bit 0 is set | `lda $C79A,y` at `$E6D5` | | `$C79C-$C79D` | 2 | `CommonSpeedTableB` | 2 bytes ($01, $FF) added to the same pointer's high byte; picked when the entity's flag bit 0 is clear | `lda $C79C,y` at `$E6DB` | ### The other seven data blocks | Address | Size | Name | Structure | Read by | |---------|------|------|-----------|---------| | `$D650-$D696` | 71 | - | unreferenced; decodes as 34 consecutive instructions, so it is code the tracer could not reach, not data. The routine writes the terminator `$FE` twice into the collision table at `$0460` and then walks the OAM to find a platform for each barrel — the table it fills is the one pointed at by the unused word at `$C05C` | not referenced by any instruction | | `$E144-$E165` | 34 | - | unreferenced; decodes as 18 consecutive instructions, so it is code the tracer could not reach, not data. The routine walks the OAM from slot 8 and records the platform index of each barrel | not referenced by any instruction | | `$F55B-$F7CB` | 449 | `Phase25MScreenLayoutStream` | a VRAM update stream for the whole 25M stage: palette upload, attribute blocks, and the girder/ladder/Pauline/barrel tilemap drawn with the `$20`/`$23` VRAM commands | reached through `ScreenLayoutPointers` at `$C4A7` (`lda $C4A7,x` at `$C808`); the bytes are consumed by `lda (Zp00),y` at `$F22D` | | `$F71C-$F7CC` | 177 | `Phase100MScreenLayoutStream` | a VRAM update stream for the whole 100M stage: palette upload, attributes and the rivet-stage tilemap | reached through `ScreenLayoutPointers` at `$C4A7`; consumed by `lda (Zp00),y` at `$F22D` | | `$F7CD-$F8D8` | 268 | `Phase75MScreenLayoutStream` | a VRAM update stream for the whole 75M stage: palette upload, attributes and the conveyor-belt tilemap | reached through `ScreenLayoutPointers` at `$C4A7`; consumed by `lda (Zp00),y` at `$F22D` | | `$F8D9-$FA1A` | 322 | `TitleScreenLayoutStream` | a VRAM update stream for the title screen: palette upload, the "DONKEY KONG" logo, the menu and the copyright line | reached through `ScreenLayoutPointers` at `$C4A7`; consumed by `lda (Zp00),y` at `$F22D` | | `$FA1B-$FA47` | 45 | `HudLayoutStream` | a VRAM update stream for the HUD: the score, lives, bonus and level rows | reached through `ScreenLayoutPointers` at `$C4A7`; consumed by `lda (Zp00),y` at `$F22D` | | `$FA9C-$FA9E` | 3 | - | the three bytes `$20 $95 $FA` are a `jsr $FA95` that no branch ever reaches; it is an unreachable instruction, not data | not referenced by any instruction | | `$FAE6-$FAF4` | 15 | `StepSfxSweepValues` | 15 x 8-bit APU sweep values for the step sound effect | `ldy $FAE5,x` at `$FC6C` (the code addresses the table one byte below its first entry) | | `$FAF5-$FAFF` | 11 | `JumpSfxSweepValues` | 11 x 8-bit APU sweep values for the jump sound effect (a value below `$80` disables the sweep) | `ldy $FAF5,x` at `$FC32` | | `$FB00-$FB4B` | 76 | `ChannelFrequencyTable` | 3 unused bytes then 36 x 16-bit LE APU frequency words; the sound engine indexes it with the channel's frequency index | `lda $FB00,y` at `$FAAA`, `lda $FB01,y` at `$FAA2` | | `$FB4C-$FB61` | 22 | `ChannelLengthTable` | 22 x 8-bit note-length values (1/8, 1/16, 1/32, 1/64 steps) used to time a note | `lda $FB4C,y` at `$FAD1` | | `$FB62-$FB66` | 5 | `TriangleNoteLengthTable` | 5 x 8-bit note lengths for the triangle channel | `lda $FB62,y` at `$FD4D` | | `$FB67-$FB74` | 14 | `PlayerDeadFrequencyTable` | 14 x 8-bit frequency indices for the "player died" square-wave effect | `ldy $FB67,x` at `$FB8B`, `adc $FB67,x` at `$FB9A` | | `$FE59-$FE8E` | 54 | `FanfareHeaderTable` | 9 x 6-byte fanfare headers `[note-length offset][sound data pointer low][sound data pointer high][triangle data offset][square-1 data offset]`; the offsets are relative to the header's own sound data | `lda $FE59,y` at `$FD67`, `$FD6B`, `lda $FE5A,y` at `$FD71`, `lda $FE5B,y` at `$FD76`, `lda $FE5C,y` at `$FD7B`, `lda $FE5D,y` at `$FD80` | | `$FE8F-$FEA9` | 27 | `GameStartSoundData` | the square-channel note stream of the "game start" fanfare | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FEAA-$FEAF` | 6 | `GameStartTriangleData` | the triangle-channel note stream of the "game start" fanfare | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FEB0-$FEBB` | 12 | `PhaseCompleteSoundData` | the square-channel note stream of the "phase complete" fanfare | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FEBC-$FECF` | 19 | `PhaseCompleteSquare1Data` | the square-1-channel note stream of the "phase complete" fanfare | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FECF-$FEE8` | 26 | `KongDefeatedSoundData` | the square-channel note stream of the "Kong defeated" fanfare | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FEE9-$FF04` | 28 | `KongDefeatedSquare1Data` | the square-1-channel note stream of the "Kong defeated" fanfare | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FF05-$FF0F` | 11 | `PhaseStartSoundData` | the square-channel note stream of the "phase start" fanfare | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FF10-$FF1F` | 16 | `PhaseStartSquare1Data` | the square-1-channel note stream of the "phase start" fanfare | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FF20-$FF40` | 33 | `TitleScreenThemeSoundData` | the square-channel note stream of the title-screen theme | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FF41-$FF5D` | 29 | `TitleScreenThemeTriangleData` | the triangle-channel note stream of the title-screen theme | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FF5E-$FFA0` | 67 | `TitleScreenThemeSquare1Data` | the square-1-channel note stream of the title-screen theme | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FFA1-$FFA8` | 8 | `DeadPart2SoundData` | the square-channel note stream of the "player dead, part 2" effect | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FFA9-$FFAC` | 4 | `DeadPart2TriangleData` | the triangle-channel note stream of the "player dead, part 2" effect | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FFAD-$FFAF` | 3 | `KongFallingSoundData` | the square-channel note stream of the "Kong falling" effect | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FFB0-$FFBD` | 14 | `KongFallingSquare1Data` | the square-1-channel note stream of the "Kong falling" effect | reached through the offset in `FanfareHeaderTable` at `$FE59` | | `$FFBE-$FFC3` | 6 | `ScoreSoundData` | the square-channel note stream of the score chime | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FFC4-$FFCC` | 9 | `GamePauseSoundData` | the square-channel note stream of the pause jingle | reached through the pointer in `FanfareHeaderTable` at `$FE59` | | `$FFCD-$FFD3` | 7 | `MusicDataOffsetTable` | 7 x 8-bit offsets into the music data, one per music track, used as the triangle channel's beat counter | `lda $FFCD,y` at `$FD25` | | `$FFD4-$FFDC` | 9 | `Phase25MMusicData` | 9 bytes of triangle-channel note/timing data for the 25M stage music | reached through the music pointer set at `$FD2B`/`$FD2F` | | `$FFDD-$FFE1` | 5 | `Phase100MMusicData` | 5 bytes of triangle-channel note/timing data for the 100M stage music | reached through the music pointer set at `$FD2B`/`$FD2F` | | `$FFE2-$FFE5` | 4 | `HurryUpMusicData` | 4 bytes of triangle-channel note/timing data for the hurry-up tune | reached through the music pointer set at `$FD2B`/`$FD2F` | | `$FFE6-$FFF9` | 20 | `HammerMusicData` | 20 bytes of triangle-channel note/timing data for the hammer tune; the IRQ vector at `$FFFE` points into the middle of it, which is why the IRQ handler is a placeholder | reached through the music pointer set at `$FD2B`/`$FD2F` | | `$FFFA-$FFFF` | 6 | `InterruptVectorTable` | 3 x 16-bit LE vectors: NMI = `$C85F`, RESET = `$C79E`, IRQ = `$FFF0` | the CPU reads them from the vector page; the IRQ target is the placeholder inside `HammerMusicData` | ### Notes on the blocks that are not tables - The two blocks that "decode as N consecutive instructions" (`$D650-$D696` and `$E144-$E165`) are code, not data: the tracer never reached them, so they are still emitted as `.byte` rows, but their contents are instructions. They are left unnamed on purpose. - `$FA9C-$FA9E` is a single unreachable `jsr`, not a table. - The pointer table at `$C066` and the duplicate pointer tables at `$C46F` and `$C477` are not read by any instruction of this dump. The tables they point at are still interpreted above (their layout is plain from the records), but they are marked as reached indirectly so the reader knows the evidence for them is the record shape rather than an instruction. - The 16-byte group at `$C192-$C1A1` is four 4-byte hitbox-shaped records. Nothing reads them; their layout is recorded, not assumed. ## Pass 3 Details (2026-10-19, revised 2026-10-21) - **Data table naming**: the 2026-10-19 pass named ten whole blocks. After the 2026-10-21 Pass 1 re-split from the Mesen CDL capture (`dk_gameplay.cdl`) the generic block names were replaced by **175 individually interpreted tables**, listed in the Pass 3 data-table inventory above. The old names (`LevelPtrTable`, `ObjectPtrTable`, `LevelDataPtrTable`, `SpriteInitPtrTable`, `MusicDataTable`, `APUDataTable`, `SfxDataTable`, `VectorTable`, `UnreachedCode_D650`, `UnreachedCode_E144`) are gone; every one of the ten regions is now covered by named sub-tables, by a recorded unreferenced group, or by a note that the bytes are unreachable code. - The `$C000-$C79D` region turned out to be the phase/level data block: per phase (25M girders, 75M conveyor belt, 100M rivets) it holds the platform and ladder tables, the hitbox tables, the per-phase pointer tables, the entity initialisation records and Kong's sprite tilemaps. - The `$F55B-$FA47` region is not music data: it is the five VRAM update streams that draw the three stages, the title screen and the HUD. - All regions remain byte-identical; `make` proves the **whole ROM** (header + PRG + CHR). ## Promotion (2026-10-19) Executed per `PROMPTS.md` / AGENTS.md: `git mv` to top level, `rom.nes` symlink added, `header.s` + `chr.s` + HEADER/PRG/CHR `linker.cfg` added (a Pass-0 skeleton ships none of the three), Makefile switched from `cmp reconstructed_prg.bin prg.bin` to `cmp reconstructed.nes rom.nes`. No `_tools` path change was needed — this Makefile does not reference `_tools/`, and there is no `make regen` target. Mirroring discrepancy resolved to Horizontal from header byte 6. ## Next Steps The data tables are done: every one of the eight tracer data blocks is interpreted in the inventory above, and the 173 tables carry ROM-specific names. Open work that is **not** about the tables: - The two unreached code blocks at `$D650-$D696` and `$E144-$E165` are still emitted as `.byte` rows. Seeding the tracer at their first byte would turn them into real routines; the README records what they do in the meantime. - The 19-byte pointer table at `$C066` and the duplicate tables at `$C46F` and `$C477` are read by no instruction of this dump. Their targets are interpreted from the record shape, not from a reader. - The 654 `SubC_` branch labels and the 145 zero-page slots in `locals.inc` still carry address-derived or neutral names; behavioural names for them would be the next piece of work.