388 lines
No EOL
11 KiB
JSON
388 lines
No EOL
11 KiB
JSON
{
|
|
"_comment": "Seed annotations written while reverse engineering the loader. Format: labels {hexAddr: name}, notes {hexAddr: {routine:[header lines], block:[comment lines before the address], line: 'end of line comment'}}, dataTypes {hexAddr: [type, length]} with type text|addr|word|byte, zp {hexAddr: [name, comment]}, driveZp likewise for the 1541 listings. Drive/raw-unit notes carry a 'unit' field.",
|
|
"entries": [
|
|
"09A6"
|
|
],
|
|
"labels": {
|
|
"0800": "gameEntry",
|
|
"0803": "loaderStatus",
|
|
"0804": "loadSectors",
|
|
"0808": "loadSectorsLoop",
|
|
"0820": "loadSectorOk",
|
|
"0830": "loadSectorNext",
|
|
"0840": "writeSectorsFail",
|
|
"0843": "writeSectors",
|
|
"0847": "writeSectorsLoop",
|
|
"085C": "setLoadDest",
|
|
"0863": "writeOneSector",
|
|
"088F": "sendSectorData",
|
|
"089C": "sendByteToDrive",
|
|
"08E8": "sendByteShift",
|
|
"08E9": "recvByteShift",
|
|
"08EB": "readOneSector",
|
|
"08FE": "readSectorBody",
|
|
"0943": "finishTransfer",
|
|
"0950": "receiveSectorData",
|
|
"0957": "receiveByteLoop",
|
|
"09A2": "loadDestLo",
|
|
"09A3": "loadDestHi",
|
|
"09A5": "savedSpriteEnable",
|
|
"09A6": "manualLookupCheck",
|
|
"0A1E": "wipeMemoryLoop",
|
|
"0A48": "msgIdentifyMap",
|
|
"0A6C": "mainStart",
|
|
"0B4F": "loadCommTailBuild1",
|
|
"0EFE": "loadRuntimeOverlays",
|
|
"0F31": "loadCommBuild2",
|
|
"0F41": "loadCommFinish",
|
|
"0F55": "loadSectorsRetry",
|
|
"0F81": "msgNotADataDisk",
|
|
"0F91": "msgInsertGameDisk",
|
|
"0FA2": "msgDiskError",
|
|
"0FAD": "diskIdTable",
|
|
"0FB1": "checkDiskId",
|
|
"1018": "diskErrorExit",
|
|
"1047": "loadOverlayA",
|
|
"1060": "loadStringsAndCommTail",
|
|
"1081": "loadOverlayBIfNeeded",
|
|
"1086": "loadOverlayB",
|
|
"10A4": "loadMapAndSetup",
|
|
"10DF": "waitForGameDisk",
|
|
"02B8": "eaLoadGame",
|
|
"02EC": "eaFileName"
|
|
},
|
|
"notes": {
|
|
"0800": {
|
|
"routine": [
|
|
"gameEntry - jumped to by the boot code at $02B8 after the fast loader has filled memory."
|
|
],
|
|
"line": "-> mainStart"
|
|
},
|
|
"0803": {
|
|
"line": "bit 7 = a read error occurred (cleared once reported)"
|
|
},
|
|
"0804": {
|
|
"routine": [
|
|
"loadSectors - read A consecutive sectors from track Y starting at sector X into the address set by setLoadDest.",
|
|
"In: A = sector count, Y = track, X = first sector. Out: C = 0. Destination advances one page per sector.",
|
|
"Private copy of the boot loader's $C004; on an error it shows msgDiskError and retries forever."
|
|
]
|
|
},
|
|
"0843": {
|
|
"routine": [
|
|
"writeSectors - write A consecutive sectors to track Y from sector X, source address set by setLoadDest.",
|
|
"In: A = count, Y = track, X = first sector. Out: C = 1 on failure, 0 on success."
|
|
]
|
|
},
|
|
"085C": {
|
|
"routine": [
|
|
"setLoadDest - X = low byte, Y = high byte of the next transfer address (patches loadDestLo/Hi)."
|
|
]
|
|
},
|
|
"0863": {
|
|
"routine": [
|
|
"writeOneSector - send command $60, track, sector and 256 data bytes to the drive, then read the status byte."
|
|
]
|
|
},
|
|
"089C": {
|
|
"routine": [
|
|
"sendByteToDrive - clock one byte to the drive 1 bit at a time through CIA2 port A bits 4/5 with a handshake on bits 6/7."
|
|
]
|
|
},
|
|
"08EB": {
|
|
"routine": [
|
|
"readOneSector - request track Y sector X from the drive (command $80) and receive 256 bytes. Out: C = 1 on error."
|
|
]
|
|
},
|
|
"0950": {
|
|
"routine": [
|
|
"receiveSectorData - the timing critical 2-bit receive loop. Sprites are disabled and bad lines avoided",
|
|
"by waiting for a raster line that is not a multiple of 8 (the operand at $095F is patched with $D011 & 7 + $2F)."
|
|
]
|
|
},
|
|
"09A6": {
|
|
"routine": [
|
|
"manualLookupCheck - copy protection: ask the player to identify a map from the manual.",
|
|
"Picks one of 32 three-byte answers from the table at $0401 (index patched into $09C4), prints msgIdentifyMap,",
|
|
"reads the player's answer into $5A-$5C and allows three tries; after that it erases all of memory and hangs."
|
|
]
|
|
},
|
|
"0A48": {
|
|
"line": "copy-protection prompt (bit 7 set on the last character terminates the string)"
|
|
},
|
|
"0A9B": {
|
|
"line": "was JSR manualLookupCheck ($20 A6 09); the opcode is $2C = BIT, so the manual check is disabled in this build"
|
|
},
|
|
"0EFE": {
|
|
"routine": [
|
|
"loadRuntimeOverlays - called once at start-up: $C000 <- track 30, then loadOverlayA, then the communications",
|
|
"module at $E000 (build 1 from track 35 when $0BA5 bit 7 is set, otherwise track 18 s7 + track 34)."
|
|
]
|
|
},
|
|
"0F55": {
|
|
"routine": [
|
|
"loadSectorsRetry - like loadSectors but first calls $C37F with A=8 (drive/UI housekeeping in the $C000 overlay)."
|
|
]
|
|
},
|
|
"0FB1": {
|
|
"routine": [
|
|
"checkDiskId - read the BAM (track 18 sector 0) into $0200 and compare the disk id with diskIdTable[X] (X=0 'OZ' game",
|
|
"disk, X=2 'EA' data disk). Copies the 10-byte serial at BAM offset $AB to $FFDE-$FFE7 for the game disk.",
|
|
"Out: C = 0 ok, C = 1 wrong disk / error (message already shown)."
|
|
]
|
|
},
|
|
"1047": {
|
|
"routine": [
|
|
"loadOverlayA - $6F00 <- track 31 s0-16, $8000 <- track 32 s0-7; falls through into loadStringsAndCommTail."
|
|
]
|
|
},
|
|
"1060": {
|
|
"routine": [
|
|
"loadStringsAndCommTail - $8800 <- track 29 s9-10 (messages), $EC00 <- track 34 s12-15."
|
|
]
|
|
},
|
|
"1086": {
|
|
"routine": [
|
|
"loadOverlayB - $6F00 <- track 33 s0-16, $8000 <- track 32 s8-15 (the variant the boot loader installs)."
|
|
]
|
|
},
|
|
"10A4": {
|
|
"routine": [
|
|
"loadMapAndSetup - $F000 <- track 18 s8-14 (battlefield map), $0200 <- track 18 s15-16 (saved setup block)."
|
|
]
|
|
},
|
|
"C004": {
|
|
"routine": [
|
|
"bootLoadSectors - read A sectors from track Y starting at sector X to the address set by bootSetDest.",
|
|
"The game keeps its own identical copy at $0804 because this page is overwritten by the $C000 overlay."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C03B": {
|
|
"routine": [
|
|
"bootSendByte - full-duplex 1-bit exchange: shifts the command byte out LSB first on CIA2 port A and shifts the drive's",
|
|
"reply in (LSB first, into $C088); returns the reply in A (Z set when it is 0)."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C0EF": {
|
|
"routine": [
|
|
"bootReceiveSectorData - 2-bit parallel receive loop; identical to $0950 in the game."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C145": {
|
|
"routine": [
|
|
"bootMain - entry from $02B8. Shows the title picture, initialises modem and drive, installs the drive code",
|
|
"(B-E of track 1 sector 17), banks out the ROMs and loads the game (see docs/overview.md section 2)."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C1B1": {
|
|
"line": "patched to PHA by bootShowTitlePicture (DEC $C1B1): pushes the RTS opcode ($60 read from bootDone) onto the stack at $01FD",
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C168": {
|
|
"line": "patched from STA abs,Y ($99) to TXS ($9A) by bootShowTitlePicture: S=$FD, so the return stack is $01FE/$01FF",
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C219": {
|
|
"line": "leftover strings from the shared EA loader ('GAMECHAR', 'HMEM'); unused here",
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C229": {
|
|
"routine": [
|
|
"rtiVector - NMI and IRQ vector target while the loader runs with the ROMs banked out."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C23F": {
|
|
"routine": [
|
|
"bootShowTitlePicture - clear VIC registers, copy colour RAM from $9800 and screen RAM $9C00 -> $8C00,",
|
|
"select VIC bank 2 and multicolour bitmap mode (bitmap at $A000)."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C2AB": {
|
|
"routine": [
|
|
"bootDriveInitialize - OPEN 15,8,15,\"I0\" then CLOSE (initialise the drive)."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C2DA": {
|
|
"routine": [
|
|
"bootModemInit - MEMTOP = $9700, OPEN 2,2,0 with RS-232 parameters $06/$00 (300 baud, 8N1) and send the",
|
|
"Hayes command ATE0S0=0 (echo off, no auto-answer) so a connected modem is quiet while the game loads."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C32C": {
|
|
"routine": [
|
|
"bootBlockExecute - open a buffer channel (\"#\" on channel 2) and send \"B-E 2 0 1 17\" on the command channel:",
|
|
"the drive loads track 1 sector 17 and executes it, which installs the fast loader in the drive."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"C372": {
|
|
"block": [
|
|
"$C372-$C3FF: leftover code from the shared EA loader (references $BCC8/$BE6D/$CBED/$CBF2 that do not exist",
|
|
"in this build). Not reachable from the boot path."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"02B8": {
|
|
"routine": [
|
|
"eaLoadGame - reached through the hijacked BASIC vectors: SETLFS 8,1 / SETNAM \"LOAD\" / LOAD, then JSR $C000, JMP $0800."
|
|
],
|
|
"unit": "boot/ea"
|
|
},
|
|
"02AA": {
|
|
"block": [
|
|
"$02A8-$02B7: a never-executed tokenised BASIC line (10 LOAD\"EA\",8,1) left in the file as filler."
|
|
],
|
|
"unit": "boot/ea"
|
|
},
|
|
"C218": {
|
|
"routine": [
|
|
"bootDone - RTS, but the stack was rebuilt ($01FD=$60 via PHA, $01FE=$04 from $C26F): the return address on the stack is $0460,",
|
|
"so execution continues at $0461 in the $0400 block (a memory checksum routine that ends with JMP $0800) and never",
|
|
"returns to eaLoadGame's JMP $0800."
|
|
],
|
|
"unit": "boot/fastLoaderC000"
|
|
},
|
|
"0B25": {
|
|
"line": "filename field of the boot sector ($A0 = shifted space, then terminator); the C128 KERNAL skips it and enters at $0B27",
|
|
"unit": "boot/c128boot_T1S0"
|
|
}
|
|
},
|
|
"dataTypes": {
|
|
"0A48": [
|
|
"text",
|
|
36
|
|
],
|
|
"0F81": [
|
|
"text",
|
|
16
|
|
],
|
|
"0F91": [
|
|
"text",
|
|
17
|
|
],
|
|
"0FA2": [
|
|
"text",
|
|
11
|
|
],
|
|
"0FAD": [
|
|
"text",
|
|
4
|
|
],
|
|
"C219": [
|
|
"text",
|
|
9
|
|
],
|
|
"C222": [
|
|
"text",
|
|
5
|
|
],
|
|
"C2D8": [
|
|
"text",
|
|
2
|
|
],
|
|
"C320": [
|
|
"byte",
|
|
2
|
|
],
|
|
"C322": [
|
|
"text",
|
|
10
|
|
],
|
|
"C35F": [
|
|
"text",
|
|
13
|
|
],
|
|
"C36C": [
|
|
"text",
|
|
2
|
|
],
|
|
"C3C0": [
|
|
"text",
|
|
4
|
|
],
|
|
"02EC": [
|
|
"text",
|
|
4
|
|
],
|
|
"0B25": [
|
|
"byte",
|
|
2
|
|
]
|
|
},
|
|
"zp": {
|
|
"E0": [
|
|
"ldTrack",
|
|
"loader: current track"
|
|
],
|
|
"E1": [
|
|
"ldSector",
|
|
"loader: current sector"
|
|
],
|
|
"E2": [
|
|
"ldDestPtr",
|
|
"loader: destination pointer (lo)"
|
|
],
|
|
"E3": [
|
|
"ldDestPtrHi",
|
|
"loader: destination pointer (hi)"
|
|
],
|
|
"E4": [
|
|
"ldCia2Bits",
|
|
"loader: CIA2 port A bits 0-1 (VIC bank) kept during the transfer"
|
|
],
|
|
"E5": [
|
|
"wrSrcPtr",
|
|
"loader: write source pointer (lo)"
|
|
],
|
|
"E6": [
|
|
"wrSrcPtrHi",
|
|
"loader: write source pointer (hi)"
|
|
],
|
|
"E7": [
|
|
"ldCount",
|
|
"loader: sectors left to transfer"
|
|
]
|
|
},
|
|
"unitLabels": {
|
|
"boot/fastLoaderC000": {
|
|
"C000": "bootEntry",
|
|
"C003": "bootLoaderStatus",
|
|
"C004": "bootLoadSectors",
|
|
"C034": "bootSetDest",
|
|
"C03B": "bootSendByte",
|
|
"C08A": "bootReadOneSector",
|
|
"C09D": "bootReadSectorBody",
|
|
"C0EF": "bootReceiveSectorData",
|
|
"C141": "bootDestLo",
|
|
"C142": "bootDestHi",
|
|
"C144": "bootSavedSprites",
|
|
"C145": "bootMain",
|
|
"C218": "bootDone",
|
|
"C219": "strGameChar",
|
|
"C222": "strHmem",
|
|
"C229": "rtiVector",
|
|
"C22A": "bootDisableIrqs",
|
|
"C23F": "bootShowTitlePicture",
|
|
"C2AB": "bootDriveInitialize",
|
|
"C2CA": "bootWaitFrames",
|
|
"C2D8": "strInitDrive",
|
|
"C2DA": "bootModemInit",
|
|
"C320": "rs232Params",
|
|
"C322": "strHayesInit",
|
|
"C32C": "bootBlockExecute",
|
|
"C341": "bootSendDosCommand",
|
|
"C35F": "strBlockExecute",
|
|
"C36C": "strBufferChannel",
|
|
"C371": "bootSavedCpuPort",
|
|
"C3C0": "bootDiskIdTable"
|
|
}
|
|
}
|
|
} |