- Decoded the VramWrite ($E1CC) stream format: <addr hi> <addr lo> <count> <bytes>, $00 terminator - Named all 9 payload streams ($E4CC-$E7C2, no gaps/overlaps) plus VramWriteSourcePointerTable at $F000 - Split PadBitTableLives into Player1TileTable ($E4B4) and Player2TileTable ($E4C0), 12 entries each (Y=0..11) - Decoded CHR font (digits $30-$39, letters $3A-$52, space $5F; 'W' missing from the A-Z run) and recovered on-screen text including 'PRESS A TO TEST SIDE-A' / 'SIDE-B' - Documented that the 16 KiB PRG is two byte-identical 8 KiB halves; $C000 copy is dead - Documented 7 unreached subroutines inside the live code region (kept as .byte per Pass-1 policy) - Fixed a stray duplicate sentence and stale _wip paths in root OVERVIEW.md Byte-identical ROM verified.
9.2 KiB
9.2 KiB
| 1 | # MUSCLE (U) data-region structure - Pass 3 | ||||
|---|---|---|---|---|---|
| 2 | # start<TAB>end<TAB>label<TAB>format<TAB>comment | ||||
| 3 | 0x85ED | 0x8638 | StandaloneBytecodeProgram | bytes | Pass 3: bytecode program not listed in BytecodeProgramPointerTable. |
| 4 | 0x881F | 0x8836 | StandaloneBytecodeProgram_1 | bytes | Pass 3: bytecode program not listed in BytecodeProgramPointerTable. |
| 5 | 0x8A1E | 0x8A27 | StandaloneBytecodeProgram_2 | bytes | Pass 3: tail of a bytecode program; the $1D byte rules out an instruction decode. |
| 6 | 0x8B7D | 0x8B91 | AttributeBlockDeltaTable | bytes | Pass 3: 7 x 3-byte deltas {source lo, source hi, destination lo}. ClearAttributeRegion walks it with three `sbc table,x` against the same index. |
| 7 | 0x8CEF | 0x8D3A | BytecodeProgramPointerTable | word | Pass 3: 38 x 16-bit pointers into the bytecode programs that follow. RunBytecodeInterpreter masks the program index with $3F, so entries 38-63 would read past this table; entry 38 already reads the first byte of BytecodeProgram_00, so the table is exactly 38 entries. |
| 8 | 0x8D3B | 0x8D3F | BytecodeProgram_00 | bytes | Pass 3: bytecode program, table index/indices [13], 5 bytes. |
| 9 | 0x8D40 | 0x8D5B | BytecodeProgram_01 | bytes | Pass 3: bytecode program, table index/indices [36], 28 bytes. |
| 10 | 0x8D5C | 0x8D8C | BytecodeProgram_02 | bytes | Pass 3: bytecode program, table index/indices [37], 49 bytes. |
| 11 | 0x8D8D | 0x8D95 | BytecodeProgram_03 | bytes | Pass 3: bytecode program, table index/indices [22], 9 bytes. |
| 12 | 0x8D96 | 0x8D9E | BytecodeProgram_04 | bytes | Pass 3: bytecode program, table index/indices [23], 9 bytes. |
| 13 | 0x8D9F | 0x8DB5 | BytecodeProgram_05 | bytes | Pass 3: bytecode program, table index/indices [33], 23 bytes. |
| 14 | 0x8DB6 | 0x8DE1 | BytecodeProgram_06 | bytes | Pass 3: bytecode program, table index/indices [34], 44 bytes. |
| 15 | 0x8DE2 | 0x8E2C | BytecodeProgram_07 | bytes | Pass 3: bytecode program, table index/indices [35], 75 bytes. |
| 16 | 0x8E2D | 0x8E78 | BytecodeProgram_08 | bytes | Pass 3: bytecode program, table index/indices [14], 76 bytes. |
| 17 | 0x8E79 | 0x8EA8 | BytecodeProgram_09 | bytes | Pass 3: bytecode program, table index/indices [11], 48 bytes. |
| 18 | 0x8EA9 | 0x8EF3 | BytecodeProgram_0A | bytes | Pass 3: bytecode program, table index/indices [24], 75 bytes. |
| 19 | 0x8EF4 | 0x8F19 | BytecodeProgram_0B | bytes | Pass 3: bytecode program, table index/indices [25], 38 bytes. |
| 20 | 0x8F1A | 0x8F1F | BytecodeProgram_0C | bytes | Pass 3: bytecode program, table index/indices [28], 6 bytes. |
| 21 | 0x8F20 | 0x8F47 | BytecodeProgram_0D | bytes | Pass 3: bytecode program, table index/indices [31], 40 bytes. |
| 22 | 0x8F48 | 0x8F70 | BytecodeProgram_0E | bytes | Pass 3: bytecode program, table index/indices [32], 41 bytes. |
| 23 | 0x8F71 | 0x8F93 | BytecodeProgram_0F | bytes | Pass 3: bytecode program, table index/indices [29], 35 bytes. |
| 24 | 0x8F94 | 0x8FFC | BytecodeProgram_10 | bytes | Pass 3: bytecode program, table index/indices [16], 105 bytes. |
| 25 | 0x8FFD | 0x9007 | BytecodeProgram_11 | bytes | Pass 3: bytecode program, table index/indices [15], 11 bytes. |
| 26 | 0x9008 | 0x9070 | BytecodeProgram_12 | bytes | Pass 3: bytecode program, table index/indices [17], 105 bytes. |
| 27 | 0x9071 | 0x907C | BytecodeProgram_13 | bytes | Pass 3: bytecode program, table index/indices [27], 12 bytes. |
| 28 | 0x907D | 0x9080 | BytecodeProgram_14 | bytes | Pass 3: bytecode program, table index/indices [0], 4 bytes. |
| 29 | 0x9081 | 0x90A5 | BytecodeProgram_15 | bytes | Pass 3: bytecode program, table index/indices [1], 37 bytes. |
| 30 | 0x90A6 | 0x90B8 | BytecodeProgram_16 | bytes | Pass 3: bytecode program, table index/indices [26], 19 bytes. |
| 31 | 0x90B9 | 0x90C9 | BytecodeProgram_17 | bytes | Pass 3: bytecode program, table index/indices [5], 17 bytes. |
| 32 | 0x90CA | 0x90D6 | BytecodeProgram_18 | bytes | Pass 3: bytecode program, table index/indices [2], 13 bytes. |
| 33 | 0x90D7 | 0x90DD | BytecodeProgram_19 | bytes | Pass 3: bytecode program, table index/indices [12], 7 bytes. |
| 34 | 0x90DE | 0x9118 | BytecodeProgram_1A | bytes | Pass 3: bytecode program, table index/indices [3], 59 bytes. |
| 35 | 0x9119 | 0x9130 | BytecodeProgram_1B | bytes | Pass 3: bytecode program, table index/indices [4], 24 bytes. |
| 36 | 0x9131 | 0x9135 | BytecodeProgram_1C | bytes | Pass 3: bytecode program, table index/indices [6], 5 bytes. |
| 37 | 0x9136 | 0x9140 | BytecodeProgram_1D | bytes | Pass 3: bytecode program, table index/indices [7], 11 bytes. |
| 38 | 0x9141 | 0x9174 | BytecodeProgram_1E | bytes | Pass 3: bytecode program, table index/indices [8], 52 bytes. |
| 39 | 0x9175 | 0x918A | BytecodeProgram_1F | bytes | Pass 3: bytecode program, table index/indices [18], 22 bytes. |
| 40 | 0x918B | 0x91DF | BytecodeProgram_20 | bytes | Pass 3: bytecode program, table index/indices [19], 85 bytes. |
| 41 | 0x91E0 | 0x91EB | BytecodeProgram_21 | bytes | Pass 3: bytecode program, table index/indices [20], 12 bytes. |
| 42 | 0x91EC | 0x922B | BytecodeProgram_22 | bytes | Pass 3: bytecode program, table index/indices [21], 64 bytes. |
| 43 | 0x922C | 0x922E | BytecodeProgram_23 | bytes | Pass 3: bytecode program, table index/indices [9], 3 bytes. |
| 44 | 0x922F | 0x9231 | BytecodeProgram_24 | bytes | Pass 3: bytecode program, table index/indices [10], 3 bytes. |
| 45 | 0x9232 | 0x9236 | BytecodeProgram_25 | bytes | Pass 3: bytecode program, table index/indices [30], 5 bytes. |
| 46 | 0x9237 | 0x9286 | BytecodeHandlerTable | word | Pass 3: 40 x 16-bit opcode handlers, index = (token - $C8). Dispatched through BytecodeHandlerPointerLo/Hi into DispatchThroughPointer (jmp ($001C)). Tokens $C8-$EF map to entries 0-39; slots the assembler never filled hold the next table's bytes. |
| 47 | 0x9EF4 | 0x9F13 | OamShadowTemplate | bytes | Pass 3: the 32-byte initial OAM block LoadOamShadowFromTable copies into $0300. |
| 48 | 0x9F2B | 0x9F4A | SecondaryBytecodeHandlerTable | word | Pass 3: 16 x 16-bit handlers consumed by UpdateActorMovement; index = (token & $0F) * 2. Entry 1 holds $9FBB, one byte into a real jsr, so that slot is unused. |
| 49 | 0xA5F4 | 0xA617 | StageDescriptorPointerTable | word | Pass 3: 18 x 16-bit pointers into StageDescriptorData. Two readers share it: UpdateStageDescriptorAt reads (A & $1E) starting at entry 0, and the writer at $A593 reads the same array starting at entry 9. Entry 18 already reads descriptor text, so 18. |
| 50 | 0xA618 | 0xA65F | StageDescriptorData | bytes | Pass 3: packed tile/attribute sequences the pointer table above targets. Six records, twelve bytes apart ($A618 $A624 $A630 $A63C $A648) and a final ten-byte record at $A654; each is a short header followed by a descending run of tile indices. The last record ends with the two $30 terminator bytes. |
| 51 | 0xAB14 | 0xAB67 | StandaloneBytecodeProgram_3 | bytes | Pass 3: bytecode program not listed in BytecodeProgramPointerTable. |
| 52 | 0xAC35 | 0xAC3A | LevelVramWriterTable | word | Pass 3: 3 x 16-bit VRAM writers, index = the level byte at $0326. SelectLevelVramWriter loads the entry into SourcePointerLo/Hi and jumps through jmp ($0010). |
| 53 | 0xACBD | 0xACC8 | VramRunFillValues | bytes | Pass 3: the 12 fill values the compressed-VRAM run tokens $B8-$C3 select by index (token - $B8); WriteVramRunToken reads one with `lda $ACBD,x`. |
| 54 | 0xAE35 | 0xAE44 | AnimationFrameCollisionBits | bytes | Pass 3: 16-entry animation-frame -> collision-flag-bits table (index = animation frame & $0F). |
| 55 | 0xAF37 | 0xAF3A | UnreachableSoundInitIsland | bytes | Pass 3: lda $E9 / bne $AF34 sits immediately after the rts that ends InitializeSoundEngine and branches back into the middle of it. No word in the image points here and the bytecode handler tables do not contain it, so it is unreachable. It is neither a coherent routine nor a table anything reads, so it stays data. |
| 56 | 0xB0CB | 0xB0E2 | SoundNotePeriodTable | word | Pass 3: 12 x 16-bit tone periods, index = note number & $0F (guarded by cmp #$0C). ComputeTonePeriod loads the low byte from $B0CB+n and the high byte from $B0CC+n. |
| 57 | 0xB0E3 | 0xB0F2 | SoundNoteDurationTable | bytes | Pass 3: 16 note durations, index = (duration byte - $F0), clamped by the table's end at $B0F2. |
| 58 | 0xB0F3 | 0xB0F6 | ApuChannelEnableBitsSet | bytes | Pass 3: 4 x 1-byte masks OR-ed into ApuEnableMask, indexed by channel*4 in BuildApuChannelMask. |
| 59 | 0xB0F7 | 0xB0FA | ApuChannelEnableBitsClear | bytes | Pass 3: 4 x 1-byte masks AND-ed into ApuEnableMask, indexed by channel*4 in RebuildApuEnableMask. |
| 60 | 0xB0FB | 0xB91A | StageNametableAndObjectData | bytes | Pass 3: the bulk of the per-stage data - compressed nametable and attribute payloads plus the object layout lists. Nothing indexes it with a constant address: ProcessBytecodeOpcode reaches it through StageDataPointerLow plus the 16-bit value carried in the bytecode stream, so the record structure is not resolvable from the static trace. |
| 61 | 0xB91B | 0xB970 | StageDataFiller | bytes | Pass 3: an 86-byte run of $FF padding between stage data blocks. |
| 62 | 0xB971 | 0xBD27 | StageNametableAndObjectData_1 | bytes | Pass 3: continuation of the stage data block; see StageNametableAndObjectData. |
| 63 | 0xBD28 | 0xBD29 | StageDataPointerLow | bytes | Pass 3: one low byte per player; ProcessBytecodeOpcode adds $32 for the second player to reach its copy, so the two entries are $32 apart in the stage data that follows. |
| 64 | 0xBD2A | 0xBEBF | StageNametableAndObjectData_2 | bytes | Pass 3: continuation of the stage data block, read through StageDataPointerLow plus the $32 per-player offset. |
| 65 | 0xBEC0 | 0xBEC7 | InitialOamAttributes | bytes | Pass 3: 8 entries (ldx #$07) copied into $0220 by CompactOamList. |
| 66 | 0xBEC8 | 0xBECF | InitialOamTiles | bytes | Pass 3: 8 entries copied into $0223 by CompactOamList. |
| 67 | 0xBED0 | 0xBF8F | StageDataTail | bytes | Pass 3: the tail of the stage data block, ahead of the VRAM block descriptors. |
| 68 | 0xBF90 | 0xBF97 | VramBlockByteCounts | bytes | Pass 3: 8 block sizes fed to ExecuteVramTransfer by ReadControllerAndInit. |
| 69 | 0xBF98 | 0xBF9F | VramBlockSourceLowBytes | bytes | Pass 3: 8 block source low bytes; the high byte is always $02. |
| 70 | 0xBFA0 | 0xBFFA | SoundSequenceAndLevelData | bytes | Pass 3: the $B1A1/$B1B0/$B2B9/$B3B2 sound sequences the sound engine points at, plus the level tables, ending just before the vectors. |
| 71 | 0xBFFB | 0xBFFF | InterruptVectors | bytes | Pass 3: the three CPU vectors, mirrored into the ROM at $FFFB-$FFFF. |