# Slalom (U) ## Status **Pass 3 complete; promoted.** `prg.s` is a traced disassembly with all address-derived labels replaced, all `jsr`/`jmp` operands symbolic, hardware registers named via `symbols.inc`, and `apply_symbols.py` reporting 0 residue. Code coverage: 10,537 / 32,768 bytes (32.2%). `make` assembles and verifies byte-identical to `rom.nes`. **Pass 3 data tables done.** Every `; ---- data ----` block in the PRG is now interpreted and named in `prg.s`; the full inventory (address, size, name, record structure and the consuming instruction, or the ROM provenance for the blocks nothing reads) is in [Pass 3 data-table inventory](#pass-3-data-table-inventory). 50 tables were placed; the blocks that no instruction of this dump reads are recorded there as unreferenced data or as code the tracer could not reach. ## 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 `$8050` (`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 | |---------|---------| | `$8057` | `Reset_OnNonnegative` (falls through) | | `$805C` | `Reset_OnNonnegative2` (falls through) | | `$B476` | `Sub_B476` | | `$8A6D` | `Sub_8A6D` | | `$8067` | `Sub_8067` (falls through) | | `$B49B` | `Sub_B49B` | | `$B4A3` | `Sub_B4A3` | | `$B480` | `Sub_B480` (falls through) | | `$8A6F` | `NmiHandler_OnNonzero17` (falls through) | | `$8069` | `Sub_8069` (falls through) | | `$B48E` | `Sub_B48E` | | `$B4AC` | `Sub_B4AC` | | `$A521` | `Sub_A521` | **NMI** is at `$8123` (`NmiHandler`). It is the per-frame handler; what it calls: | Address | Routine | |---------|---------| | `$B438` | `Sub_B438` | **IRQ** is at `$FEDF` (`IrqHandler`) - a different address from RESET. ## ROM | Property | Value | |----------|-------| | Format | iNES | | Mapper | 0 (NROM) | | PRG | 32 KB | | CHR | 8 KB | | Mirroring | Vertical | | NMI vector | $8123 | | RESET vector | $8050 | | IRQ vector | $FEDF | ## Power-on flow RESET enters at `$8050`: sei ; CPU:$8050 PRG:0050 78 cld ; CPU:$8051 PRG:0051 D8 lda #$18 ; CPU:$8052 PRG:0052 A9 18 sta PPUCTRL ; CPU:$8054 PRG:0054 8D 00 20 lda PPUSTATUS ; CPU:$8057 PRG:0057 AD 02 20 bpl Reset_OnNonnegative ; CPU:$805A PRG:005A 10 FB lda PPUSTATUS ; CPU:$805C PRG:005C AD 02 20 bpl Reset_OnNonnegative2 ; CPU:$805F PRG:005F 10 FB jsr Sub_B476 ; CPU:$8061 PRG:0061 20 76 B4 jsr Sub_8A6D ; CPU:$8064 PRG:0064 20 6D 8A lda #$FF ; CPU:$8067 PRG:0067 A9 FF sta $0731 ; CPU:$8069 PRG:0069 8D 31 07 NMI handler at `$8123`: lda PPUSTATUS ; CPU:$8123 PRG:0123 AD 02 20 lda #$00 ; CPU:$8126 PRG:0126 A9 00 sta OAMADDR ; CPU:$8128 PRG:0128 8D 03 20 lda #$04 ; CPU:$812B PRG:012B A9 04 sta OAMDMA ; CPU:$812D PRG:012D 8D 14 40 jsr Sub_B438 ; CPU:$8130 PRG:0130 20 38 B4 ldx Zp02 ; CPU:$8133 PRG:0133 A6 02 lda $8142,x ; CPU:$8135 PRG:0135 BD 42 81 ## Pass 3 data-table inventory Every `; ---- data $XXXX-$YYYY ----` block in `prg.s` is listed here, split further where one block holds more than one table. "Read by" gives the instruction in this dump that fetches the bytes, by address; where the address is written as "none" the block is not fetched by any instruction of this disassembly and the row records its ROM provenance instead. | Address | Size | Name | Structure | Read by | |---------|------|------|-----------|---------| | `$8000-$804F` | 80 | `CopyrightText` | ASCII "COPYRIGHT 1986 RARE LTD. THE GREEN, ASHBY-DE-LA-ZOUCH, LEICESTERSHIRE, ENGLAND. " - the Rare Software credit | none - credit text only; nothing in the dump reads it | | `$80AE-$80DB` | 46 | `Sub_Loop` | 46 bytes that decode as instructions: a power-on routine that sets `PPUCTRL`, `PPUMASK`, `OAMDMA` and `APUSTATUS` before jumping to `$9C23` | none (unreached code; the tracer's own `Sub_Loop` label is a fall-through artefact) | | `$8142-$8165` | 36 | `GameStateHandlerTable` | 18 x 16-bit little-endian code pointers - the game-state dispatch | `lda $8142,x` at `$8135` and `lda $8143,x` at `$813A`; the pair goes to `Zp91`/`Zp92` and `jmp (Zp91)` at `$813F` | | `$8287-$829A` | 20 | *(unnamed)* | 10 x 16-bit values (`$0180`, `$016C`, `$0174`, `$017C`, `$0184`, `$018C`, ...), all multiples of 4 apart from the first - the look of a sprite Y-position table, but nothing in this dump reads it, so it is left unnamed | none (unreferenced data) | | `$8347-$8372` | 44 | `ObjectHandlerTable` | 22 x 16-bit code pointers - the per-object action dispatch | `lda $8347,y` at `$81C0` and `lda $8348,y` at `$81C5`; `jmp (Zp91)` at `$81CA` | | `$84C6-$84EB` | 38 | `SkiRecordTextTable` | the ASCII string " SKI RECORD j", then 5 x 16-bit pointers to the per-record strings, then " FAILED" | `lda $84C6,x` at `$8474` and `lda $84C7,x` at `$8479` (the pointer), `lda $84E4,x` at `$8496` (the text, byte by byte) | | `$85C5-$8623` | 95 | `PlayerNameScreenData` | the ASCII strings " PLAYER", "! NAME REGISTRATION", "!fA B C D E F G H I J", "! K L M N O P Q R S T", "\"&U V W X Y Z" - the name-entry screen | none in this dump (the screen is drawn by the code that follows) | | `$8624-$87A4` | 129 | *(unnamed)* | decodes as instructions (the name-entry screen routine) | none (unreached code) | | `$87A5-$87F7` | 83 | `PlayerNameScreenData` | 41 x 16-bit constants: `$FC00`, `$F480`, `$FD00`, `$FC80`, `$FE00`, `$8004`, `$08FF`, ... `$1800`-`$1890`, `$3000`-`$308C` - the screen positions the name-entry cursor is drawn at. The individual values are not further identified | none in this dump | | `$8828-$8876` | 79 | `WorldRecordTextTable` | the ASCII string "j WORLD RECORD TIMES j", then 4 x 16-bit pointers to the three course names, then the strings "SNOWY HILL", "STEEP PEAK" and "NASTY" | `lda $8828,x` at `$8819` (the text), `lda $8849,y` at `$88D3` and `$9CC6` plus `lda $884A,y` at `$88D8` and `$9CCB` (the pointers) | | `$8AD8-$8B25` | 78 | `RomSignatureAndKeyLayout` | the ASCII signature "SLALOM" plus 7 bytes of ROM checksum, then 8 records x 3 bytes of keyboard key groups ("CTJ", "ASD", "MA ", "JBN", "CSS", "CLW", "QWE", "RTY") | `lda $8AD8,x` at `$8A6F` (checksum compare) and `$8A7F` (checksum copy); `lda $8ADE,y` at `$8AB9`, `lda $8ADF,y` at `$8ABF` and `lda $8AE0,y` at `$8AC5` (the three bytes of each key record, copied to `$0603`-`$0605`) | | `$8B59-$8B7B` | 35 | *(unnamed)* | ASCII course record times: "85567", "77", "7955:", "855567", "79555:" | none (unreferenced data) | | `$8CA1-$8CA6` | 6 | `CharacterCharsetTable` | 6 CHR tile indices (`$27`, `$2C`, `$34`, `$3B`, `$3C`, `$37`) - the characters the game draws for the player/rival labels | `lda $8CA1,x` at `$8C94` and `lda $8CA2,x` at `$8C9A` - both written straight to `PPUDATA` | | `$8CE4-$8CF7` | 20 | `GameOverText` | the ASCII string " GAME OVER " followed by two zero bytes | none (unreferenced data) | | `$8FB3-$8FF2` | 64 | `CoursePathTable` | 32 records x 2 bytes: the skier's X position in pixels and the amount the terrain drops at that point (the second byte is negated by `eor #$FF` / `adc #$01` before use) | `lda $8FB3,x` at `$8C5E` and `sbc $8FB4,x` at `$8C66`; `lda $8FB3,x` at `$8ED0` and `lda $8FB4,x` at `$8ED6` | | `$8FF3-$9032` | 64 | *(part of `CoursePathTable`)* | a second run of 32 such records, used for the other half of the descent | `lda $8FF3,x` at `$8EED` and `lda $8FF4,x` at `$8EF3` | | `$9067-$9086` | 32 | `SkierMovementTable` | 32 bytes in eight groups of four: `01 02 03 03`, `01 02 03 03`, `01 02 03 03`, `68 68 68 68`, `01 6E 6F 6F` x3, `68 68 68 68` - the per-frame steering deltas | `lda $9067,x` at `$8E5F` | | `$9125-$9130` | 12 | `KeyboardInputMap` | 12 bytes (`$4D`, `$85`, `$86`, `$87`, `$2C`, `$2D`, `$71`, `$72`, `$88`, `$89`, `$8A`, `$8B`) - the keyboard codes the game accepts, in the order it polls them | `lda $9125,x` at `$90B1` -> `Zp63` | | `$9205-$925C` | 88 | `CourseSlopeTable` | 44 x 16-bit little-endian course-segment parameters; the pair at `$921D` is split by the reader into a 5-bit value (`and #$1F`) and a high byte | `lda $921D,x` at `$9160` and `lda $921E,x` at `$9167`; `lda $9205,y` at `$918A` | | `$9648-$966F` | 40 | `SkierSpeedTable` | 16 bytes of increasing increments (`00 05 0A 0F 14 19 1E 23 28 2D 32 37 3C 3C 3C 3C`) followed by 10 x 16-bit speed values (`$6058`, `$6070`, ...) | `sbc $9648,x` at `$9637` (the increment) and `lda $9658,x` at `$960B` (the 16-bit value) | | `$97F4-$97F9` | 6 | *(unnamed)* | ASCII "00((0" | none (unreferenced data) | | `$97FD-$97FF` | 3 | *(unnamed)* | three bytes that decode as instructions (`JSR $2018` / part of it) | none (unreached code) | | `$9804-$9805` | 2 | *(unnamed)* | two bytes that decode as instructions | none (unreached code) | | `$9822-$9823` | 2 | *(unnamed)* | two bytes that decode as instructions | none (unreached code) | | `$986B-$98CE` | 100 | `DecimalDigitTable` | the 100 values `$00` to `$63` in order - the number-to-two-digit conversion table | `lda $986B,x` at `$8986`, `$8995`, `$985E`; `lda $986B,y` at `$8C12`, `$8C26`, `$9EE0`, `$9EF4`, `$A431`, `$A44A`, `$A45E`, `$A477` and `$A48B` | | `$9A1D-$9A58` | 60 | `CourseLevelHeightTable` | 9 levels x 5 bytes: the height of each of the five gate rows, stepping down `$0F`, `$0E`, `$0D`, `$0C`, `$0B`, `$0A`, `$09`, `$08`; the last four bytes are the start of the following code | `lda $9A1D,y` at `$9996` | | `$9BDB-$9BE2` | 8 | `CourseDifficultyTable` | 8 bytes: `06 06 07 07 08 08 08 08` - the difficulty of each of the eight courses | `lda $9BDB,x` at `$9B3E` | | `$9CE9-$9D0A` | 34 | `PlayerSelectTextTable` | 4 x 16-bit pointers, then the ASCII strings " PLAYER 1" and " PLAYER 2" | `lda $9CEF,x` at `$83C5` and `lda $9CF0,x` at `$83CA`; `lda $9CE9,x` at `$9C4E` and `lda $9CEA,x` at `$9C57`; `ldy $9CF0,x` at `$9CAE` and `lda $9CEF,x` at `$9CB1` | | `$9E60-$9EAD` | 78 | `BonusScoreTextTable` | the ASCII strings "ER BONUS SCORE", "!FFAST TIME REWARDn", "! FREESTYLE POINTSn" and "\" TOTAL SOLO BONUSn" - the end-of-run score breakdown | none (unreferenced data) | | `$9F3C-$9F45` | 10 | `SpriteHandlerTable` | 5 x 16-bit code pointers | `lda $9F3C,x` at `$9F2F` and `lda $9F3D,x` at `$9F34` | | `$9FC8-$A337` | 880 | `TitleScreenGraphicsList` | a Namco-style graphics list: control bytes `$01`/`$02`/`$03` (a count, a fill, a run) followed by CHR tile bytes, with 16-bit VRAM addresses embedded; the same list format the other Rare titles use | `lda $9FC8,x` at `$8A21`, `$8A41` and `$8A5F`; `lda $9FC9,x` at `$8A27` and `$8A33`; `lda $9FC9,x` at `$8A4F`; `lda $A298,x` at `$A88D` | | `$A380-$A38B` | 12 | `SpriteTileIndexTable` | 12 CHR tile indices: `$E8`..`$EF` then `$F5`, `$F1`, `$F2`, `$F3` | `lda $A380,x` at `$A363` | | `$A4C9-$A4DE` | 22 | `TimeDigitTileTable` | 11 x 2-byte records: the tile drawn at the digit position and the tile drawn at the shadow position, one pair per digit value plus a zero terminator | `lda $A4C9,x` and `lda $A4CA,x` at `$8C1B`/`$8C21`, `$8C2D`/`$8C4B`, `$9EE9`/`$9EEF`, `$9EFB`/`$9F19`, and the same pair at `$A3C5`/`$A3CB`, `$A3DD`/`$A3E3`, `$A3F0`/`$A3F6`, `$A401`/`$A407`, `$A438`/`$A43E`, `$A453`/`$A459`, `$A465`/`$A46B`, `$A480`/`$A486`, `$A492`/`$A498` | | `$A6E0-$A818` | 313 | `TitleScreenGraphicsAndCredits` | a graphics list followed by the ASCII credit strings "©1986 RARE LTD", "LICENSED EXCLUSIVELY TO NINTENDO", "BY RARE COIN IT INC" and "OF NINTENDO" | `lda $A6E9,x` at `$A579` and `$A587`; `lda $A6E0,y` at `$A581` and `$A58D`; `lda $A739,x` at `$A5A4` | | `$A8DA-$A8DF` | 6 | *(unnamed)* | two 16-bit constants (`$5813`, `$B00F`) that are added to a running value; the same bytes also decode as instructions, so the block is most probably a mis-split of unreached code | `adc $A8DA,x` at `$A8B7` and `adc $A8DB,x` at `$A8D0` | | `$A998-$A999` | 2 | *(unnamed)* | two bytes (`$3A`, `$52`) that decode as undocumented 6502 opcodes | `lda $A998,x` at `$A8E2` - a single byte of the unreached code is picked up here | | `$A9C8-$AB75` | 430 | `PlayerSelectGraphicsList` | the ASCII strings "! 1 PLAYER GAME", "!k2 PLAYER GAME", "ESNOWY HILL", "M. NASTY" and "SSTEEP PEAK", then graphics lists and code | `lda $AA36,x` at `$A853` and `lda $AB36,x` at `$A85C`; `lda $AA15,y` at `$A8A4`, `$A8BE`, `$A8C5` and `$A8CC`; `adc $AA15,y` at `$A8B3`; `lda $AA26,x` at `$A8E9`, `$A8F4`, `$A8FC` and `$A904` | | `$AB9A-$AD59` | 448 | `AttributeTableData` | nametable attribute bytes: 16-byte rows of `$00`, `$A0`, `$AA`, `$FA`, `$FF`, `$50`, `$55` and the sprite palette blocks | `lda $ACDA,x` at `$839E` | | `$AD7D-$AE7C` | 256 | `CourseGraphicsList` | a graphics list of CHR tiles and letter shapes used to draw the course and the HUD | `lda $AD7D,x` at `$AD73`; `lda $ADED,x` at `$A5C7`; `lda $AE0D,x` at `$A5BB` | | `$AF00-$AF07` | 8 | `SpriteOamTemplateData` | 8 bytes copied into the sprite buffer page `$0400` | `lda $AF00,y` at `$AEF6` | | `$AF23-$AF2A` | 8 | `SpriteCountTable` | 8 bytes: `04 05 06 07 07 07 07 07` - how many sprites each character uses | `lda $AF23,x` at `$AF16` -> `Zp9A` | | `$B027-$B046` | 32 | `PaletteGradientTable` | 32 gradient steps: `$FC FC FD FD FD FE FE FE FE FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF` then eight zero bytes | `lda $B027,x` at `$B014`, index = (value & `$7F`) >> 2 | | `$B1C4-$B1CB` | 8 | `SoundHandlerTable` | 4 x 16-bit code pointers (`$B1DF`, `$B1D1`, `$B1D2`, `$B1D3`) - the sound-effect dispatch | `lda $B1C4,y` at `$B1B5` and `lda $B1C5,y` at `$B1BA`; `jmp (Zp91)` at `$B1C1` | | `$B328-$B337` | 16 | `TimeAndScoreTextData` | the ASCII strings "TIME TO BEAT", " +PLAYER 1" and " +PLAYER 2" | none in this dump | | `$B338-$B339` | 2 | *(part of `TimeAndScoreTextData`)* | a 16-bit coordinate pair (X and Y) for the text above | `lda $B338,x` at `$B321` and `ldy $B339,x` at `$B31E` | | `$B354-$B393` | 64 | *(part of `TimeAndScoreTextData`)* | 64 CHR tile bytes, one screen row of text | `lda $B354,x` at `$B2F7` - 64 bytes written to `PPUDATA` | | `$B374-$B3B3` | 64 | *(part of `TimeAndScoreTextData`)* | a second row of 64 CHR tile bytes | `lda $B374,x` at `$B304` - 64 bytes written to `PPUDATA` | | `$B4D6-$B5D5` | 256 | `CourseTextGraphicsList` | a graphics list holding the course names and the other text screens; the tiles are drawn with the same control-byte format as `$9FC8` | `lda $B536,x` at `$9C3F` - 32 bytes copied to `$0797` | | `$B664-$B6B3` | 80 | `GameEventHandlerTable` | 40 x 16-bit code pointers - the game-event dispatch | `lda $B664,x` at `$B60F` and the seven following bytes at `$B614`, `$B619`, `$B61E`, `$B623`, `$B628`, `$B62D` and `$B632` | | `$B717-$B73E` | 40 | `SoundEventHandlerTable` | 20 x 16-bit code pointers - the sound-event dispatch | `lda $B717,y` at `$B6C5` and `lda $B718,y` at `$B6CA` | | `$B73F-$B765` | 39 | *(part of `SoundEventHandlerTable`)* | a second table of 16-bit code pointers used by the routine at `$C48D` | `lda $B73F,y` at `$C492` and `lda $B740,y` at `$C497`; `jmp (Zp91)` at `$C49C` | | `$B78A-$B792` | 9 | `TimerControlData` | 9 bytes of timer constants; the first six are read into the per-sprite timer array at `$0780` | `lda $B78A,y` at `$B77E` | | `$B7B5-$B7BB` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B7BD-$B7C3` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B7EA-$B7F0` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B814-$B81A` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B82D-$B833` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B868-$B878` | 17 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B89A-$B8A0` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B8AF-$B8B5` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B8B9-$B8EE` | 54 | *(unnamed)* | decodes as instructions: a routine that reads the timer at `$076F`, selects an index and jumps to `$C49F` | none (unreached code) | | `$B90D-$B913` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B917-$B91D` | 7 | *(unnamed)* | bytes that decode as instructions | none (unreached code) | | `$B93F-$C44D` | 2831 | `MusicNoteData` | the music and sound-effect sequence data in the Namco command format: `$50`/`$57` start a note, `$51`/`$53` set its length, `$00` is a rest, and the small numbers that follow are the durations and the note indices | `lda $B93F,y` at `$B930` - the byte is stored to the per-voice slot at `$0780` | | `$C4AA-$C55B` | 178 | `SpriteRenderPointerTable` | 20 x 16-bit code pointers; the first points at `$C61F` and the rest at `$C5EF` | `lda $C4AA,y` at `$C476` and `lda $C4AB,y` at `$C47B`; `jmp (Zp91)` at `$C480` | | `$C55C-$C5D5` | 122 | `SpriteTileAttributeTable` | pairs of (tile, attribute) for the sprite draws | `lda $C55C,y` at `$C5F6` and `ora $C55D,y` at `$C601` | | `$C6EF-$FE09` | 14107 | *(several tables and code)* | the bulk of the PRG: traced code interleaved with many 16-bit code-pointer tables and the course data. The named sub-tables are listed in the rows that follow | see the rows below | | `$C6FA-$C6F9` | 2 | `CourseHandlerPointerTable` | a 16-bit code pointer (`$C74C`) | `lda $C6FA,x` at `$8179` and `lda $C6FB,x` at `$817E` | | `$C72B-$C851` | 295 | `CourseHeightProfileTable` | the terrain height profile: a run of increasing byte values (steps of 4 or 5) that give the height of the course at each point | `lda $C72B,y` (part of the same read as the handler table) | | `$C852-$C9CB` | 378 | `LevelHandlerPointerTable` | 16-bit code pointers to the per-level routines | `lda $C852,x` at `$899C` and `lda $C853,x` at `$89A1` | | `$C9CC-$D819` | 3404 | `SoundSequencePointerTable` | 16-bit code pointers to the sound-sequence routines | `lda $C9CC,x` at `$952D` and `lda $C9CD,x` at `$9532` | | `$D81A-$DED5` | 1476 | `ObjectBehaviourPointerTable` | 16-bit code pointers to the per-object behaviour routines | `lda $D81A,x` at `$A33A` and `lda $D81B,x` at `$A33F` | | `$DED6-$E3B1` | 1244 | `ObjectUpdatePointerTable` | 16-bit code pointers to the per-object update routines | `lda $DED6,x` at `$95D4` and `lda $DED7,x` at `$95D9` | | `$E3B2-$E4B1` | 256 | `SpriteDrawPointerTable` | 16-bit code pointers to the sprite-drawing routines | `lda $E3B2,x` at `$8C77`, `$93AE` and `lda $E3B3,x` at `$8C7C`, `$93B6` | | `$E4B2-$E4E9` | 56 | `SpriteAnimPointerTable` | 16-bit code pointers to the sprite-animation routines | `lda $E4B2,x` at `$93E6` and `lda $E4B3,x` at `$93EE` | | `$E4EA-$E5E9` | 256 | `SpriteMovePointerTable` | 16-bit code pointers to the sprite-movement routines | `lda $E4EA,x` at `$93D1` and `lda $E4EB,x` at `$93D9` | | `$E5EA-$FE09` | 1824 | `SpriteScorePointerTable` | 16-bit code pointers to the remaining sprite routines, then the rest of the traced code | `lda $E5EA,x` at `$93F4` and `lda $E5EB,x` at `$93FC` | | `$FE8D-$FF9F` | 275 | *(unnamed)* | a mixture of code and data: the routine at `$FE8D` reads the scroll registers, and the bytes at `$FF00` are a table read by the timer code | `lda $FF00,x` at `$917B`; `lda $FF00,y` at `$9975` and `$9AE8`; `adc $FF00,y` at `$997B`; `lda $FEE0,x` at `$B0E6`; `lda $FE8D,x` at `$FE0C` | | `$FFA7-$FFF2` | 76 | `CopyrightTextTail` | the same copyright credit as at `$8000`, with the two spaces of the original removed | none - credit text only | | `$FFF3-$FFF9` | 7 | *(unnamed)* | `$FF` padding | none | | `$FFFA-$FFFF` | 6 | *(unnamed)* | the three 6502 vectors: NMI `$8123`, RESET `$8050`, IRQ `$FEDF` | the CPU's hardware | ### Notes on the interpretation * The graphics lists (`$9FC8`, `$A6E0`, `$A9C8`, `$AD7D`, `$B4D6`) share the Namco/Rare control-byte format: a control byte, then a count, then the CHR tile bytes. The reader at `$A579` walks the `$A6E0` list and the reader at `$AD73` walks the `$AD7D` list, which is the evidence for the format. * `$8FB3` and `$8FF3` are read as pairs of bytes rather than as 16-bit words, and the second byte of each pair is negated before use (`eor #$FF` / `adc #$01` at `$8ED9`), so it is a signed drop amount. * The 7-byte and 17-byte blocks at `$B7B5`-`$B91D` and `$B868` all decode cleanly as 6502 instructions, so they are recorded as code the tracer could not reach rather than as tables. ## Entry points that are still named after their address **246 of the 284 address-derived entry points are still named `Sub_` or `SubC`.** The other 38 now carry a name taken from what the ROM shows them doing, and their `; Global:` lines were rewritten to say so. The residue is grouped below by *why* the dump does not reveal a better name. | Address | Why the dump does not reveal a better name | |---------|------------------------------------------| | `$8067`, `$81CD`, `$81D2`, `$81D4`, `$81D9`, `$81FD`, `$8206`, `$837E`, `$8496`, `$8819`, `$888A`, `$88A8`, `$88B3`, `$88FC`, `$8973`, `$899B`, `$89A8`, `$89B7`, `$89C9`, `$8A6D`, `$8B26`, `$8B7F`, `$8BA3`, `$8BA5`, `$8BDD`, `$8BE7`, `$8BEE`, `$8BF2`, `$8C86`, `$8CA7`, `$8CF8`, `$8D0C`, `$8D15`, `$8D1F`, `$8D35`, `$8D9E`, `$8DB6`, `$8DBD`, `$8E11`, `$8E22`, `$8E39`, `$8E65`, `$8EAD`, `$8ED9`, `$8F0F`, `$8F1C`, `$9033`, `$904E`, `$9087` | the screen and skier code. The game drives the screens through the handler tables (`GameStateHandlerTable`, `ObjectHandlerTable`, `CourseHandlerPointerTable`, `LevelHandlerPointerTable`, `SpriteHandlerTable`), and the entries of those tables are plain numbers that the ROM does not name in words | | `$8CC2`, `$8DDC`, `$8E7x`, `$8EA7`, `$8EE7` | the level and course set-up steps. They read the course tables (`CoursePathTable`, `CourseSlopeTable`, `CourseLevelHeightTable`, `CourseDifficultyTable`) and the dump shows the arithmetic, but not which of the game's courses each step belongs to | | `$8F0F`…`$90B8` | the skier's position and movement code: the 16-bit position in `$0702`/`$0703`, the frame counter in `$06`/`$07` and the split of the position into a screen and a course coordinate. The dump shows the arithmetic, not the game's word for the field | | `$9143`, `$9154`, `$91AD`, `$91E7`, `$925D`, `$92AF`, `$92C6`, `$9369`, `$93B9`, `$94D5`, `$952B`, `$954B`, `$955F`, `$95D1`, `$9613`, `$9620`, `$9670`, `$967D`, `$9760` | the course-lookup and drawing helpers. They read the course data through the pointer in `Zp8F`/`Zp90` and the tables at `$C852`, `$C9CC` and `$DED6`; the dump shows the table reads, not the game's word for the course feature each table holds | | `$9807`, `$9824`, `$9849`, `$985D`, `$98CF`, `$9917`, `$993F`, `$99C5`, `$99DA`, `$9A59`, `$9A64`, `$9A69` | the timer, the skier's records and the object spawn code. The timers are plain counters and the dump does not name the records they feed | | `$9Bxx`…`$B4xx` | the sprite, sound and event-handler code. The sound engine is well understood (it plays the `SoundNoteSequenceTable`), but the sprite and event tables are plain handler numbers | | `$B476`, `$B480`, `$B48E`, `$B49B`, `$B4A3`, `$B4AC`, `$B5D6`, `$B5D8`, `$B5FF`, `$B6B4`, `$B6B4`, `$B6CB` | the reset-time set-up: the RAM clear, the palette load, the PPU and OAM set-up and the sound driver start. Each of them does one obvious thing, but the dump does not say which of the game's screens they are preparing | | `$B0C3`, `$B419`, `$B426`, `$B438`, `$B476`… | the NMI-time work: the OAM copy, the palette update and the frame counters | | `$C44E`, `$C6CB`, `$C7A5`, `$C852`, `$C6FE`, `$CA4E`, `$CA86`, `$CA8A`, `$CA8D`, `$CA93`, `$CAFF`, `$CAB3`, `$CAC2`, `$CADE`, `$CAE7`, `$CAEA`, `$CAED`, `$CAFB`, `$CAFF` | the labels whose address does not match the four hex digits in their name: the pass-2 naming put a `C` in front of the address for the labels that sit in the second half of the code window. They are the same routines as the neighbouring `Sub_…` labels and are named the same way | | `$97F2`, `$97F3`, `$97FA`, `$97FB`, `$97FC` | five labels that sit on `BRK` bytes at the end of a data block. The tracer split them as instructions; they are not code at all and are left as they are rather than given a name that would claim otherwise | ## Build ``` Byte-identical ROM verified. ```