{ "chunk": "boot_ea_02A8", "unit": "boot/ea", "routines": [ { "addr": "02B8", "name": "eaLoadGame", "summary": "Stage-1 boot stub reached through the hijacked BASIC vectors (normally IMAIN at $0302 after BASIC prints READY. following LOAD\"EA\",8,1). Sets logical file 8 / device 8 / secondary address 1, names the file \"LOAD\" (4 chars at $02EC), clears the KERNAL message flag so no SEARCHING/LOADING text appears, then KERNAL-LOADs \"load\" to its own header address $9800-$C3FF. On success it JSRs the boot loader entry at $C000 (-> bootMain $C145, which shows the title picture, installs the drive fast loader and fills $0800+ with the game) and finally JMPs to gameEntry $0800. On a LOAD error (C=1) it skips the boot loader and jumps to $0800 anyway - the original error handler that followed was patched away (see $02D8).", "inputs": "none (entered by JMP via the BASIC vector table, BASIC stack in place); reads filename at $02EC", "outputs": "never returns; zp $9D (MSGFLG) = 0; memory $9800-$C3FF loaded; then $C000 boot path and JMP $0800", "confidence": "high" }, { "addr": "02DA", "name": "deadLoadErrorRetry", "summary": "Unreachable remnant of the original load-error handler. Decodes as LDA #$12 / STA $0401 / STA $0402 / STA $0404 / LDA #$0F / STA $0403 / BNE $02B8, i.e. writes screen codes 'R','R','O','R' into the top-left screen row (the preceding LDA #$05 / STA $0400 = 'E' was overwritten by the JSR $C000 + JMP $0800 patch, leaving the orphaned operand bytes $00,$04 at $02D8-$02D9) and then loops back to retry the whole load. The BCS at $02D0 originally landed here; in this build it lands on JMP $0800 instead.", "inputs": "none", "outputs": "would write screen RAM $0400-$0404 and branch to $02B8; never executed in this build", "confidence": "medium" } ], "variables": [ { "addr": "9D", "scope": "zp", "name": "kernalMsgFlag", "meaning": "KERNAL MSGFLG: bit 7 enables control messages (SEARCHING FOR / LOADING), bit 6 enables error messages. eaLoadGame stores 0 so the LOAD is silent. Only written here; not a game variable.", "confidence": "high" }, { "addr": "0300", "scope": "abs", "name": "basicErrorVector", "meaning": "BASIC IERROR vector. In this file it is part of the 6-vector hijack table (all = $02B8); at run time the game reloads $0200-$03FF from track 18 s15-16 and $0300 then holds startup code called from $0A87 (that is what the XREF label sub_0300 refers to).", "confidence": "high" }, { "addr": "0302", "scope": "abs", "name": "basicMainVector", "meaning": "BASIC IMAIN vector (JMP ($0302) at $A480 after READY.). This is the vector that actually transfers control to eaLoadGame after LOAD\"EA\",8,1 finishes in direct mode.", "confidence": "high" } ], "dataBlocks": [ { "addr": "02A8", "length": 16, "type": "unknown", "name": "strayBasicStub", "description": "Tokenised BASIC program text: link $080D, line 10, token $93 LOAD, \"EA\",8,1, $00, then $00,$00 end-of-program. Formatted as if it lived at $0801 (the link only matches a 12-byte line, e.g. LOAD\"EA\",8 without ,1, so it was probably edited by hand). Never executed - it merely pads the file so that the vector table lands on $0300. The seed note places the line at $02AA; it really begins at $02A8 with its link word." }, { "addr": "02D8", "length": 20, "type": "unknown", "name": "leftoverErrorHandler", "description": "$02D8-$02D9 = orphaned operand ($0400) of an overwritten STA $0400; $02DA-$02EB = valid but unreachable 6502 code that writes 'ERROR' screen codes to $0400-$0404 and BNEs back to $02B8 (see routine deadLoadErrorRetry)." }, { "addr": "02EC", "length": 4, "type": "text", "name": "eaFileName", "description": "\"LOAD\" - PETSCII name of the 45-block second-stage file passed to SETNAM (length 4)." }, { "addr": "02F0", "length": 16, "type": "unknown", "name": "fileNamePadding", "description": "\"00\" ($30,$30) followed by 14 zero bytes; probably the tail of a longer name from the mastering template (e.g. LOAD00) plus padding up to the vector table. Unused." }, { "addr": "0300", "length": 12, "type": "wordTable", "name": "basicVectorHijack", "description": "Six little-endian words, all $02B8, overwriting the BASIC vectors IERROR $0300, IMAIN $0302, ICRNCH $0304, IQPLOP $0306, IGONE $0308, IEVAL $030A. Whichever path BASIC takes after the LOAD (READY main loop, an error, tokenising, listing, executing, evaluating) ends up in eaLoadGame. The table extends to $030B, 4 bytes past the nominal chunk end, but is fully contained in lines 19-55 of the file." } ], "misclassified": [ { "addr": "0300", "length": 12, "actual": "data", "evidence": "Labels sub_0300 / D_0301 / D_0302 / D_0304 / D_0307 are imported from unit game/setup_0200 (call:0A87, writes from the $6F00 overlay). In the ea file these bytes are the BASIC vector table ($B8,$02 x6), not code; the label names and the odd .byte grouping are a cross-unit artefact. Likewise D_02AB (r:0FF3) and L_02D5 refer to runtime contents of the reloaded $0200 block, not to this file." }, { "addr": "02DA", "length": 18, "actual": "code", "evidence": "Bytes A9 12 8D 01 04 8D 02 04 8D 04 04 A9 0F 8D 03 04 D0 CC decode to a coherent instruction stream ending in BNE $02B8 (offset $CC from $02EC = $02B8, exactly the routine start). Dead code, so keeping it as .byte is harmless, but it is code by origin." } ], "insights": [ "Boot chain, stage 1: LOAD\"EA\",8,1 puts this 100-byte image at $02A8-$030B. BASIC prints READY. and executes JMP ($0302) -> $02B8. eaLoadGame then loads \"LOAD\" ($9800-$C3FF, secondary address 1 so the file header supplies the address), JSR $C000 (bootEntry = JMP bootMain $C145), JMP $0800 (gameEntry -> mainStart $0A6C).", "The boot loader at $C000 returns to $02D5, so $02B8-$02D7 must survive the fast load; it does because the loader only fills $0800+ and the high pages. The game itself later overwrites $0200-$03FF from track 18 s15-16 (sub_10BB at $0A84) and then calls the new $0300 code at $0A87 - every XREF hit on $02AB/$02D5/$0300-$0307 concerns that runtime block, not this file.", "The load-error path is effectively broken: BCS $02D0 -> JMP $0800 with nothing loaded. Inferred (medium confidence): because the ROMs are still banked in and $0800 holds $00, the resulting BRK goes through the KERNAL BRK handler -> BASIC warm start -> JMP ($0302) -> $02B8, so in practice a failed load just retries; RUN/STOP-RESTORE during the KERNAL LOAD does the same since only the $0314+ KERNAL vectors are restored, never the $0300 BASIC vectors.", "$02D8-$02EB is a fossil of the generic EA loader template: an 'ERROR' screen-code writer plus retry loop that was overwritten when JSR $C000 / JMP $0800 were patched in. The first 16 bytes of the file ($02A8) are an equally unused tokenised '10 LOAD\"EA\",8,1' BASIC line.", "MSGFLG ($9D) = 0 is the only zero-page write in the chunk; it is a KERNAL variable, not game state, and should not be given a game-specific name in zeropage.inc." ] }