{
 "chunk": "boot_c64CartridgeStub8000_8000",
 "unit": "boot/c64CartridgeStub8000",
 "unitLabels": {
  "boot/c64CartridgeStub8000": {
   "8000": "cartHeader",
   "8004": "cbm80Signature",
   "8009": "cartColdStart",
   "800F": "clearLowRamLoop",
   "8061": "eaFileNameCart",
   "8065": "cartLoadEaFile",
   "806B": "cartTailFiller"
  }
 },
 "dataTypes": {
  "8000": [
   "addr",
   2
  ],
  "8002": [
   "addr",
   2
  ],
  "8004": [
   "byte",
   5
  ],
  "8061": [
   "text",
   4
  ],
  "806B": [
   "byte",
   8
  ],
  "8073": [
   "byte",
   4
  ]
 },
 "notes": {
  "8000": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "cartHeader ($8000-$8008) - the 9-byte autostart cartridge header the C64 KERNAL looks for.",
    "$8000/$8001 = cold-start vector, $8002/$8003 = warm-start (NMI) vector, $8004-$8008 = the",
    "signature 'CBM80'.  Both vectors point at $8009, so RESET and RESTORE do exactly the same thing.",
    "This is RAM, not ROM: the C128 boot sector at $0B27 copies 256 bytes from $0B89 to $8000-$80FF",
    "and then calls GO64 ($FF4D).  The C64 reset code ($FCE4: SEI / TXS / CLD) calls the signature",
    "check at $FD02, finds CBM80 here, and takes the JMP ($8000) at $FCEC - which skips IOINIT,",
    "RAMTAS, RESTOR and CINT entirely.  cartColdStart has to redo all four by hand.",
    "On the plain C64 path (LOAD\"EA\",8,1) none of this exists and $8000 is just free RAM."
   ],
   "line": "cold-start vector -> cartColdStart ($8009); taken by the KERNAL reset at $FCEC"
  },
  "8002": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "warm-start vector, also $8009: the KERNAL NMI handler ($FE47) jumps here when RESTORE is pressed, so RESTORE restarts the whole boot"
  },
  "8004": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "cbm80Signature ($8004-$8008) - the five magic bytes $C3 $C2 $CD $38 $30 = 'C'|$80, 'B'|$80,",
    "'M'|$80, '8', '0'.  The KERNAL's cartridge test at $FD02 compares these against its own copy at",
    "$FD10; a match is what makes both the reset and the NMI vector through $8000/$8002.  Not a",
    "string in the game's own format (no bit-7 terminator) - the high bits are part of the magic."
   ],
   "line": "'CBM80' with bit 7 set on the first three characters - the autostart magic tested by $FD02"
  },
  "8009": {
   "unit": "boot/c64CartridgeStub8000",
   "routine": [
    "cartColdStart - Cold/warm start of the CBM80 pseudo-cartridge that the C128 boot sector plants at $8000 before GO64.  Because the KERNAL reset jumps through the $8000 vector before it runs IOINIT/RAMTAS/RESTOR/CINT, this routine performs all of them itself (I/O init, clear $0002-$0101 and $0200-$03FF, MEMTOP=$A000, MEMSTR=$0800, HIBASE=$0400, RESTOR, CINT), blanks the screen in blue, initialises the drive with a DOS 'I' command, then SETNAMs \"0:EA\" and falls through cartLoadEaFile into the normal boot chain.  It never returns.",
    "In:  Nothing in registers (entered from the KERNAL reset at $FCEC via JMP ($8000), or from the NMI handler at $FE4D via JMP ($8002) if RESTORE is pressed).  Requires the C128 boot sector's helper routines at $0B45 (open command channel) and $0B55 (send DOS command) to still be in RAM - they are, because the reset skipped RAMTAS and the clear loop below stops at $03FF.",
    "Out: $0002-$0101 and $0200-$03FF zeroed; MEMSIZ $0283/$0284 = $A000; MEMSTR high $0282 = $08; HIBASE $0288 = $04; KERNAL indirect vectors restored; screen editor initialised; VIC_BORDER = VIC_BG0 = 6 (blue); VIC_CTRL1 bit 4 (DEN) cleared so the display is blank; drive initialised and logical file 15 closed; stack pointer = $F0; A = 0 for the LOAD.  Does not return - control ends up at $02B8 (eaLoadGame).",
    "Called from: nobody in this disassembly - only the C64 KERNAL reset/NMI, through the vectors at $8000/$8002.  (The XREF entries for L_8059/L_805C/L_8065/L_806A come from game/mapGenerator6F00 and game/comcenScreens6F00, which are different code loaded over these addresses at run time.)",
    "Note: unlike the real RAMTAS this does not set the tape buffer pointer $B2/$B3 = $033C (harmless - the game never touches tape), and it never executes CLI, so the I flag set by the reset's SEI at $FCE4 is only cleared later, inside the KERNAL's own serial routines."
   ],
   "line": "IOINIT ($FF84): set up CIA1/CIA2 (keyboard, serial bus, jiffy timer) and the SID/VIC defaults the reset skipped"
  },
  "800C": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "$00 = the fill value for the low-RAM clear below"
  },
  "800E": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "Y = 0: first of the 256 offsets to clear"
  },
  "800F": {
   "unit": "boot/c64CartridgeStub8000",
   "routine": [
    "clearLowRamLoop - Not a callable routine, just the body of the clear loop inside cartColdStart.  One pass of Y = 0..255 writes $00 through three absolute,Y stores, clearing $0002-$0101, $0200-$02FF and $0300-$03FF.  It is a byte-for-byte copy of the clear loop at the head of the KERNAL's RAMTAS ($FD54), which the reset did not run.",
    "In:  A = 0 (fill value), Y = 0 (index)",
    "Out: $0002-$0101, $0200-$03FF all zero; Y = 0 again on exit; A still 0",
    "Called from: fall-through from $800E, and its own BNE at $8019.",
    "The clear deliberately stops at $03FF: $0400 upwards holds the C128 boot sector's code and its still-needed helpers at $0B45/$0B55, and $0000/$0001 (the 6510 CPU port) are skipped because the first store is at $0002."
   ],
   "line": "clear $0002+Y - absolute,Y, so the last two passes spill into $0100/$0101; $00/$01 (CPU port) are never touched"
  },
  "8012": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "clear $0200+Y - BASIC input buffer and the KERNAL workspace ($0282 MEMSTR, $0288 HIBASE included; both are rewritten below)"
  },
  "8015": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "clear $0300+Y - the vector page; RESTOR at $802D refills $0314-$0333 afterwards"
  },
  "8018": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "advance to the next of the 256 offsets"
  },
  "8019": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "loop until Y wraps back to 0, i.e. all 256 offsets of all three pages are cleared"
  },
  "801B": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "Rebuild the power-on memory layout that RAMTAS would normally have measured and stored.  The",
    "values are simply hardcoded rather than RAM-tested: top of memory $A000, bottom of user memory",
    "$0800, screen page $0400.  RESTOR and CINT then repair the vectors and the editor that the clear",
    "loop above just wiped."
   ],
   "line": "top-of-memory low byte = $00"
  },
  "801D": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "top-of-memory high byte = $A0, i.e. MEMTOP = $A000 (the standard C64 value; $A000-$BFFF later holds the title bitmap)"
  },
  "801F": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "C = 0 selects the 'set' direction of MEMTOP (C = 1 would read it back)"
  },
  "8020": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "MEMTOP ($FF99): store $A000 into MEMSIZ $0283/$0284"
  },
  "8023": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "page $08 = the standard start of user RAM"
  },
  "8025": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "MEMSTR high byte $0282 = $08 -> bottom of memory $0800 (its low byte $0281 is already 0 from the clear loop)"
  },
  "8028": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "page $04 = the default text screen"
  },
  "802A": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "HIBASE $0288 = $04 so CINT below points the screen editor at $0400"
  },
  "802D": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "RESTOR ($FF8A): reload the KERNAL indirect vectors $0314-$0333, which the clear loop had zeroed"
  },
  "8030": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "CINT ($FF81): program the VIC from the KERNAL's default table, clear screen RAM at $0400 and reset the editor"
  },
  "8033": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "Hide the load.  CINT has just switched on a normal blue-on-blue text screen, so paint border and",
    "background the same colour and then turn the display off completely; the player sees a plain blue",
    "screen until the boot loader at $C145 sets VIC_CTRL1 = $3B and shows the title bitmap."
   ],
   "line": "colour 6 = blue"
  },
  "8035": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "VIC_BORDER ($D020) = blue"
  },
  "8038": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "VIC_BG0 ($D021) = blue as well, so no text can show through"
  },
  "803B": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "read VIC_CTRL1 ($D011) - the raster/mode register CINT just initialised to $1B"
  },
  "803E": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "clear bit 4 (DEN, display enable); the other bits (RSEL, YSCROLL, raster MSB) are left alone"
  },
  "8040": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "write it back: screen blanked ($D011 = $0B) for the whole loading sequence"
  },
  "8043": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "Reset the drive.  Both calls go to routines that belong to the C128 boot sector and are still",
    "sitting in RAM at $0B45/$0B55 - the KERNAL reset skipped RAMTAS and this stub only cleared up to",
    "$03FF, so they survived GO64.  The SETLFS inside $0B45 (lfn 15, device 8, secondary 15) also sets",
    "up the logical-file variables that the LOAD at $8065 later inherits.",
    "Note that these are NOT the game's own $0B45/$0B55 - the main program's code at $0B00 only exists",
    "after the fast loader has run, long after this stub is dead."
   ],
   "line": "c128OpenCommandChannel ($0B45): SETNAM length 0 / SETLFS 15,8,15 / OPEN -> drive command channel open"
  },
  "8046": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "drive-command index 2 = the string \"I\" at $0B87 (DOS INITIALIZE); index 0/1 are the 1571 commands the C128-mode code already sent"
  },
  "8048": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "c128SendDriveCommand ($0B55): CHKOUT 15, send \"I\" byte by byte, CLRCHN - the drive re-reads the BAM and clears any pending error"
  },
  "804B": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "logical file 15 = the command channel just used"
  },
  "804D": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "CLOSE ($FFC3): shut the command channel; the KERNAL leaves the current-file variables $B8/$B9/$BA at 15 / 15 / 8, which is exactly what the LOAD below needs"
  },
  "8050": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "Name the stage-1 file and hand over.  The filename is stored inline four bytes further on, so the",
    "pointer passed to SETNAM points back into this routine.  No SETLFS is issued: the device (8) and",
    "the non-zero secondary address (15) left over from the command channel are what make LOAD honour",
    "the load address in the file's own header."
   ],
   "line": "filename length = 4 characters"
  },
  "8052": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "filename pointer low byte $61"
  },
  "8054": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "filename pointer high byte $80 -> eaFileNameCart at $8061, embedded in this very routine"
  },
  "8056": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "SETNAM ($FFBD): filename = \"0:EA\""
  },
  "8059": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "stack pointer value $F0 (the reset had set $FF)"
  },
  "805B": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "SP = $F0, i.e. stack top $01F0; safe because nothing on the stack is ever needed again - this code never returns.  Probably just copied from EA's generic cartridge template"
  },
  "805C": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "A = 0 tells LOAD to load (A = 1 would mean verify)"
  },
  "805E": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "jump over the four inline filename bytes at $8061 into cartLoadEaFile"
  },
  "8061": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "eaFileNameCart ($8061-$8064) - 4 bytes of plain PETSCII, \"0:EA\": drive 0, file \"EA\" (the 1-block",
    "directory file that loads to $02A8-$030B).  Length-counted by SETNAM, so there is no terminator",
    "and no bit-7 flag.  It sits in the middle of the code and is stepped over by the JMP at $805E."
   ],
   "line": "\"0:EA\" - drive number, colon, filename; passed to SETNAM as X=$61 / Y=$80 / A=4"
  },
  "8065": {
   "unit": "boot/c64CartridgeStub8000",
   "routine": [
    "cartLoadEaFile - Tail of cartColdStart, reached by the JMP at $805E that steps over the inline filename.  KERNAL-LOADs \"0:EA\" and jumps straight into it.  Because the secondary address inherited from the command channel is 15 (non-zero), LOAD uses the two-byte load address in the file itself, so \"ea\" lands at $02A8-$030B; the JMP then enters eaLoadGame at $02B8 by hand.  On the ordinary C64 path that entry happens indirectly, through the BASIC vectors that \"ea\" overwrites at $0300-$030B - here BASIC never runs at all, which is why the jump is explicit.  The carry/error result of LOAD is discarded: a load failure runs whatever happens to be at $02B8.",
    "In:  A = 0 (load, not verify); filename set by the SETNAM at $8056; device 8 / secondary 15 left in $B8/$B9/$BA by $0B45 and the CLOSE at $804D",
    "Out: $02A8-$030B filled from disk; control passes to $02B8 (eaLoadGame), which SETLFS 8,8,1, loads the 45-block file \"LOAD\" to $9800-$C3FF, JSRs the boot loader at $C000 and finally JMPs to the game at $0800.  Never returns.",
    "Called from: only the JMP at $805E."
   ],
   "line": "LOAD ($FFD5): pull \"0:EA\" from device 8; secondary 15 means 'use the file's own load address' -> $02A8-$030B"
  },
  "8068": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "enter eaLoadGame at $02B8 directly, skipping the BASIC-vector hijack that the C64 path relies on; C (LOAD error) is ignored"
  },
  "806B": {
   "unit": "boot/c64CartridgeStub8000",
   "block": [
    "cartTailFiller ($806B-$8076) - 12 dead bytes, never referenced by anything.  A $00 followed by",
    "8E 72 17 / 8E 73 17 / 8E 70 17 / 8E 71, which disassembles as STX $1772 / STX $1773 / STX $1770 /",
    "STX $1771 with the last operand byte cut off.  These are simply the last bytes ($F4-$FF) of track",
    "1 sector 0 that the C128 boot sector's 256-byte copy loop dragged along with the real cartridge",
    "image; they look like leftovers in the mastering system's buffer, the same way track 1 sector 16",
    "still holds fragments of assembler source text.  Execution can never reach them (the routine",
    "above ends in a JMP), and at run time the whole $8000-$87FF block is overwritten by the $6F00",
    "overlay's upper half anyway."
   ],
   "line": "leftover mastering-buffer bytes: $00, then STX $1772 / STX $1773 / STX $1770 ..."
  },
  "8073": {
   "unit": "boot/c64CartridgeStub8000",
   "line": "... and the truncated STX $1771 that ends the sector; dead filler, never referenced"
  }
 }
}
