{ "_comment": "generated by tools/mergeSurvey.py from survey/*.json - do not edit by hand", "notes": { "0300": { "routine": [ "fastloaderMain - Entry point of the 1541 fast loader; the bootstrap sector (T1 s17) reads T1 s18-20 to $0300-$05FF and JMPs here. Idles the serial lines, sets the default track/sector ($06=18,$07=0), issues disk-controller job $B0 on buffer 0 and waits for it to finish, then falls into commandDispatchLoop.", "In: none (entered from the bootstrap)", "Out: zp_06=$12, zp_07=$00, zp_00 job issued; falls through to $0313" ], "unit": "drive/driveFastLoader" }, "0313": { "routine": [ "commandDispatchLoop - Top of the drive command loop. Resets the stack (SP=$45), receives a command byte from the host via receiveCommand, and dispatches: $C0 resets the drive (JMP through reset vector), $60 goes to handleWriteCommand, anything else is a read (receive track and sector, read the sector, send it back, then report status 0). Re-entered after every operation.", "In: command byte from receiveCommand", "Out: zp_50=0; branches to read/write/reset handlers" ], "unit": "drive/driveFastLoader" }, "0342": { "routine": [ "setHeadReadMode - Sets VIA2 PCR bits 1-3 (ORA #$0E) to put the read/write head electronics into read mode. Called by prepareHeadAndVerifyId before reading or writing a sector.", "In: VIA2_PCR", "Out: VIA2_PCR updated", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "034B": { "routine": [ "exchangeByteWithHost - Core full-duplex serial byte transfer with the C64. Clocks the byte in A out to the host one bit at a time (LSB first) on VIA1 serial bit1 while simultaneously shifting a received byte in on bit0, using a two-phase CLK/ACK handshake on bits 2/3. This is the drive-side counterpart of the C64 routine sendByteToDrive ($089C). Used for all command/parameter bytes, the status byte, and (in the write path) the 256 data bytes from the host.", "In: A = byte to send (into zp_90)", "Out: A = byte received from host (zp_8F); uses zp_14 as handshake temp; X clobbered" ], "unit": "drive/driveFastLoader" }, "0391": { "routine": [ "sendStatusAndLoop - Sends the status/error byte in A to the host via exchangeByteWithHost, then JMPs back to commandDispatchLoop. Every error path (header not found=$02, checksum=$05, write protect/id error=$08) jumps here with its code in A; the normal read path jumps here with A=0.", "In: A = status byte", "Out: status sent to host; loops to $0313" ], "unit": "drive/driveFastLoader" }, "0397": { "routine": [ "seekSectorAndSyncData - Finds the requested sector header on disk (findSectorHeader) then waits for and reads into the data-block sync (waitForSyncByte). Called at the start of readSectorFromDisk to position the read at the sector's data field.", "In: zp_3D drive index, zp_12/zp_13, zp_32 header pointer", "Out: positioned at data field; V clear, Y=0; error $02 via sendStatusAndLoop", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "039D": { "routine": [ "findSectorHeader - Builds the expected 8-byte GCR header image (from the id bytes zp_12/zp_13, the track/sector bytes via (zp_32), and their XOR checksum) with ROM_MAKE_HEADER_GCR into the zp_24 buffer, then reads raw GCR bytes from VIA2 comparing 8 bytes at a time. Returns when the matching header passes under the head; after $5A failed tries reports error $02. Also used by writeSectorToDisk to locate the sector before writing.", "In: zp_3D drive index, zp_12/zp_13 disk id bytes, zp_32 header ptr", "Out: header located; zp_16-zp_1A header scratch; error $02 via sendStatusAndLoop", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "03E3": { "routine": [ "waitForSyncByte - Arms VIA1 timer 1 as a timeout, waits for a SYNC mark on VIA2 (bit 7 of the disk-control port), then reads the first byte after sync from VIA2 and returns it. On timeout it branches to the error path ($02 via sendStatusAndLoop). Clears V and Y before returning.", "In: VIA1_T1, VIA2 disk port", "Out: A = byte after sync, V clear, Y=0; timeout -> error", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "03FB": { "routine": [ "readSectorFromDisk - Reads the sector named by zp_06/zp_07 from disk into buffer $0600: waits for the buffer-0 job, verifies the head/id (prepareHeadAndVerifyId), seeks to the data field (seekSectorAndSyncData), reads 256 GCR data bytes into $0600 plus the GCR overflow into $0100, converts GCR->binary and verifies the data checksum against zp_3A (error $05 on mismatch), then falls through to cryptSectorBuffer to decrypt. Invoked by the read branch of the command loop.", "In: zp_06 track, zp_07 sector, zp_31 buffer page", "Out: decrypted sector in $0600; zp_3A checksum; error $05 via sendStatusAndLoop" ], "unit": "drive/driveFastLoader" }, "044B": { "routine": [ "sendSectorToHost - Sends the 256 decrypted bytes in buffer $0600 back to the C64. Each byte is split into two nibbles, each nibble translated through nibbleSendTable and clocked out 4 bits at a time on the VIA1 serial port with a handshake (bit0 = clock). This bulk path is received by the C64 routine receiveSectorData ($0950). Ends via finishSendByte.", "In: $0600 buffer (256 decrypted bytes), nibbleSendTable", "Out: 256 bytes clocked to host; VIA1 serial port" ], "unit": "drive/driveFastLoader" }, "0490": { "routine": [ "handleWriteCommand - Write-command ($60) handler: receives the track and sector bytes from the host into zp_06/zp_07, calls writeSectorToDisk, then returns to commandDispatchLoop.", "In: track/sector from host via exchangeByteWithHost", "Out: sector written; loops to $0313" ], "unit": "drive/driveFastLoader" }, "04A0": { "routine": [ "writeSectorToDisk - Receives 256 data bytes from the host into $0600, encrypts them in place (cryptSectorBuffer, symmetric with decrypt), computes the data checksum into zp_3A, checks the write-protect sense (VIA2 bit 4; error $08 if protected), converts binary->GCR, positions on the header (findSectorHeader), switches VIA2 to write mode, writes the GCR overflow ($0100) and data (zp_30) fields, restores read mode, and sends the status byte. Called by handleWriteCommand.", "In: 256 bytes from host, zp_06/zp_07, zp_30 buffer ptr", "Out: sector written to disk, zp_3A checksum; error $08 via sendStatusAndLoop" ], "unit": "drive/driveFastLoader" }, "0525": { "routine": [ "prepareHeadAndVerifyId - Selects read mode (setHeadReadMode) and validates the drive id bytes: if zp_12 EOR zp_13 EOR $15 is nonzero it branches to the write-protect/id error path ($08). Called at the start of both readSectorFromDisk and writeSectorToDisk. The exact meaning of the $15 constant is a DOS id/consistency check.", "In: zp_12, zp_13", "Out: read mode set; error $08 via sendStatusAndLoop on mismatch", "(confidence: low)" ], "unit": "drive/driveFastLoader" }, "0531": { "routine": [ "cryptSectorBuffer - The sector cipher: XORs the 256 bytes in $0600 with a self-modifying rolling key (key0 = ROL((track|$C0)<<1 + sector + carry); key[y]=ROL(y EOR key)). Track 18 ($12) is left in plaintext (BAM/directory/map/setup). Symmetric, so the same routine decrypts on read and encrypts on write. This is the cipher documented in overview section 4.", "In: $0600 buffer, zp_06 track, zp_07 sector", "Out: $0600 XORed in place (except track 18)" ], "unit": "drive/driveFastLoader" }, "0553": { "routine": [ "uploadBytesToDrive - Code/data injection loop reached from receiveCommand when the host sends a count byte >= $F0: receives (256 - count) bytes and stores them consecutively into drive RAM starting at $0580 (the RTS-filled scratch area) using self-modifying stores, then falls through into receiveCommand again to fetch the real command. Lets the host push a small routine or table into the drive.", "In: count in patched $057E, bytes from host", "Out: bytes written to $0580+; re-enters receiveCommand", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "0561": { "routine": [ "receiveCommand - Receives one command/parameter byte from the host: clears a VIA2 status bit, sends $01 and receives a byte via exchangeByteWithHost, patches it into the LDA at $057D. If the byte is >= $F0 it is a byte-count preamble and control drops to uploadBytesToDrive to inject that many bytes into $0580 before looping back for the real command; otherwise the received byte is returned in A.", "In: host serial input", "Out: A = command byte", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "05DE": { "routine": [ "finishSendByte - Tail of sendSectorToHost: writes the final value in A to the VIA1 serial port and returns (leaves the serial lines in the idle state after a bulk read).", "In: A, VIA1 serial port", "Out: VIA1 serial port set; RTS", "(confidence: medium)" ], "unit": "drive/driveFastLoader" }, "05E2": { "routine": [ "checksumBufferAndReport - Small 6502 routine that the disassembler classified as data (it sits after an RTS and has no in-file caller). $05E2 does JSR $05E8 / JMP sendStatusAndLoop; $05E8 sums the 256 bytes of $0600 with a ROL+ADC accumulator and returns. Most likely a verify/checksum helper invoked by code injected via uploadBytesToDrive, or dead code. Followed by a hidden signature.", "In: $0600 buffer", "Out: A = rolling checksum, reported to host via sendStatusAndLoop", "(confidence: low)" ], "unit": "drive/driveFastLoader" }, "043B": { "unit": "drive/driveFastLoader", "block": [ "nibbleSendTable: byteTable, 16 bytes. 16-entry nibble translation table used by sendSectorToHost. Entry n = complement of the nibble n with its two outer bits swapped (0->$0F,1->$07,2->$0D,...). Encodes each nibble into the 4 serial bits sent to the C64 during a bulk read." ] }, "0582": { "unit": "drive/driveFastLoader", "block": [ "driveUploadScratch: byteTable, 92 bytes. $0582-$05DD filled with $60 (RTS). This is the RTS-filled scratch/patch area; uploadBytesToDrive stores injected bytes starting at $0580 into this region. Pre-filling with RTS makes any un-overwritten byte a harmless return." ] }, "05F4": { "unit": "drive/driveFastLoader", "block": [ "hiddenSignature: text, 12 bytes. Hidden signature bytes at the very end of the loader: ASCII fragments 'DaN' and 'SaRa' (Dan Bunten / family names) mixed with a couple of opcode-looking bytes. Not referenced; an easter-egg credit like the EA message in the bootstrap sector." ] } } }