; Amdek AMDC-I/II v1.1 firmware disassembly (rev.0.9, CRC32 904CC6B5)
; Disassembled by Avery Lee
;
;===============================================================================
; Hardware memory map
;
; $0000-03FF    1K static RAM (2 x MM2114N)
; $0800   (R)   Read strobe?
; $1000         Printer port?
;   D7    (R)   Printer BUSY (1 = busy)
;   D6    (R)   Printer SELECT (0 = printer present)
;   D5    (R)   AMDC-II flag (1 = second internal drive present)
;   D4    (R)   Diagnostic mode switch (0 = diagnostic mode)
; $1800         Parallel printer data port
; $2000         MC6850 ACIA control/status register
;   D7    (W)   Receive interrupt enable
;   D6:D5 (W)   Transmit control (00 = /RTS low, disable transmit IRQ)
;   D4:D2 (W)   Word select (101 = 8 data bits + 1 stop bit)
;   D1:D0 (W)   Counter divide select (00=/1, 01=/16, 10=/64, 11=reset)
;   D7    (R)   /IRQ
;   D6    (R)   Parity error
;   D5    (R)   Receiver overrun
;   D4    (R)   Framing error
;   D3    (R)   /CTS (SIO command)
;   D2    (R)   /DCD (SIO ready)
;   D1    (R)   Transmit data register empty
;   D0    (R)   Receive data register full
; $2001         MC6850 ACIA receive/transmit data register
; $4000-4003    FDC (FD1797A-02)
; $6000         Control port
;   D0:D1 (W)   Drive index
;   D3    (W)   High speed (1 = ???, 0 = 19200 baud)
;   D4    (W)   Drive select / motor on
;   D5    (W)   Printer strobe (1=asserted)
;   D6    (W)   ?? something disk related - maybe write gate?
;   D7    (W)   FDC density (1 = FM, 0 = MFM)
; $8000         Drive default density switches
;   D0-D3 (R)   0 for single density, 1 for double density
; $8001
;   D0-D1 (R)   Starting drive number switches (inverted; %11 = drive 0)
;   D2    (R)   External drive ID select (0/on = internal drives first, 1/off = external drives first)
;   D3    (R)   1050 compatibility switch (0/on = ED only, 1/off = DD enabled)
;
; $C000 (R)     Start watchdog timer?
; $F000-FFFF    4K ROM
;
; FDC DRQ -> 6809 FIRQ
; Watchdog -> 6809 NMI
; ??? -> 6809 IRQ
;
;===============================================================================
; Firmware memory map
;
; $0000-01FF    Sector buffer
; $0300         Device ID
; $0301         Command ID
; $0302         AUX1
; $0303         AUX2
; $0306         Format timeout
; $0308         Retry counter
; $0309         Bad sector list offset
; $030B         Motor off timer counter
; $030D         Motor off timer prescaler
; $030F-0312    Device IDs for each drive
; $0313         Selected drive index
; $0314         Current request track number
; $0315         Current request sector number
; $0316-0325    Drive control block 1
;   0,U         Drive status
;       D6=1    Write protected
;       D5=1    Double density (256 byte sectors)
;       D4=1    Motor on
;       D3=1    Write protect error
;       D2=1    Unsuccessful PUT operation error
;       D1=1    Data frame error
;       D0=1    Command error
;   1,U         FDC status
;   2,U         Step rate
;   3,U         Current side (0/2 for FDC command bit)
;   4,U         Density flag: $80 for FM, $00 for MFM
;   5,U         Number of sides (1/2)
;   6,U         Track count
;   7,U         Current track
;   8,U         Current sector size lo
;   9,U         Current sector size hi
;   10,U        Total sector count hi
;   11,U        Total sector count lo
;   12,U        ???
;   13,U        Sectors per track hi
;   14,U        Sectors per track lo
; $0326-0335    Drive control block 2
; $0336-0345    Drive control block 3
; $0346-0355    Drive control block 4
; $0357-035A    Printer control block
;   $0357       Printer status
;   $0358       Printer mode
;   $0359       Printer timeout
; $035F-0360    Exception handler (NMI)
; $0361         Exception handler stack pointer
; $0363         unused?
; $0364         Custom interleave flag -- cleared after non-$66 command
; $0365         Shadow for $6000
; $0367         Format: size field encoding
; $0368         Format: sector size in words
; $036A         Memory command enable flag
; $036B-036F    Sector address buffer
; $036C-0385    Format interleave buffer?
; $0391-039A    Format layout table
;   $0391       Gap I byte count
;   $0392       Gap I byte value
;   $0393       Gap IIIb byte count
;   $0394       Gap IIIb byte value
;   $0395       Pre address mark sync byte count
;   $0396       Pre address mark sync byte value
;   $0397       Gap IIb byte count
;   $0398       Gap IIb byte value
;   $0399
;   $039A       Gap IIIa byte value
; $03A0-03FF    Stack

;===============================================================================
; FIRQ/SWI handler
;
F000: 7F035F            CLR     $035F       ;clear exception handler
F003: B60800            LDA     $0800
F006: 10CE03FF          LDS     #$03FF      ;initialize stack
F00A: 1A50              ORCC    #$50        ;mask IRQs and FIRQs
F00C: BDFC89            JSR     $FC89       ;do initialization
;--- main service loop
F00F: B62001            LDA     $2001       ;read ACIA data to clear receive status
F012: B62000            LDA     $2000       ;read ACIA status to clear /DCD detect
F015: 10BE030B          LDY     $030B       ;get motor off timer counter
F019: 2713              BEQ     $F02E       ;skip if drive not selected
F01B: 73030D            COM     $030D
F01E: 260E              BNE     $F02E
F020: 313F              LEAY    -1,Y        ;decrement motor off counter
F022: 10BF030B          STY     $030B       ;store motor off counter
F026: 2606              BNE     $F02E
F028: 7F6000            CLR     $6000       ;deselect drive and turn off motor
F02B: 7F0365            CLR     $0365       ;update shadow
F02E: B62000            LDA     $2000       ;read ACIA status
F031: 8504              BITA    #$04        ;check /DCD
F033: 26DA              BNE     $F00F       ;
F035: 8508              BITA    #$08        ;check /CTS
F037: 27D6              BEQ     $F00F
F039: 1CEF              ANDCC   #$EF        ;enable IRQs
F03B: BDFC0F            JSR     $FC0F       ;receive command frame
F03E: 25CF              BCS     $F00F
F040: B60300            LDA     $0300       ;get command ID
F043: 8140              CMPA    #$40        ;check if printer
F045: 260F              BNE     $F056       ;jump if not
F047: B61000            LDA     $1000       ;read printer status
F04A: 8540              BITA    #$40        ;check printer /SELECT
F04C: 26C1              BNE     $F00F       ;jump if no printer present
F04E: 8EFE7B            LDX     #$FE7B      ;select printer command table
F051: CE0357            LDU     #$0357
F054: 204B              BRA     $F0A1

F056: 8D04              BSR     $F05C       ;try to match against drive
F058: 2425              BCC     $F07F       ;jump if found
F05A: 20B3              BRA     $F00F       ;ignore command, unknown device ID

;===============================================================================
; Get drive for device ID
;
F05C: B60300            LDA     $0300       ;get command device ID
F05F: 1CFE              ANDCC   #$FE        ;C=0
F061: 8E030E            LDX     #$030E      ;point to device table - 1
F064: C604              LDB     #$04        ;four drives to check
F066: A185              CMPA    B,X         ;check if drive device ID matches
F068: 2707              BEQ     $F071       ;jump if it's this drive
F06A: 5A                DECB                ;next drive
F06B: 26F9              BNE     $F066       ;jump until all drives checked
F06D: 1A01              ORCC    #$01        ;C=1 (not found)
F06F: 200D              BRA     $F07E       ;return

F071: 5A                DECB                ;B = drive index (0-3)
F072: F70313            STB     $0313       ;store drive index
F075: 58                ASLB                ;x2
F076: 58                ASLB                ;x4
F077: 58                ASLB                ;x8
F078: 58                ASLB                ;x16
F079: CE0316            LDU     #$0316      ;compute drive control block ptr
F07C: 33C5              LEAU    B,U         ; "
F07E: 39                RTS

;===============================================================================
F07F: B60301            LDA     $0301       ;get command ID
F082: 8153              CMPA    #$53        ;check if status command
F084: 2710              BEQ     $F096       ;jump if so
F086: A6C4              LDA     ,U
F088: 8470              ANDA    #$70
F08A: A7C4              STA     ,U
F08C: BE030B            LDX     $030B       ;get motor off counter
F08F: 2705              BEQ     $F096       ;
F091: 8610              LDA     #$10
F093: BDF290            JSR     $F290       ;set drive status bit
F096: 8EFE32            LDX     #$FE32      ;point to memory-protected command table
F099: 7D036A            TST     $036A       ;check if mem commands should be enabled
F09C: 2703              BEQ     $F0A1       ;skip if not
F09E: 8EFE29            LDX     #$FE29      ;point to full command table
F0A1: A680              LDA     ,X+         ;get next command in table
F0A3: 8100              CMPA    #$00        ;check if end of table
F0A5: 2611              BNE     $F0B8       ;jump if still have entries
F0A7: BDFC07            JSR     $FC07       ;wait for command to deassert
F0AA: 8601              LDA     #$01        ;command error bit
F0AC: BDF290            JSR     $F290       ;set drive status bit
F0AF: BDFBFA            JSR     $FBFA       ;short delay
F0B2: BDFC7F            JSR     $FC7F       ;send NAK
F0B5: 7EF00F            JMP     $F00F       ;restart

F0B8: 10AE81            LDY     ,X++        ;get command handler pointer
F0BB: B10301            CMPA    $0301       ;check if command changes
F0BE: 26E1              BNE     $F0A1       ;keep scanning if not
F0C0: ADA4              JSR     ,Y          ;call command handler
F0C2: B60800            LDA     $0800
F0C5: B60301            LDA     $0301       ;get command ID
F0C8: 8166              CMPA    #$66        ;check if set interleave command
F0CA: 2703              BEQ     $F0CF       ;skip if not
F0CC: 7F0364            CLR     $0364       ;clear custom interleave flag
F0CF: 7EF00F            JMP     $F00F

;===============================================================================
; Get Status command ($53)
;
F0D2: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F0D5: 5F                CLRB
F0D6: 1CFE              ANDCC   #$FE
F0D8: A6C4              LDA     ,U          ;get drive status
F0DA: BDFC59            JSR     $FC59       ;send byte
F0DD: A641              LDA     1,U         ;get FDC status
F0DF: 88FF              EORA    #$FF        ;invert for 810 emulation
F0E1: BDFC59            JSR     $FC59       ;send byte
F0E4: B60306            LDA     $0306       ;get format timeout
F0E7: BDFC59            JSR     $FC59       ;send byte
F0EA: A647              LDA     7,U
F0EC: BDFC59            JSR     $FC59       ;send byte
F0EF: C900              ADCB    #$00        ;finalize checksum
F0F1: F70305            STB     $0305       ;store checksum
F0F4: B60305            LDA     $0305       ;get checksum
F0F7: BDFC59            JSR     $FC59       ;send byte
F0FA: A6C4              LDA     ,U          ;load drive status
F0FC: 84F8              ANDA    #$F8        ;clear unsuccessful PUT and command/data frame error flags
F0FE: A7C4              STA     ,U
F100: 39                RTS

;===============================================================================
; Put Sector command ($50)
; Write Sector command ($57)
;
F101: BDF94B            JSR     $F94B       ;compute track/sector
F104: 240D              BCC     $F113       ;jump if logical sector valid
F106: A6C4              LDA     ,U          ;clear wp, bad put, and command/data error flags
F108: 8470              ANDA    #$70
F10A: A7C4              STA     ,U
F10C: 8601              LDA     #$01        ;invalid command bit
F10E: BDF290            JSR     $F290       ;set drive status bit
F111: 202C              BRA     $F13F       ;send NAK and exit

F113: BDFC6D            JSR     $FC6D       ;send ACK
F116: B60301            LDA     $0301       ;get command ID
F119: 8157              CMPA    #$57        ;check if regular speed command
F11B: 230D              BLS     $F12A
F11D: 8614              LDA     #$14
F11F: B72000            STA     $2000
F122: B60365            LDA     $0365       ;load control shadow
F125: 8A08              ORA     #$08        ;set high speed bit
F127: B76000            STA     $6000       ;write control
F12A: BDF163            JSR     $F163       ;receive sector
F12D: 8615              LDA     #$15
F12F: B72000            STA     $2000
F132: B60365            LDA     $0365       ;get control shadow
F135: B76000            STA     $6000       ;restore normal speed
F138: 2409              BCC     $F143       ;jump if frame received OK
F13A: 8612              LDA     #$12        ;set bad data frame and motor on bits
F13C: BDF290            JSR     $F290       ;set drive status bit
F13F: BDFC7F            JSR     $FC7F       ;send NAK
F142: 39                RTS

F143: BDFC6D            JSR     $FC6D       ;send ACK
F146: BDF991            JSR     $F991       ;select drive, motor on, seek to track
F149: 250B              BCS     $F156
F14B: A641              LDA     1,U         ;get drive status
F14D: 8540              BITA    #$40        ;check for write protect
F14F: 2709              BEQ     $F15A       ;jump if not
F151: 8608              LDA     #$08        ;write protect error
F153: BDF290            JSR     $F290       ;set drive status bit
F156: BDFC84            JSR     $FC84       ;send Error
F159: 39                RTS

F15A: BDF183            JSR     $F183       ;do the sector write/verify
F15D: 25F7              BCS     $F156       ;fail if error
F15F: BDFC72            JSR     $FC72       ;delay + send Complete
F162: 39                RTS

;===============================================================================
; Receive sector buffer / data frame
;
F163: 8E0000            LDX     #$0000
F166: 10BE035D          LDY     $035D
F16A: 5F                CLRB                ;checksum = 0
F16B: 1CFE              ANDCC   #$FE        ;C=0
F16D: BDFC32            JSR     $FC32       ;receive data frame
F170: F70305            STB     $0305       ;store computed checksum
F173: BDFC3D            JSR     $FC3D       ;receive checksum
F176: B70304            STA     $0304       ;store received checksum
F179: 1CFE              ANDCC   #$FE        ;C=0
F17B: B10305            CMPA    $0305       ;compare checksums
F17E: 2702              BEQ     $F182       ;exit C=0 if checksum OK
F180: 1A01              ORCC    #$01        ;exit C=1 if checksum bad
F182: 39                RTS

;===============================================================================
; Write sector (possibly with verify)
;
F183: 8604              LDA     #$04
F185: B70308            STA     $0308
F188: 8EF1BC            LDX     #$F1BC      ;exception handling routine
F18B: BF035F            STX     $035F       ;set exception handler
F18E: 10FF0361          STS     $0361       ;set exception handling stack pointer
F192: 8E0000            LDX     #$0000
F195: B60315            LDA     $0315       ;get sector number
F198: B74002            STA     $4002       ;set FDC sector number
F19B: B6C000            LDA     $C000
F19E: 86A8              LDA     #$A8        ;write sector command
F1A0: AA43              ORA     3,U         ;merge in current side
F1A2: B74000            STA     $4000       ;write FDC command
F1A5: E680              LDB     ,X+         ;load next byte from buffer
F1A7: AC48              CMPX    8,U         ;check if at end of sector
F1A9: 2E07              BGT     $F1B2       ;exit if done
F1AB: 53                COMB                ;invert for 810 emulation
F1AC: 13                SYNC                ;wait for DRQ
F1AD: F74003            STB     $4003       ;write byte to FDC
F1B0: 20F3              BRA     $F1A5       ;loop back for next byte

F1B2: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F1B5: B64000            LDA     $4000       ;read FDC status
F1B8: 8514              BITA    #$14        ;check for RNF or Lost Data
F1BA: 271B              BEQ     $F1D7       ;jump if neither
F1BC: B64000            LDA     $4000       ;read FDC status
F1BF: BDF20C            JSR     $F20C       ;force interrupt FDC
F1C2: 7A0308            DEC     $0308
F1C5: 26CB              BNE     $F192
F1C7: 1A01              ORCC    #$01
F1C9: B64000            LDA     $4000       ;read FDC status
F1CC: F68001            LDB     $8001       ;read switches
F1CF: C508              BITB    #$08        ;check switch 8 (1050 compatibility)
F1D1: 2631              BNE     $F204       ;
F1D3: 8A10              ORA     #$10        ;pretend we got RNF
F1D5: 202D              BRA     $F204

F1D7: B60301            LDA     $0301       ;get command
F1DA: 8157              CMPA    #$57        ;check if it's put sector
F1DC: 2624              BNE     $F202       ;jump if not
F1DE: 8E0000            LDX     #$0000      ;init sector buffer pointer
F1E1: B6C000            LDA     $C000
F1E4: 8688              LDA     #$88        ;FDC read sector command
F1E6: AA43              ORA     3,U         ;merge in current side
F1E8: B74000            STA     $4000       ;write FDC command
F1EB: 13                SYNC                ;wait for DRQ
F1EC: F64003            LDB     $4003       ;read byte from FDC
F1EF: 53                COMB                ;uninvert for 810 emulation
F1F0: E180              CMPB    ,X+         ;compare against buffer
F1F2: 26C8              BNE     $F1BC       ;fail if mismatch
F1F4: AC48              CMPX    8,U         ;check if at end of sector
F1F6: 26F3              BNE     $F1EB       ;loop back if not
F1F8: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F1FB: B64000            LDA     $4000       ;load FDC status
F1FE: 850C              BITA    #$0C        ;check for CRC or lost data
F200: 26BA              BNE     $F1BC       ;fail if so
F202: 1CFE              ANDCC   #$FE        ;C=0
F204: A741              STA     1,U         ;save FDC status for drive
F206: 8600              LDA     #$00
F208: B7035F            STA     $035F
F20B: 39                RTS

;===============================================================================
; Force interrupt FDC
;
F20C: 3412              PSHS    A,X
F20E: 86D0              LDA     #$D0        ;FDC force interrupt command
F210: B74000            STA     $4000       ;write FDC command
F213: 8E0001            LDX     #$0001
F216: BDFBFD            JSR     $FBFD       ;delay
F219: 3512              PULS    X,A
F21B: 39                RTS

;===============================================================================
; Read sector command ($52)
;
F21C: BDFC6D            JSR     $FC6D       ;send ACK
F21F: BDF94B            JSR     $F94B       ;compute track/sector
F222: 240F              BCC     $F233       ;jump if sector valid
F224: A6C4              LDA     ,U          ;clear wp, bad put, and command/data error flags
F226: 8470              ANDA    #$70
F228: A7C4              STA     ,U
F22A: 8601              LDA     #$01
F22C: BDF290            JSR     $F290       ;set drive status bit
F22F: BDFC7F            JSR     $FC7F       ;send NAK
F232: 39                RTS

F233: BDF991            JSR     $F991       ;select drive, motor on, seek to track
F236: 2505              BCS     $F23D       ;fail if error
F238: BDF295            JSR     $F295       ;read sector
F23B: 240F              BCC     $F24C       ;jump if no error
F23D: 8604              LDA     #$04
F23F: BDF290            JSR     $F290       ;set drive status bit
F242: 8E0C00            LDX     #$0C00
F245: BDFBFD            JSR     $FBFD       ;delay
F248: 8645              LDA     #$45        ;Error
F24A: 2002              BRA     $F24E       ;send byte

F24C: 8643              LDA     #$43        ;ACK
F24E: BDFC59            JSR     $FC59       ;send byte
F251: 8E001F            LDX     #$001F
F254: BDFBFD            JSR     $FBFD       ;delay
F257: B60301            LDA     $0301       ;get command ID
F25A: 8172              CMPA    #$72        ;check if high-speed read
F25C: 260D              BNE     $F26B       ;jump if not
F25E: 8614              LDA     #$14        ;select /1 divider
F260: B72000            STA     $2000       ;write ACIA control
F263: B60365            LDA     $0365       ;read control shadow
F266: 8A08              ORA     #$08        ;set high speed SIO bit
F268: B76000            STA     $6000       ;write control
F26B: 8D0C              BSR     $F279       ;send data frame
F26D: 8615              LDA     #$15        ;select /16 divider
F26F: B72000            STA     $2000       ;write ACIA control
F272: B60365            LDA     $0365       ;read control shadow
F275: B76000            STA     $6000       ;restore control
F278: 39                RTS

;===============================================================================
; Send sector buffer / data frame
;
F279: 8E0000            LDX     #$0000
F27C: 10BE035D          LDY     $035D
F280: 5F                CLRB
F281: 1CFE              ANDCC   #$FE
F283: BDFC4E            JSR     $FC4E       ;send data frame
F286: F70305            STB     $0305       ;store computed checksum
F289: B60305            LDA     $0305       ;get checksum
F28C: BDFC59            JSR     $FC59       ;send byte
F28F: 39                RTS

;===============================================================================
; Set drive status bit
;
F290: AAC4              ORA     ,U
F292: A7C4              STA     ,U
F294: 39                RTS

;===============================================================================
; Read sector
;
F295: 8601              LDA     #$01
F297: B70308            STA     $0308
F29A: 8EF2CC            LDX     #$F2CC
F29D: BF035F            STX     $035F       ;set exception handler
F2A0: 10FF0361          STS     $0361       ;set exception handler stack pointer
F2A4: 8E0000            LDX     #$0000
F2A7: B6C000            LDA     $C000       ;arm watchdog timer
F2AA: B60315            LDA     $0315       ;get desired sector
F2AD: B74002            STA     $4002       ;write FDC sector
F2B0: 8688              LDA     #$88        ;read sector
F2B2: AA43              ORA     3,U         ;merge in current side flag
F2B4: B74000            STA     $4000       ;write FDC command
F2B7: 13                SYNC                ;wait for DRQ
F2B8: F64003            LDB     $4003       ;load byte from FDC
F2BB: 53                COMB                ;invert for 810 emulation
F2BC: E780              STB     ,X+         ;store to buffer
F2BE: AC48              CMPX    8,U         ;check if sector done
F2C0: 26F5              BNE     $F2B7       ;continue if not
F2C2: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F2C5: B64000            LDA     $4000       ;read FDC status
F2C8: 853C              BITA    #$3C        ;check deleted, RNF, CRC, lost data
F2CA: 2720              BEQ     $F2EC       ;jump if no error
F2CC: B64000            LDA     $4000       ;read FDC status again
F2CF: BDF20C            JSR     $F20C       ;force interrupt FDC
F2D2: 7A0308            DEC     $0308
F2D5: 2CCD              BGE     $F2A4
F2D7: F60356            LDB     $0356
F2DA: 2703              BEQ     $F2DF
F2DC: 7C0369            INC     $0369
F2DF: 1A01              ORCC    #$01
F2E1: F68001            LDB     $8001       ;get switches
F2E4: C508              BITB    #$08        ;check 1050 compat
F2E6: 2606              BNE     $F2EE
F2E8: 8A10              ORA     #$10        ;force RNF
F2EA: 2002              BRA     $F2EE

F2EC: 1CFE              ANDCC   #$FE
F2EE: 8520              BITA    #$20        ;check deleted error
F2F0: 2702              BEQ     $F2F4       ;skip if not
F2F2: 8A40              ORA     #$40        ;copy to bit 6 for 810 FD1771 emulation
F2F4: A741              STA     1,U         ;set FDC status
F2F6: 8600              LDA     #$00
F2F8: B7035F            STA     $035F
F2FB: 39                RTS

;===============================================================================
; Toggle density
;
F2FC: A644              LDA     4,U         ;get density flag
F2FE: 2610              BNE     $F310       ;jump if single density
F300: 8E02D0            LDX     #$02D0      ;set 720 total sectors
F303: AF4A              STX     10,U
F305: 8E0012            LDX     #$0012      ;set 18 sectors per track
F308: AF4D              STX     13,U
F30A: 8680              LDA     #$80        ;set FM encoding
F30C: A744              STA     4,U
F30E: 200E              BRA     $F31E

F310: 8E0400            LDX     #$0400      ;set 1024 total sectors
F313: AF4A              STX     10,U
F315: 8E001A            LDX     #$001A      ;set 26 sectors per track
F318: AF4D              STX     13,U
F31A: 8600              LDA     #$00        ;set MFM encoding
F31C: A744              STA     4,U         ;get encoding flag
F31E: 8A10              ORA     #$10        ;drive on
F320: BA0313            ORA     $0313       ;merge drive index
F323: B76000            STA     $6000       ;write control
F326: B70365            STA     $0365
F329: BDF94B            JSR     $F94B       ;compute track/sector
F32C: 39                RTS

;===============================================================================
; Format command ($21)
;
F32D: BDFC6D            JSR     $FC6D       ;send ACK
F330: B60356            LDA     $0356
F333: 2703              BEQ     $F338
F335: BDFACD            JSR     $FACD       ;select single density
F338: 8EF3A9            LDX     #$F3A9      ;select single density layout
F33B: 108EF62D          LDY     #$F62D      ;select single density interleave
F33F: 6D44              TST     4,U
F341: 2612              BNE     $F355
F343: 8EF3B3            LDX     #$F3B3      ;select medium density layout
F346: 108EF640          LDY     #$F640      ;select medium density interleave
F34A: 6D48              TST     8,U
F34C: 2707              BEQ     $F355
F34E: 8EF3BD            LDX     #$F3BD      ;select double density layout
F351: 108EF61A          LDY     #$F61A      ;select double density interleave
F355: 3420              PSHS    Y
F357: 108E0391          LDY     #$0391      ;temporary layout table
F35B: C60A              LDB     #$0A        ;copy layout table to temp buffer
F35D: A680              LDA     ,X+
F35F: A7A0              STA     ,Y+
F361: 5A                DECB
F362: 26F9              BNE     $F35D
F364: 3520              PULS    Y
F366: EC48              LDD     8,U         ;get sector size
F368: FD035D            STD     $035D
F36B: B70367            STA     $0367       ;set size encoding from sector size high
F36E: 44                LSRA                ;divide sector size by two
F36F: 56                RORB
F370: F70368            STB     $0368       ;set word count for writing data field
F373: 7D0364            TST     $0364       ;check if custom interleave has been set
F376: 2704              BEQ     $F37C       ;skip if not
F378: 108E036B          LDY     #$036B      ;use custom interleave table
F37C: BDF5CB            JSR     $F5CB
F37F: 240D              BCC     $F38E
F381: BDF20C            JSR     $F20C       ;force interrupt FDC
F384: 6F4C              CLR     12,U
F386: BDFC84            JSR     $FC84       ;send Error
F389: BDFBFA            JSR     $FBFA       ;short delay
F38C: 2014              BRA     $F3A2

F38E: BDF417            JSR     $F417
F391: 25EE              BCS     $F381
F393: B60800            LDA     $0800
F396: BDF5AE            JSR     $F5AE
F399: BDFDA2            JSR     $FDA2
F39C: BDFC72            JSR     $FC72       ;delay + send Complete
F39F: BDFBFA            JSR     $FBFA       ;short delay
F3A2: 8E0000            LDX     #$0000
F3A5: BDF279            JSR     $F279       ;send data frame
F3A8: 39                RTS

;===============================================================================
; Single density layout
;
F3A9: 19FF
F3AB: 0400
F3AD: 0100
F3AF: 0200
F3B1: 14FF

;===============================================================================
; Medium density layout
;
F3B3: 324E
F3B5: 1F4E
F3B7: 03F5
F3B9: 124E
F3BB: 324E

;===============================================================================
; Double density layout
;
F3BD: 324E
F3BF: 154E
F3C1: 03F5
F3C3: 124E
F3C5: 1E4E

;===============================================================================
; Set interleave command ($66)
;
; Receives a 26-byte frame containing the custom interleave to use for the next
; command, which must be a format command. Any other disk command will clear
; the custom interleave.
;
; Note that this is NOT the same as the US Doubler's format skewed ($66)
; command, which takes a whole sector buffer and immediately begins formatting.
;
F3C7: BDFC6D            JSR     $FC6D       ;send ACK
F3CA: 8E036C            LDX     #$036C
F3CD: 108E001A          LDY     #$001A      ;data frame len = 26 bytes
F3D1: BDF16A            JSR     $F16A       ;receive data frame
F3D4: 2407              BCC     $F3DD       ;jump if data frame OK
F3D6: BDFBFA            JSR     $FBFA       ;short delay
F3D9: BDFC7F            JSR     $FC7F       ;send NAK
F3DC: 39                RTS

F3DD: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F3E0: 7C0364            INC     $0364       ;enable custom interleave
F3E3: 7F036B            CLR     $036B
F3E6: 39                RTS

;===============================================================================
; Format medium command ($22)
; Set medium density command ($74)
;
F3E7: 8E0080            LDX     #$0080      ;set 128 bytes per sector
F3EA: AF48              STX     8,U
F3EC: 8E001A            LDX     #$001A      ;set 26 sectors per track
F3EF: AF4D              STX     13,U
F3F1: 8600              LDA     #$00
F3F3: A744              STA     4,U
F3F5: 8610              LDA     #$10
F3F7: A7C4              STA     ,U
F3F9: 8628              LDA     #$28        ;set 40 tracks
F3FB: A746              STA     6,U
F3FD: 8601              LDA     #$01        ;set single sided
F3FF: A745              STA     5,U
F401: 8E0400            LDX     #$0400      ;set 1024 total sectors
F404: AF4A              STX     10,U
F406: B60301            LDA     $0301
F409: 8174              CMPA    #$74        ;check if $74 command
F40B: 2703              BEQ     $F410       ;skip if so
F40D: 7EF32D            JMP     $F32D       ;begin format now for $22

F410: BDFC6D            JSR     $FC6D       ;send ACK
F413: BDFC72            JSR     $FC72       ;short delay and send Complete
F416: 39                RTS

;===============================================================================
F417: 8EF562            LDX     #$F562
F41A: BF035F            STX     $035F       ;set exception handler
F41D: 10FF0361          STS     $0361       ;set exception handler stack pointer
F421: 6F43              CLR     3,U         ;set DCB to side 1
F423: 8E0000            LDX     #$0000
F426: BF0309            STX     $0309
F429: E646              LDB     6,U
F42B: B6C000            LDA     $C000       ;reset watchdog timer
F42E: 8E07FF            LDX     #$07FF
F431: BDFBFD            JSR     $FBFD       ;delay
F434: B6C000            LDA     $C000       ;reset watchdog timer
F437: 3404              PSHS    B
F439: 86F0              LDA     #$F0        ;FDC write track command
F43B: AA43              ORA     3,U         ;merge in side select bit
F43D: B74000            STA     $4000       ;write FDC command
F440: F60391            LDB     $0391
F443: B60392            LDA     $0392
F446: 13                SYNC
F447: B74003            STA     $4003
F44A: 5A                DECB
F44B: 26F9              BNE     $F446
F44D: E64E              LDB     14,U        ;get sectors per track
F44F: 3404              PSHS    B           ;save it
F451: F60393            LDB     $0393
F454: B60394            LDA     $0394
F457: 13                SYNC
F458: B74003            STA     $4003
F45B: 5A                DECB
F45C: 26F9              BNE     $F457
F45E: C60C              LDB     #$0C
F460: 8600              LDA     #$00
F462: 13                SYNC
F463: B74003            STA     $4003
F466: 5A                DECB
F467: 26F9              BNE     $F462
F469: F60395            LDB     $0395       ;get sync byte count
F46C: B60396            LDA     $0396       ;get sync byte value
F46F: 13                SYNC
F470: B74003            STA     $4003
F473: 5A                DECB
F474: 26F9              BNE     $F46F
F476: 86FE              LDA     #$FE        ;IDAM
F478: 13                SYNC
F479: B74003            STA     $4003       ;write to FDC
F47C: B64001            LDA     $4001       ;track number
F47F: 13                SYNC
F480: B74003            STA     $4003       ;write to FDC as track
F483: A643              LDA     3,U         ;get FDC side select bit
F485: 44                LSRA                ;convert to 0/1
F486: 13                SYNC                ;wait for DRQ
F487: B74003            STA     $4003       ;write to FDC as side number
F48A: E6E4              LDB     ,S
F48C: A6A5              LDA     B,Y         ;read sector from interleave table
F48E: 13                SYNC                ;wait for DRQ
F48F: B74003            STA     $4003       ;write to FDC as sector number
F492: B60367            LDA     $0367       ;load size encoding
F495: 13                SYNC                ;wait for DRQ
F496: B74003            STA     $4003       ;write to FDC as size field
F499: 86F7              LDA     #$F7        ;CRC-16 token
F49B: 13                SYNC                ;wait for DRQ
F49C: B74003            STA     $4003       ;write to FDC to write CRC-16
F49F: F60397            LDB     $0397
F4A2: B60398            LDA     $0398
F4A5: 13                SYNC                ;wait for DRQ
F4A6: B74003            STA     $4003       ;write byte to FDC
F4A9: 5A                DECB
F4AA: 26F9              BNE     $F4A5
F4AC: C60C              LDB     #$0C
F4AE: 8600              LDA     #$00
F4B0: 13                SYNC                ;wait for DRQ
F4B1: B74003            STA     $4003       ;write byte to FDC
F4B4: 5A                DECB
F4B5: 26F9              BNE     $F4B0
F4B7: F60395            LDB     $0395       ;get sync byte count
F4BA: B60396            LDA     $0396       ;get sync byte value
F4BD: 13                SYNC                ;wait for DRQ
F4BE: B74003            STA     $4003       ;write byte to FDC
F4C1: 5A                DECB
F4C2: 26F9              BNE     $F4BD
F4C4: 86FB              LDA     #$FB        ;DAM
F4C6: 13                SYNC                ;wait for DRQ
F4C7: B74003            STA     $4003       ;write byte to FDC
F4CA: F60368            LDB     $0368
F4CD: 866B              LDA     #$6B        ;first half of $6BB6
F4CF: 13                SYNC                ;wait for DRQ
F4D0: B74003            STA     $4003       ;write byte to FDC
F4D3: 86B6              LDA     #$B6        ;second half of $6BB6
F4D5: 13                SYNC                ;wait for DRQ
F4D6: B74003            STA     $4003       ;write byte to FDC
F4D9: 5A                DECB
F4DA: 26F1              BNE     $F4CD
F4DC: 86F7              LDA     #$F7        ;FDC CRC-16 token
F4DE: 13                SYNC                ;wait for DRQ
F4DF: B74003            STA     $4003       ;write byte to FDC
F4E2: B6039A            LDA     $039A
F4E5: 3504              PULS    B
F4E7: 13                SYNC
F4E8: B74003            STA     $4003
F4EB: 5A                DECB                ;decrement sector count
F4EC: 1026FF5F          LBNE    $F44F       ;loop back until all sectors done
F4F0: B74003            STA     $4003
F4F3: F64000            LDB     $4000       ;get FDC status
F4F6: C501              BITB    #$01        ;check BSY
F4F8: 26F6              BNE     $F4F0       ;keep looping if so
F4FA: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F4FD: BDF20C            JSR     $F20C       ;force interrupt FDC
F500: BDF571            JSR     $F571       ;verify track
F503: A645              LDA     5,U         ;get side count
F505: 8101              CMPA    #$01        ;check if single sided
F507: 2722              BEQ     $F52B       ;skip if so
F509: A643              LDA     3,U         ;get current side
F50B: 261E              BNE     $F52B       ;skip if side 2
F50D: 8602              LDA     #$02        ;switch to side 2
F50F: A743              STA     3,U
F511: 8D05              BSR     $F518       ;update FDC side select output
F513: 3504              PULS    B
F515: 16FF13            LBRA    $F42B

F518: 8688              LDA     #$88        ;read sector
F51A: AA43              ORA     3,U         ;merge in current side
F51C: B74000            STA     $4000       ;write FDC command
F51F: BDFBFA            JSR     $FBFA       ;short delay
F522: 86D0              LDA     #$D0        ;FDC force interrupt command
F524: B74000            STA     $4000       ;write FDC command
F527: BDFBFA            JSR     $FBFA       ;short delay
F52A: 39                RTS

F52B: 3504              PULS    B
F52D: 5A                DECB
F52E: 261E              BNE     $F54E
F530: 8EFFFF            LDX     #$FFFF
F533: 10AE48            LDY     8,U         ;get sector size
F536: 313E              LEAY    -2,Y        ;move to last word offset
F538: AFA4              STX     ,Y          ;store terminator
F53A: 10BE0309          LDY     $0309       ;
F53E: 8EFFFF            LDX     #$FFFF
F541: AFA4              STX     ,Y
F543: B64000            LDA     $4000       ;get FDC status
F546: A741              STA     1,U         ;store in DCB
F548: 7F035F            CLR     $035F
F54B: 1CFE              ANDCC   #$FE
F54D: 39                RTS

F54E: 6F43              CLR     3,U
F550: 8DC6              BSR     $F518       ;update FDC side select output
F552: 8658              LDA     #$58        ;FDC step in command
F554: AA42              ORA     2,U         ;merge in step rate
F556: B74000            STA     $4000       ;write FDC command
F559: BDFBFA            JSR     $FBFA       ;short delay
F55C: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F55F: 16FEC9            LBRA    $F42B

;===============================================================================
; Format exception handler
;
F562: 10BE0309          LDY     $0309       ;get bad sector list offset
F566: 8EFFFF            LDX     #$FFFF      ;write terminator
F569: AFA4              STX     ,Y
F56B: 7F035F            CLR     $035F
F56E: 1A01              ORCC    #$01
F570: 39                RTS

;===============================================================================
; Format: verify track
;
F571: E64E              LDB     14,U        ;get sectors per track count
F573: B6C000            LDA     $C000       ;reset watchdog timer
F576: AE48              LDX     8,U         ;get current sector size lo
F578: A6A5              LDA     B,Y         ;get sector from interleave table
F57A: B74002            STA     $4002       ;write FDC sector
F57D: 8688              LDA     #$88        ;FDC read sector command
F57F: AA43              ORA     3,U         ;merge in side select
F581: B74000            STA     $4000       ;write FDC command
F584: BDFDD7            JSR     $FDD7       ;wait for FDC busy
F587: 13                SYNC                ;wait for DRQ
F588: B64003            LDA     $4003       ;read FDC data byte
F58B: 301F              LEAX    -1,X        ;decrement byte count
F58D: 26F8              BNE     $F587       ;jump if still bytes left
F58F: BDFDCF            JSR     $FDCF       ;wait for FDC idle
F592: B64000            LDA     $4000       ;read FDC status
F595: 8518              BITA    #$18        ;check for RNF, CRC
F597: 2711              BEQ     $F5AA       ;jump if neither
F599: 3420              PSHS    Y           ;save interleave table pointer
F59B: 10BE0309          LDY     $0309       ;get bad sector list offset
F59F: BE4001            LDX     $4001       ;read FDC track/sector number
F5A2: AFA1              STX     ,Y++        ;store bad track/sector
F5A4: 10BF0309          STY     $0309       ;save bad sector list offset
F5A8: 3520              PULS    Y           ;restore interleave table pointer
F5AA: 5A                DECB                ;next sector
F5AB: 26C6              BNE     $F573       ;jump back until all sectors done
F5AD: 39                RTS

F5AE: 108E0000          LDY     #$0000
F5B2: 10BC0309          CMPY    $0309
F5B6: 2712              BEQ     $F5CA
F5B8: E6A0              LDB     ,Y+
F5BA: A64E              LDA     14,U
F5BC: 3D                MUL
F5BD: 1F01              TFR     D,X
F5BF: E6A0              LDB     ,Y+
F5C1: 3A                ABX
F5C2: 1F10              TFR     X,D
F5C4: E73E              STB     -2,Y
F5C6: A73F              STA     -1,Y
F5C8: 20E8              BRA     $F5B2

F5CA: 39                RTS

;===============================================================================
F5CB: B60313            LDA     $0313       ;get selected drive index
F5CE: 8A10              ORA     #$10        ;motor/drive on bit
F5D0: AA44              ORA     4,U         ;merge in encoding flag
F5D2: B76000            STA     $6000       ;write control
F5D5: B70365            STA     $0365
F5D8: 8EAFFF            LDX     #$AFFF
F5DB: BF030B            STX     $030B       ;set motor off timer
F5DE: BDFC02            JSR     $FC02       ;delay
F5E1: BDFC02            JSR     $FC02       ;delay
F5E4: BDF20C            JSR     $F20C       ;force interrupt FDC
F5E7: B64000            LDA     $4000       ;get FDC status
F5EA: 8540              BITA    #$40        ;check for write protect error
F5EC: 270E              BEQ     $F5FC       ;jump if not
F5EE: 8608              LDA     #$08        ;unsuccessful put error
F5F0: BDF290            JSR     $F290       ;set drive status bit
F5F3: B64000            LDA     $4000       ;get FDC status
F5F6: A741              STA     1,U         ;save in DCB
F5F8: 1A01              ORCC    #$01        ;exit C=1 (error)
F5FA: 201D              BRA     $F619

F5FC: BDFC02            JSR     $FC02       ;delay
F5FF: BDFC02            JSR     $FC02       ;delay
F602: BDFDA2            JSR     $FDA2       ;recalibrate drive
F605: B64000            LDA     $4000       ;read FDC status
F608: 25EC              BCS     $F5F6       ;jump if recalibrate failed
F60A: 8E0000            LDX     #$0000      ;clear sector buffer
F60D: CC0000            LDD     #$0000
F610: ED81              STD     ,X++
F612: 8C0100            CMPX    #$0100
F615: 25F9              BCS     $F610
F617: 1CFE              ANDCC   #$FE        ;exit C=0 (success)
F619: 39                RTS

;===============================================================================
; Double density interleave table
;
F61A: 00 0E 08 02 0F 09 03 10 0A 04 11 0B 05 12 0C 06 0D 07 01

;===============================================================================
; Single density interleave table
;
F62D: 00 02 04 06 08 0A 0C 0E 10 12 01 03 05 07 09 0B 0D 0F 11

;===============================================================================
; Medium density interleave table
;
F640: 00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A
F64E: 01 03 05 07 09 0B 0D 0F 11 13 15 17 19

;===============================================================================
; Read PERCOM Block command ($4E)
;
F65B: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F65E: 5F                CLRB                ;clear checksum
F65F: 1CFE              ANDCC   #$FE        ;clear carry for checksum computation
F661: A646              LDA     6,U         ;get track count
F663: BDFC59            JSR     $FC59       ;send byte
F666: A642              LDA     2,U         ;get step rate
F668: BDFC59            JSR     $FC59       ;send byte
F66B: A64D              LDA     13,U        ;get sectors per track hi
F66D: BDFC59            JSR     $FC59       ;send byte
F670: A64E              LDA     14,U        ;get sectors per track lo
F672: BDFC59            JSR     $FC59       ;send byte
F675: A645              LDA     5,U         ;get number of sides
F677: 4A                DECA                ;compute sides-1
F678: BDFC59            JSR     $FC59       ;send byte
F67B: A644              LDA     4,U         ;get density encoding
F67D: 2B04              BMI     $F683       ;skip if FM
F67F: 8604              LDA     #$04        ;indicate MFM
F681: 2002              BRA     $F685

F683: 8600              LDA     #$00        ;indicate FM
F685: BDFC59            JSR     $FC59       ;send byte
F688: A648              LDA     8,U         ;get bytes per sector hi
F68A: BDFC59            JSR     $FC59       ;send byte
F68D: A649              LDA     9,U         ;get bytes per sector lo
F68F: BDFC59            JSR     $FC59       ;send byte
F692: 86FF              LDA     #$FF        ;indicate drive active
F694: BDFC59            JSR     $FC59       ;send byte
F697: 8615              LDA     #$15
F699: BDFC59            JSR     $FC59       ;send byte
F69C: 8600              LDA     #$00
F69E: BDFC59            JSR     $FC59       ;send byte
F6A1: BDFC59            JSR     $FC59       ;send byte
F6A4: C900              ADCB    #$00        ;fold final carry
F6A6: 1F98              TFR     B,A         ;get checksum
F6A8: BDFC59            JSR     $FC59       ;send byte
F6AB: 39                RTS

;===============================================================================
; Write PERCOM Block command ($4F)
;
F6AC: BDFC6D            JSR     $FC6D       ;send ACK
F6AF: 8E0000            LDX     #$0000
F6B2: 108E000C          LDY     #$000C
F6B6: BDF16A            JSR     $F16A
F6B9: 2407              BCC     $F6C2
F6BB: BDFBFA            JSR     $FBFA       ;short delay
F6BE: BDFC7F            JSR     $FC7F       ;send NAK
F6C1: 39                RTS

F6C2: BDFC6A            JSR     $FC6A       ;delay + send ACK
F6C5: 8E0000            LDX     #$0000
F6C8: A680              LDA     ,X+
F6CA: A746              STA     6,U         ;set DCB track count
F6CC: A680              LDA     ,X+
F6CE: 8403              ANDA    #$03
F6D0: A742              STA     2,U         ;set DCB step rate
F6D2: EC81              LDD     ,X++
F6D4: ED4D              STD     13,U        ;set DCB sectors per track hi
F6D6: A680              LDA     ,X+
F6D8: 4C                INCA
F6D9: A745              STA     5,U         ;set DCB side count
F6DB: A680              LDA     ,X+
F6DD: 2604              BNE     $F6E3
F6DF: 8680              LDA     #$80
F6E1: 2002              BRA     $F6E5

F6E3: 8600              LDA     #$00
F6E5: A744              STA     4,U         ;set DCB density encoding
F6E7: EC84              LDD     ,X
F6E9: ED48              STD     8,U         ;set DCB sector size
F6EB: A648              LDA     8,U
F6ED: 2708              BEQ     $F6F7
F6EF: A6C4              LDA     ,U          ;set double density in DCB drive status
F6F1: 8A20              ORA     #$20
F6F3: A7C4              STA     ,U
F6F5: 2006              BRA     $F6FD

F6F7: A6C4              LDA     ,U          ;clear double density in DCB drive status
F6F9: 84DF              ANDA    #$DF
F6FB: A7C4              STA     ,U
F6FD: 6F41              CLR     1,U         ;clear FDC status
F6FF: A646              LDA     6,U         ;get track count
F701: E645              LDB     5,U         ;get side count
F703: 3D                MUL                 ;compute total tracks
F704: A64E              LDA     14,U        ;get sectors per track
F706: 3D                MUL                 ;compute total sectors
F707: ED4A              STD     10,U        ;set DCB total sector count
F709: BDFC72            JSR     $FC72       ;delay + send Complete
F70C: 39                RTS

;===============================================================================
; Get drive device IDs command handler ($63)
;
; Sends a 4-byte frame containing the device IDs for all drives.
;
F70D: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F710: BDFBFA            JSR     $FBFA       ;short delay
F713: 8E030F            LDX     #$030F      ;drive device ID table
F716: 108E0004          LDY     #$0004      ;4 device IDs to send
F71A: BDF280            JSR     $F280       ;send frame
F71D: 39                RTS

;===============================================================================
; Set drive device IDs command handler ($64)
;
; Receives a 4-byte data frame and then sets the device IDs for all drives.
;
F71E: BDFC6D            JSR     $FC6D       ;send ACK
F721: 8E0000            LDX     #$0000
F724: 108E0004          LDY     #$0004      ;4 device IDs to receive
F728: BDF16A            JSR     $F16A       ;receive data frame
F72B: 2407              BCC     $F734
F72D: BDFBFA            JSR     $FBFA       ;short delay
F730: BDFC7F            JSR     $FC7F       ;send NAK
F733: 39                RTS

F734: BDFC6A            JSR     $FC6A       ;delay + send ACK
F737: DC00              LDD     $00         ;copy IDs to drive device ID table
F739: FD030F            STD     $030F
F73C: DC02              LDD     $02
F73E: FD0311            STD     $0311
F741: BDFC72            JSR     $FC72       ;delay + send Complete
F744: 39                RTS

;===============================================================================
; Reset command handler ($78)
;
F745: BDFC6D            JSR     $FC6D       ;send ACK
F748: BDFC89            JSR     $FC89       ;reset
F74B: BDFC75            JSR     $FC75       ;send Complete
F74E: 39                RTS

;===============================================================================
; Get drive count command handler ($69)
;
; Returns a single byte data frame containing the number of drives found
; starting at the given device ID. Command is NAKed if the device ID used is
; not of the first drive.
;
F74F: B68001            LDA     $8001       ;read non-density switches
F752: 43                COMA                ;uninvert
F753: 8403              ANDA    #$03        ;read switches 5 and 6 (starting drive)
F755: 4C                INCA                ;map to 1-4
F756: 8A30              ORA     #$30        ;map to $31-34 device ID
F758: B10300            CMPA    $0300       ;see if it matches command's device ID
F75B: 270C              BEQ     $F769       ;jump if so
F75D: 8601              LDA     #$01        ;command error bit
F75F: BDF290            JSR     $F290       ;set drive status bit
F762: BDFBFA            JSR     $FBFA       ;short delay
F765: BDFC7F            JSR     $FC7F       ;send NAK
F768: 39                RTS

F769: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F76C: B60366            LDA     $0366
F76F: BDFC59            JSR     $FC59       ;send byte
F772: BDFC59            JSR     $FC59       ;send byte
F775: 39                RTS

;===============================================================================
; Check disk command handler ($43)
;
; Checks for a disk in the drive and returns a single byte frame with $00 for
; no disk, $01 for FM, or $02 for MFM.
;
F776: BDF20C            JSR     $F20C       ;force interrupt FDC
F779: BDFC6D            JSR     $FC6D       ;send ACK
F77C: B60313            LDA     $0313       ;get selected drive index
F77F: 8A10              ORA     #$10        ;motor on
F781: B76000            STA     $6000       ;write control
F784: BDFC02            JSR     $FC02       ;delay
F787: 10BE030B          LDY     $030B       ;check if motor was on
F78B: 2608              BNE     $F795       ;skip spin-up delay if so
F78D: C604              LDB     #$04
F78F: BDFC02            JSR     $FC02       ;delay
F792: 5A                DECB
F793: 26FA              BNE     $F78F
F795: 108EAFFF          LDY     #$AFFF      ;motor off timer duration
F799: 10BF030B          STY     $030B       ;set motor off timer
F79D: 6F4C              CLR     12,U
F79F: BDFDA2            JSR     $FDA2       ;recalibrate drive
F7A2: F64000            LDB     $4000       ;read FDC status
F7A5: C402              ANDB    #$02        ;check for index pulse
F7A7: F7037E            STB     $037E
F7AA: 8E3000            LDX     #$3000
F7AD: B64000            LDA     $4000       ;read FDC status
F7B0: 8402              ANDA    #$02        ;check for index pulse
F7B2: B1037E            CMPA    $037E       ;look for IP edge
F7B5: 2608              BNE     $F7BF       ;jump if so
F7B7: 301F              LEAX    -1,X
F7B9: 26F2              BNE     $F7AD
F7BB: C600              LDB     #$00
F7BD: 200B              BRA     $F7CA

F7BF: BDFA84            JSR     $FA84       ;detect density
F7C2: C601              LDB     #$01
F7C4: A644              LDA     4,U         ;get encoding flag
F7C6: 2602              BNE     $F7CA       ;skip if FM
F7C8: C602              LDB     #$02
F7CA: 3404              PSHS    B
F7CC: BDFC75            JSR     $FC75       ;send Complete
F7CF: 3502              PULS    A
F7D1: BDFC59            JSR     $FC59       ;send byte
F7D4: BDFC59            JSR     $FC59       ;send byte
F7D7: 39                RTS

;===============================================================================
; Set single density command ($75)
;
F7D8: BDFC6D            JSR     $FC6D       ;send ACK
F7DB: BDFACD            JSR     $FACD       ;select single density
F7DE: BDFC72            JSR     $FC72       ;delay + send Complete
F7E1: 39                RTS

;===============================================================================
; Set double density command ($76)
;
F7E2: BDFC6D            JSR     $FC6D       ;send ACK
F7E5: BDFAED            JSR     $FAED       ;switch to MFM
F7E8: 8E02D0            LDX     #$02D0      ;set 720 total sectors
F7EB: AF4A              STX     10,U
F7ED: 8628              LDA     #$28        ;set 40 tracks
F7EF: A746              STA     6,U
F7F1: 8601              LDA     #$01        ;set single sided
F7F3: A745              STA     5,U
F7F5: 6F43              CLR     3,U         ;select side 1
F7F7: BDFC72            JSR     $FC72       ;delay + send Complete
F7FA: 39                RTS

;===============================================================================
; Get version command handler ($56)
;
F7FB: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F7FE: BDFBFA            JSR     $FBFA       ;short delay
F801: 8EF80C            LDX     #$F80C
F804: 108E0019          LDY     #$0019
F808: BDF280            JSR     $F280       ;send frame
F80B: 39                RTS

F80C: 20                ' '
F80D: 414D44432020      'AMDC  '
F813: 56455220312E31    'VER 1.1'
F81A: 20202020          '    '
F81E: 312F33302F3834    '1/30/84'

;===============================================================================
; Read switches command ($73)
;
F825: B68000            LDA     $8000
F828: 840F              ANDA    #$0F
F82A: B7036B            STA     $036B
F82D: B68001            LDA     $8001
F830: 8407              ANDA    #$07
F832: 48                ASLA
F833: 48                ASLA
F834: 48                ASLA
F835: 48                ASLA
F836: BA036B            ORA     $036B
F839: B7036B            STA     $036B
F83C: B61000            LDA     $1000
F83F: 8410              ANDA    #$10
F841: 48                ASLA
F842: 48                ASLA
F843: 48                ASLA
F844: BA036B            ORA     $036B
F847: B7036B            STA     $036B
F84A: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F84D: B6036B            LDA     $036B
F850: BDFC59            JSR     $FC59       ;send byte
F853: BDFC59            JSR     $FC59       ;send byte
F856: 39                RTS

;===============================================================================
; Get drive speed command handler ($71)
;
F857: BDFC6D            JSR     $FC6D       ;send ACK
F85A: B60313            LDA     $0313       ;get selected drive index
F85D: 8A10              ORA     #$10        ;motor on
F85F: B76000            STA     $6000       ;write control
F862: B70365            STA     $0365       ;update shadow
F865: BDF20C            JSR     $F20C       ;force interrupt FDC
F868: 8E030B            LDX     #$030B      ;!! - BUG - should be just $030B
F86B: 2618              BNE     $F885       ;jump if motor already on
F86D: BDFC02            JSR     $FC02       ;delay
F870: BDFC02            JSR     $FC02       ;delay
F873: BDFC02            JSR     $FC02       ;delay
F876: BDFC02            JSR     $FC02       ;delay
F879: BDFC02            JSR     $FC02       ;delay
F87C: BDFC02            JSR     $FC02       ;delay
F87F: BDFC02            JSR     $FC02       ;delay
F882: BDFC02            JSR     $FC02       ;delay
F885: 108EAFFF          LDY     #$AFFF      ;set motor off timer
F889: 10BF030B          STY     $030B       ; "
F88D: 108E0000          LDY     #$0000      ;
F891: 7F036B            CLR     $036B
F894: 8EF904            LDX     #$F904      ;set exception handler
F897: BF035F            STX     $035F
F89A: 10FF0361          STS     $0361       ;set exception stack pointer
F89E: F6C000            LDB     $C000       ;restart watchdog
F8A1: B64000            LDA     $4000       ;get FDC status
F8A4: 8502              BITA    #$02        ;check for index pulse
F8A6: 27F9              BEQ     $F8A1       ;keep waiting for one if not
F8A8: B64000            LDA     $4000       ;get FDC status
F8AB: 8502              BITA    #$02        ;check for index pulse
F8AD: 26F9              BNE     $F8A8       ;wait until trailing edge
F8AF: F6C000            LDB     $C000       ;restart watchdog
F8B2: 8E0017            LDX     #$0017
F8B5: 7D036B            TST     $036B
F8B8: 260C              BNE     $F8C6
F8BA: B64000            LDA     $4000       ;get FDC status
F8BD: 8502              BITA    #$02        ;check for index pulse
F8BF: 270C              BEQ     $F8CD
F8C1: 7C036B            INC     $036B
F8C4: 2007              BRA     $F8CD

F8C6: B64000            LDA     $4000
F8C9: 8502              BITA    #$02
F8CB: 270F              BEQ     $F8DC
F8CD: 301F              LEAX    -1,X
F8CF: 26E4              BNE     $F8B5
F8D1: 3121              LEAY    1,Y
F8D3: 21FE              BRN     $F8D3
F8D5: 21FE              BRN     $F8D5
F8D7: 12                NOP
F8D8: 12                NOP
F8D9: 12                NOP
F8DA: 20D6              BRA     $F8B2

F8DC: 7F035F            CLR     $035F
F8DF: B60800            LDA     $0800
F8E2: 8C000B            CMPX    #$000B
F8E5: 2E02              BGT     $F8E9
F8E7: 3121              LEAY    1,Y
F8E9: 10BF036B          STY     $036B
F8ED: CC0258            LDD     #$0258      ;600
F8F0: B3036B            SUBD    $036B       ;600-Y
F8F3: FD036B            STD     $036B
F8F6: BDFC75            JSR     $FC75       ;send Complete
F8F9: 108E0002          LDY     #$0002      ;two bytes to send
F8FD: 8E036B            LDX     #$036B      ;set transfer pointer
F900: BDF280            JSR     $F280       ;send frame
F903: 39                RTS

F904: 7F035F            CLR     $035F
F907: BDFC84            JSR     $FC84       ;send Error
F90A: 39                RTS

;===============================================================================
; Write memory ($58)
;
; Writes 128 bytes of memory to the address in AUX1/2.
;
F90B: BDFC6D            JSR     $FC6D       ;send ACK
F90E: B60303            LDA     $0303
F911: F60302            LDB     $0302
F914: 1F01              TFR     D,X         ;set transfer address to AUX1/2
F916: 108E0080          LDY     #$0080      ;transfer length is 128 bytes
F91A: BDF16A            JSR     $F16A       ;receive data frame
F91D: 2407              BCC     $F926       ;jump if received OK
F91F: BDFBFA            JSR     $FBFA       ;short delay
F922: BDFC7F            JSR     $FC7F       ;send NAK
F925: 39                RTS

F926: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F929: 39                RTS

;===============================================================================
; Read memory ($59)
;
; Reads 128 bytes of memory to the address in AUX1/2.
;
F92A: BDFC7A            JSR     $FC7A       ;send ACK + Complete
F92D: BDFBFA            JSR     $FBFA       ;short delay
F930: B60303            LDA     $0303
F933: F60302            LDB     $0302
F936: 1F01              TFR     D,X         ;set transfer address to AUX1/2
F938: 108E0080          LDY     #$0080      ;transfer length is 128 bytes
F93C: BDF280            JSR     $F280       ;send frame
F93F: 39                RTS

;===============================================================================
; Execute command ($5A)
;
F940: B60303            LDA     $0303
F943: F60302            LDB     $0302
F946: 1F01              TFR     D,X
F948: AD84              JSR     ,X
F94A: 39                RTS

;===============================================================================
; Track/sector division routine
;
F94B: B60303            LDA     $0303       ;load logical sector high
F94E: F60302            LDB     $0302       ;load logical sector low
F951: 10A34A            CMPD    10,U        ;check if over total sector count
F954: 2303              BLS     $F959       ;jump if <=
F956: 1A01              ORCC    #$01        ;C=1 for invalid logical sector
F958: 39                RTS

F959: 7F0314            CLR     $0314       ;set track:sector to zero
F95C: 10A34D            CMPD    13,U        ;check if still more than a track
F95F: 2307              BLS     $F968       ;jump if not
F961: A34D              SUBD    13,U        ;subtract a track's worth of sectors
F963: 7C0314            INC     $0314       ;increment track number
F966: 20F4              BRA     $F95C       ;next track

F968: F70315            STB     $0315       ;store physical sector number
F96B: AE48              LDX     8,U         ;X = sector size
F96D: FC0314            LDD     $0314       ;load track:sector
F970: 10830003          CMPD    #$0003      ;check if boot sector
F974: 2E03              BGT     $F979       ;jump if not
F976: 8E0080            LDX     #$0080      ;force 128 byte sector
F979: BF035D            STX     $035D       ;set sector size
F97C: 6F43              CLR     3,U         ;select side 1
F97E: B60314            LDA     $0314       ;load track number
F981: A146              CMPA    6,U         ;check if greater than track count
F983: 2509              BCS     $F98E       ;jump if not
F985: A046              SUBA    6,U         ;subtract track count
F987: B70314            STA     $0314       ;update physical track number
F98A: 8602              LDA     #$02        ;choose side 2
F98C: A743              STA     3,U         ;select side 2
F98E: 1CFE              ANDCC   #$FE        ;C=0 for valid sector
F990: 39                RTS

;===============================================================================
; Motor on and seek to track
;
F991: BDF20C            JSR     $F20C       ;force interrupt FDC
F994: 8604              LDA     #$04        ;four retries
F996: B70308            STA     $0308       ;set retry counter
F999: B60313            LDA     $0313       ;get selected drive index
F99C: 8A10              ORA     #$10        ;select drive
F99E: AA44              ORA     4,U         ;merge encoding bit
F9A0: B76000            STA     $6000       ;write control
F9A3: 8610              LDA     #$10        ;motor on bit
F9A5: BDF290            JSR     $F290       ;set drive status bit
F9A8: B64000            LDA     $4000       ;get FDC status
F9AB: 8540              BITA    #$40        ;check if write protected
F9AD: 2705              BEQ     $F9B4       ;jump if not protected
F9AF: 8608              LDA     #$08        ;write protect failure bit
F9B1: BDF290            JSR     $F290       ;set drive status bit
F9B4: A64C              LDA     12,U
F9B6: 261C              BNE     $F9D4
F9B8: BDFC02            JSR     $FC02       ;delay
F9BB: BDFC02            JSR     $FC02       ;delay
F9BE: BDFDA2            JSR     $FDA2       ;recalibrate drive
F9C1: BDFC02            JSR     $FC02       ;delay
F9C4: 240E              BCC     $F9D4
F9C6: 7A0308            DEC     $0308       ;decrement retry counter
F9C9: 10270080          LBEQ    $FA4D
F9CD: BDF20C            JSR     $F20C       ;force interrupt FDC
F9D0: 6F4C              CLR     12,U
F9D2: 20E0              BRA     $F9B4

F9D4: BE030B            LDX     $030B       ;check motor off timer
F9D7: 2611              BNE     $F9EA       ;jump if motor is already running
F9D9: BDFC02            JSR     $FC02       ;delay for motor spin-up
F9DC: BDFC02            JSR     $FC02       ;delay
F9DF: BDFC02            JSR     $FC02       ;delay
F9E2: BDFC02            JSR     $FC02       ;delay
F9E5: B60300            LDA     $0300       ;get device ID
F9E8: 2000              BRA     $F9EA
F9EA: B7035B            STA     $035B       ;
F9ED: BDFA74            JSR     $FA74       ;detect density
F9F0: 108EAFFF          LDY     #$AFFF
F9F4: 10BF030B          STY     $030B       ;set motor off timer
F9F8: 8EFA33            LDX     #$FA33
F9FB: BF035F            STX     $035F       ;set NMI handler
F9FE: 10FF0361          STS     $0361
FA02: A647              LDA     7,U         ;get current track for drive
FA04: B74001            STA     $4001       ;set current track on FDC
FA07: 7D0369            TST     $0369
FA0A: 2605              BNE     $FA11
FA0C: B10314            CMPA    $0314       ;check if we're already on correct track
FA0F: 2747              BEQ     $FA58       ;jump if so
FA11: 7F0369            CLR     $0369
FA14: B60314            LDA     $0314       ;get requested track
FA17: B74003            STA     $4003       ;set FDC desired track
FA1A: A747              STA     7,U         ;set current track in DCB
FA1C: 861C              LDA     #$1C        ;FDC seek command
FA1E: AA42              ORA     2,U         ;merge in step rate
FA20: B74000            STA     $4000       ;write FDC command
FA23: BDFBFA            JSR     $FBFA       ;short delay
FA26: B6C000            LDA     $C000
FA29: BDFDCF            JSR     $FDCF       ;wait for FDC idle
FA2C: B64000            LDA     $4000       ;get drive status
FA2F: 8510              BITA    #$10        ;check for RNF
FA31: 2728              BEQ     $FA5B       ;jump if not
FA33: B60356            LDA     $0356
FA36: 2703              BEQ     $FA3B
FA38: BDF2FC            JSR     $F2FC       ;toggle density
FA3B: 7A0308            DEC     $0308
FA3E: 270D              BEQ     $FA4D
FA40: BDF20C            JSR     $F20C       ;force interrupt FDC
FA43: 7F035F            CLR     $035F
FA46: 6F4C              CLR     12,U
FA48: BDFDA2            JSR     $FDA2       ;recalibrate drive
FA4B: 20A0              BRA     $F9ED

FA4D: 6F4C              CLR     12,U
FA4F: B64000            LDA     $4000       ;get FDC status
FA52: 8A10              ORA     #$10        ;pretend RNF status
FA54: 1A01              ORCC    #$01        ;set C=1 error
FA56: 2005              BRA     $FA5D

FA58: B64000            LDA     $4000       ;get FDC status
FA5B: 1CFE              ANDCC   #$FE        ;set C=0 success
FA5D: A741              STA     1,U         ;store in DCB
FA5F: 8600              LDA     #$00
FA61: B7035F            STA     $035F
FA64: B60313            LDA     $0313       ;get selected drive index
FA67: 8A10              ORA     #$10        ;motor/drive on
FA69: AA44              ORA     4,U         ;merge in density flag
FA6B: 8A40              ORA     #$40        ;??
FA6D: B76000            STA     $6000       ;write control
FA70: B70365            STA     $0365
FA73: 39                RTS

;===============================================================================
; Detect density
;
FA74: B60301            LDA     $0301       ;get command ID
FA77: 8152              CMPA    #$52        ;check if read sector
FA79: 2651              BNE     $FACC       ;jump if not
FA7B: FC0302            LDD     $0302       ;get sector number
FA7E: 10830100          CMPD    #$0100      ;check if logical sector 1
FA82: 2648              BNE     $FACC       ;exit if not
FA84: B60313            LDA     $0313       ;get selected drive index
FA87: 8A10              ORA     #$10        ;motor/drive on
FA89: 8A80              ORA     #$80        ;set single density
FA8B: B76000            STA     $6000       ;write control
FA8E: B60800            LDA     $0800
FA91: C606              LDB     #$06        ;six bytes to read for address field
FA93: 8E04E4            LDX     #$04E4      ;set timeout
FA96: 108E036B          LDY     #$036B      ;set sector address buffer
FA9A: 86C0              LDA     #$C0        ;read address command
FA9C: B74000            STA     $4000       ;write FDC command
FA9F: 301F              LEAX    -1,X        ;decrement timeout counter
FAA1: 2716              BEQ     $FAB9       ;jump if timeout
FAA3: B64000            LDA     $4000       ;check FDC status
FAA6: 8502              BITA    #$02        ;test DRQ
FAA8: 27F5              BEQ     $FA9F       ;keep waiting if not
FAAA: B64003            LDA     $4003       ;read byte from FDC
FAAD: A7A0              STA     ,Y+         ;store in sector address buffer
FAAF: 5A                DECB                ;next byte
FAB0: 26ED              BNE     $FA9F       ;jump if need more bytes
FAB2: B6036C            LDA     $036C       ;get side field
FAB5: 8101              CMPA    #$01
FAB7: 230E              BLS     $FAC7
FAB9: 8D32              BSR     $FAED       ;switch to MFM
FABB: B60313            LDA     $0313       ;get selected drive index
FABE: 8A10              ORA     #$10        ;motor/drive on
FAC0: AA44              ORA     4,U         ;merge density setting
FAC2: B76000            STA     $6000       ;write control
FAC5: 2002              BRA     $FAC9       ;force interrupt and exit

FAC7: 8D04              BSR     $FACD       ;select single density
FAC9: BDF20C            JSR     $F20C       ;force interrupt FDC
FACC: 39                RTS

FACD: 8680              LDA     #$80        ;FM encoding
FACF: A744              STA     4,U
FAD1: 8610              LDA     #$10        ;motor on
FAD3: A7C4              STA     ,U          ;set drive status
FAD5: 8601              LDA     #$01
FAD7: A745              STA     5,U
FAD9: 8628              LDA     #$28        ;40 tracks
FADB: A746              STA     6,U
FADD: 8E02D0            LDX     #$02D0      ;720 sectors total
FAE0: AF4A              STX     10,U
FAE2: 8E0080            LDX     #$0080      ;128 bytes per sector
FAE5: AF48              STX     8,U
FAE7: 8E0012            LDX     #$0012      ;18 sectors per track
FAEA: AF4D              STX     13,U
FAEC: 39                RTS

;===============================================================================
FAED: B60356            LDA     $0356
FAF0: 2613              BNE     $FB05       ;select enhanced density
FAF2: 8600              LDA     #$00        ;MFM encoding
FAF4: A744              STA     4,U         ;set FDC status
FAF6: 8630              LDA     #$30        ;motor on + double density
FAF8: A7C4              STA     ,U          ;set drive status
FAFA: 8E0100            LDX     #$0100      ;256 bytes per sector
FAFD: AF48              STX     8,U
FAFF: 8E0012            LDX     #$0012      ;18 sectors per track
FB02: AF4D              STX     13,U
FB04: 39                RTS

FB05: 8600              LDA     #$00        ;MFM encoding
FB07: A744              STA     4,U
FB09: 8E0400            LDX     #$0400      ;1024 sectors total
FB0C: AF4A              STX     10,U
FB0E: 8E001A            LDX     #$001A      ;26 sectors per track
FB11: AF4D              STX     13,U
FB13: 8601              LDA     #$01
FB15: A745              STA     5,U
FB17: 8610              LDA     #$10        ;motor on
FB19: A7C4              STA     ,U          ;set drive status
FB1B: 8628              LDA     #$28        ;40 tracks
FB1D: A746              STA     6,U
FB1F: 8E0080            LDX     #$0080      ;128 bytes per sector
FB22: AF48              STX     8,U
FB24: 39                RTS

;===============================================================================
; Printer get status command handler ($53)
;
FB25: BDFC7A            JSR     $FC7A       ;send ACK + Complete
FB28: 8E0357            LDX     #$0357
FB2B: 108E0004          LDY     #$0004
FB2F: BDF280            JSR     $F280       ;send frame
FB32: 86FF              LDA     #$FF
FB34: B70358            STA     $0358
FB37: 8680              LDA     #$80
FB39: B70357            STA     $0357
FB3C: 39                RTS

;===============================================================================
; Printer write command handler ($57)
;
FB3D: 8680              LDA     #$80
FB3F: B70357            STA     $0357
FB42: 864E              LDA     #$4E
FB44: B70358            STA     $0358
FB47: BDFC6A            JSR     $FC6A       ;delay + send ACK
FB4A: 8E0000            LDX     #$0000
FB4D: 108E0028          LDY     #$0028
FB51: BDF16A            JSR     $F16A       ;receive data frame
FB54: 2407              BCC     $FB5D
FB56: BDFBFA            JSR     $FBFA       ;short delay
FB59: BDFC7F            JSR     $FC7F       ;send NAK
FB5C: 39                RTS

FB5D: BDFC6A            JSR     $FC6A       ;delay + send ACK
FB60: 108E0000          LDY     #$0000
FB64: 8E5B00            LDX     #$5B00
FB67: F60359            LDB     $0359
FB6A: F70308            STB     $0308
FB6D: C628              LDB     #$28        ;40 characters max to print
FB6F: A6A0              LDA     ,Y+         ;get next character from buffer
FB71: 3402              PSHS    A           ;save ATASCII character
FB73: 819B              CMPA    #$9B        ;check if EOL
FB75: 2602              BNE     $FB79       ;skip if not
FB77: 860D              LDA     #$0D        ;replace EOL with CR
FB79: 3402              PSHS    A           ;save ASCII character
FB7B: 3410              PSHS    X           ;
FB7D: BE030B            LDX     $030B
FB80: 270A              BEQ     $FB8C
FB82: 301F              LEAX    -1,X
FB84: BF030B            STX     $030B
FB87: 2603              BNE     $FB8C
FB89: 7F0365            CLR     $0365
FB8C: 3510              PULS    X
FB8E: 301F              LEAX    -1,X
FB90: 2608              BNE     $FB9A
FB92: 8E5B00            LDX     #$5B00
FB95: 7A0308            DEC     $0308       ;decrement timeout hi
FB98: 2734              BEQ     $FBCE       ;jump if timeout
FB9A: B61000            LDA     $1000       ;read status port
FB9D: 8580              BITA    #$80        ;check if printer ready
FB9F: 26DA              BNE     $FB7B       ;keep waiting if not
FBA1: 3502              PULS    A           ;restore ASCII character
FBA3: B71800            STA     $1800       ;set character to parallel port
FBA6: 3470              PSHS    X,Y,U
FBA8: 3570              PULS    U,Y,X
FBAA: B60365            LDA     $0365       ;get control shadow
FBAD: 8A20              ORA     #$20        ;set strobe bit
FBAF: B76000            STA     $6000       ;assert printer strobe
FBB2: 12                NOP                 ;tiny delay
FBB3: 12                NOP                 ; "
FBB4: 84DF              ANDA    #$DF        ;reset strobe bit
FBB6: B76000            STA     $6000       ;deassert printer strobe
FBB9: 3502              PULS    A           ;restore ATASCII character
FBBB: 819B              CMPA    #$9B        ;was it EOL?
FBBD: 271A              BEQ     $FBD9       ;exit if so
FBBF: 5A                DECB                ;decrement char count
FBC0: 2717              BEQ     $FBD9       ;exit if out of chars
FBC2: 3410              PSHS    X           ;save buffer index
FBC4: 8E0005            LDX     #$0005      ;set delay
FBC7: BDFBFD            JSR     $FBFD       ;delay
FBCA: 3510              PULS    X           ;restore buffer index
FBCC: 20A1              BRA     $FB6F       ;loop back for next char

FBCE: 3506              PULS    B,A         ;clean up stack
FBD0: 8604              LDA     #$04        ;unsuccessful put operation
FBD2: BDF290            JSR     $F290       ;set device status bit
FBD5: BDFC7F            JSR     $FC7F       ;send NAK
FBD8: 39                RTS

FBD9: CC0000            LDD     #$0000      ;zero print buffer
FBDC: 8E0000            LDX     #$0000
FBDF: ED81              STD     ,X++
FBE1: 8C0028            CMPX    #$0028
FBE4: 23F9              BLS     $FBDF
FBE6: BDFC72            JSR     $FC72       ;delay + send Complete
FBE9: 39                RTS

;===============================================================================
; Set printer timeout command handler ($65)
;
FBEA: BDFC6D            JSR     $FC6D       ;send ACK
FBED: BDFC3D            JSR     $FC3D       ;read byte and update checksum
FBF0: B70359            STA     $0359
FBF3: BDFC3D            JSR     $FC3D       ;read byte and update checksum
FBF6: BDFC7A            JSR     $FC7A       ;send ACK + Complete
FBF9: 39                RTS

;===============================================================================
; Delay (~140 cycles)
;
FBFA: 8E0010            LDX     #$0010      ;3
FBFD: 301F              LEAX    -1,X        ;5
FBFF: 26FC              BNE     $FBFD       ;3
FC01: 39                RTS                 ;5

;===============================================================================
; Delay (~125K cycles)
;
FC02: 8E3D09            LDX     #$3D09
FC05: 20F6              BRA     $FBFD

;===============================================================================
; Wait for command line to deassert
;
FC07: B62000            LDA     $2000
FC0A: 8508              BITA    #$08
FC0C: 26F9              BNE     $FC07
FC0E: 39                RTS

;===============================================================================
; Receive command frame
;
FC0F: 8E0300            LDX     #$0300
FC12: 108E0004          LDY     #$0004
FC16: 5F                CLRB
FC17: 1CFE              ANDCC   #$FE
FC19: 8D17              BSR     $FC32       ;receive data frame
FC1B: F70305            STB     $0305       ;store computed checksum
FC1E: 8D1D              BSR     $FC3D       ;receive checksum byte
FC20: B70304            STA     $0304       ;store received checksum
FC23: 8DE2              BSR     $FC07       ;wait for command to deassert
FC25: 1CFE              ANDCC   #$FE        ;C=0
FC27: B60304            LDA     $0304       ;get received checksum
FC2A: B10305            CMPA    $0305       ;compare to computed checksum
FC2D: 2702              BEQ     $FC31       ;exit C=0 if checksum OK
FC2F: 1A01              ORCC    #$01        ;exit C=1 if checksum bad
FC31: 39                RTS

;===============================================================================
; Receive data frame
;
FC32: 8D09              BSR     $FC3D       ;receive byte and update checksum
FC34: A780              STA     ,X+         ;store in buffer
FC36: 313F              LEAY    -1,Y        ;decrement count
FC38: 26F8              BNE     $FC32       ;loop if not done yet
FC3A: C900              ADCB    #$00        ;finalize checksum
FC3C: 39                RTS

;===============================================================================
; Receive byte and update checksum
;
FC3D: B62000            LDA     $2000       ;read ACIA status
FC40: 8501              BITA    #$01        ;check if byte received
FC42: 27F9              BEQ     $FC3D       ;wait if not
FC44: B62001            LDA     $2001       ;get received byte
FC47: 3402              PSHS    A
FC49: E9E4              ADCB    ,S          ;update checksum
FC4B: 3502              PULS    A
FC4D: 39                RTS

;===============================================================================
; Send data frame
;
FC4E: A680              LDA     ,X+
FC50: 8D07              BSR     $FC59       ;send byte
FC52: 313F              LEAY    -1,Y
FC54: 26F8              BNE     $FC4E
FC56: C900              ADCB    #$00        ;finalize checksum
FC58: 39                RTS

;===============================================================================
; Send byte and update checksum
;
FC59: 3402              PSHS    A
FC5B: B62000            LDA     $2000       ;get ACIA status
FC5E: 8502              BITA    #$02        ;check if transmit empty
FC60: 27F9              BEQ     $FC5B       ;loop if not
FC62: E9E4              ADCB    ,S          ;update checksum
FC64: 3502              PULS    A
FC66: B72001            STA     $2001       ;write byte to transmit
FC69: 39                RTS

;===============================================================================
; Send ACK
;
FC6A: BDFBFA            JSR     $FBFA       ;short delay
FC6D: 8641              LDA     #$41        ;ACK
FC6F: 8DE8              BSR     $FC59       ;send byte
FC71: 39                RTS

;===============================================================================
; Send Complete
;
FC72: BDFBFA            JSR     $FBFA       ;short delay
FC75: 8643              LDA     #$43        ;Complete
FC77: 8DE0              BSR     $FC59       ;send byte
FC79: 39                RTS

;===============================================================================
; Send ACK + Complete
;
FC7A: 8DEE              BSR     $FC6A       ;delay + send ACK
FC7C: 8DF4              BSR     $FC72       ;delay + send Complete
FC7E: 39                RTS

;===============================================================================
; Send NAK
;
FC7F: 864E              LDA     #$4E        ;NAK
FC81: 8DD6              BSR     $FC59       ;send byte
FC83: 39                RTS

;===============================================================================
; Send Error
;
FC84: 8645              LDA     #$45        ;Error
FC86: 8DD1              BSR     $FC59       ;send byte
FC88: 39                RTS

;===============================================================================
; Power-on initialization
;
FC89: 8E0000            LDX     #$0000      ;clear RAM $0000-039F
FC8C: CC0000            LDD     #$0000
FC8F: ED81              STD     ,X++
FC91: 8C039F            CMPX    #$039F
FC94: 25F9              BCS     $FC8F
FC96: 8601              LDA     #$01        ;assume two internal drives
FC98: F61000            LDB     $1000       ;read status port
FC9B: C520              BITB    #$20        ;check for internal drive 2
FC9D: 2601              BNE     $FCA0       ;skip if present
FC9F: 4A                DECA                ;only one internal drive
FCA0: B7036B            STA     $036B       ;set number of internal drives
FCA3: 7F0366            CLR     $0366
FCA6: B68001            LDA     $8001       ;read switches
FCA9: 43                COMA                ;uninvert
FCAA: 8403              ANDA    #$03        ;mask to starting drive number switches
FCAC: 8B31              ADDA    #$31        ;map to device ID
FCAE: B7035C            STA     $035C       ;set starting device ID
FCB1: B68001            LDA     $8001       ;read switches
FCB4: 5F                CLRB                ;start with drive 0 (externals will be 3/4)
FCB5: 8404              ANDA    #$04        ;check switch 7 (external drive ID)
FCB7: 2702              BEQ     $FCBB       ;skip if on
FCB9: C602              LDB     #$02        ;start with drive 2 (externals will be 1/2)
FCBB: 3404              PSHS    B
FCBD: 108E0004          LDY     #$0004      ;4 drives to process
FCC1: A6E4              LDA     ,S          ;get drive index
FCC3: 8A10              ORA     #$10        ;motor/drive on
FCC5: B76000            STA     $6000       ;write control
FCC8: BDFC02            JSR     $FC02       ;delay
FCCB: BDFC02            JSR     $FC02       ;delay
FCCE: CE0316            LDU     #$0316
FCD1: E6E4              LDB     ,S
FCD3: C403              ANDB    #$03
FCD5: 58                ASLB
FCD6: 58                ASLB
FCD7: 58                ASLB
FCD8: 58                ASLB
FCD9: 33C5              LEAU    B,U
FCDB: BDFD8E            JSR     $FD8E       ;check if drive present
FCDE: 2578              BCS     $FD58       ;skip init/assign drive if not present
FCE0: B61000            LDA     $1000       ;load status port
FCE3: 8510              BITA    #$10        ;check test switch
FCE5: 261F              BNE     $FD06       ;jump if not on
FCE7: B68000            LDA     $8000       ;read switches
FCEA: 840F              ANDA    #$0F        ;isolate to per-drive density switches
FCEC: 2605              BNE     $FCF3       ;skip if any off (any double density)
FCEE: 7C036A            INC     $036A
FCF1: 2009              BRA     $FCFC

FCF3: 810F              CMPA    #$0F        ;check if all off (all double density)
FCF5: 2705              BEQ     $FCFC       ;jump if so
FCF7: 7C036A            INC     $036A
FCFA: 200A              BRA     $FD06

FCFC: 8E0080            LDX     #$0080      ;128 bytes per sector
FCFF: AF48              STX     8,U         ;set sector size
FD01: 7C0356            INC     $0356
FD04: 201A              BRA     $FD20

FD06: 8E0100            LDX     #$0100      ;256 bytes per sector
FD09: F60366            LDB     $0366
FD0C: 3420              PSHS    Y
FD0E: 108EFD8A          LDY     #$FD8A      ;Drive bit table
FD12: B68000            LDA     $8000
FD15: A5A5              BITA    B,Y         ;check default density switch for drive
FD17: 2603              BNE     $FD1C
FD19: 8E0080            LDX     #$0080      ;128 bytes per sector
FD1C: AF48              STX     8,U         ;set drive sector size
FD1E: 3520              PULS    Y
FD20: 1F10              TFR     X,D         ;get low byte of sector size
FD22: C480              ANDB    #$80        ;convert to FM/MFM encoding
FD24: E744              STB     4,U         ;set encoding
FD26: 8620              LDA     #$20        ;double density flag
FD28: C580              BITB    #$80        ;check if single density
FD2A: 2702              BEQ     $FD2E       ;skip if so
FD2C: 8610              LDA     #$10        ;motor on
FD2E: A7C4              STA     ,U          ;set drive status
FD30: 8600              LDA     #$00        ;clear FDC status
FD32: A741              STA     1,U
FD34: 8601              LDA     #$01        ;set single sided
FD36: A745              STA     5,U
FD38: 8628              LDA     #$28        ;set 40 tracks
FD3A: A746              STA     6,U
FD3C: 8E02D0            LDX     #$02D0      ;set 720 total sectors
FD3F: AF4A              STX     10,U
FD41: 8E0012            LDX     #$0012      ;set 18 sectors per track
FD44: AF4D              STX     13,U
FD46: 8E030F            LDX     #$030F      ;point to drive device ID table
FD49: E6E4              LDB     ,S          ;load drive index
FD4B: C403              ANDB    #$03        ;mask to 0-3
FD4D: B6035C            LDA     $035C       ;load current device ID
FD50: A785              STA     B,X         ;set device ID for drive
FD52: 7C035C            INC     $035C       ;next device ID
FD55: 7C0366            INC     $0366
FD58: 6CE4              INC     ,S
FD5A: 313F              LEAY    -1,Y
FD5C: 1026FF6E          LBNE    $FCCE       ;next drive
FD60: 861E              LDA     #$1E
FD62: B70359            STA     $0359       ;set printer timeout
FD65: 8680              LDA     #$80
FD67: B70357            STA     $0357       ;set printer status
FD6A: 8678              LDA     #$78
FD6C: B70306            STA     $0306       ;set format timeout
FD6F: 3504              PULS    B
FD71: 86D0              LDA     #$D0        ;force interrupt command
FD73: B74000            STA     $4000       ;write FDC command
FD76: 7F6000            CLR     $6000       ;deselect drives
FD79: 8603              LDA     #$03        ;reset ACIA
FD7B: B72000            STA     $2000       ;write ACIA control
FD7E: 8615              LDA     #$15        ;/RTS low, disable xmit IRQ, 8d1sb, /16
FD80: B72000            STA     $2000       ;write ACIA control
FD83: 73035B            COM     $035B
FD86: B62001            LDA     $2001       ;clear receive register
FD89: 39                RTS

;===============================================================================
; Drive bit table
;
FD8A: 01020408

;===============================================================================
; Check if drive present / recalibrate
;
FD8E: A662              LDA     2,S         ;get drive index
FD90: 8403              ANDA    #$03
FD92: B1036B            CMPA    $036B       ;check if it's one of the internal drives
FD95: 2331              BLS     $FDC8       ;skip test if so
FD97: 8A10              ORA     #$10        ;drive/motor on
FD99: B76000            STA     $6000       ;select drive
FD9C: BDFC02            JSR     $FC02       ;delay
FD9F: BDFC02            JSR     $FC02       ;delay
FDA2: C600              LDB     #$00        ;recalibrate command
FDA4: EA42              ORB     2,U         ;merge in step rate
FDA6: F74000            STB     $4000       ;write FDC command
FDA9: E642              LDB     2,U
FDAB: 8EFDCB            LDX     #$FDCB
FDAE: E685              LDB     B,X
FDB0: 8E7FFF            LDX     #$7FFF
FDB3: B64000            LDA     $4000       ;get FDC status
FDB6: 8504              BITA    #$04        ;check for track 0
FDB8: 260A              BNE     $FDC4       ;jump if track 0 found
FDBA: 301F              LEAX    -1,X        ;decrement timeout lo
FDBC: 26F5              BNE     $FDB3       ;jump if no underflow yet
FDBE: 5A                DECB                ;decrement timeout hi
FDBF: 26EF              BNE     $FDB0       ;jump if no timeout yet
FDC1: 1A01              ORCC    #$01        ;C=1 drive not found
FDC3: 39                RTS

FDC4: 6F47              CLR     7,U         ;set current track to 0
FDC6: 6C4C              INC     12,U
FDC8: 1CFE              ANDCC   #$FE        ;C=0 drive found
FDCA: 39                RTS

;===============================================================================
FDCB: 01 02 04 06

;===============================================================================
; Wait for FDC idle
;
FDCF: B64000            LDA     $4000
FDD2: 8501              BITA    #$01
FDD4: 26F9              BNE     $FDCF
FDD6: 39                RTS

;===============================================================================
; Wait for FDC busy
;
FDD7: B64000            LDA     $4000       ;read FDC status
FDDA: 8501              BITA    #$01        ;check BSY
FDDC: 27F9              BEQ     $FDD7       ;keep looping if not BSY yet
FDDE: 39                RTS

;===============================================================================
; NMI handler
;
FDDF: 7D035F            TST     $035F       ;check if exception handler set
FDE2: 2601              BNE     $FDE5       ;jump if so
FDE4: 3B                RTI                 ;nope, ignore the NMI
FDE5: 1CEF              ANDCC   #$EF        ;enable IRQs
FDE7: 10FE0361          LDS     $0361       ;restore stack pointer
FDEB: 6E9F              JMP     [$035F]     ;jump to exception handler

;===============================================================================
; IRQ handler
;
FDEF: 7F035F            CLR     $035F       ;clear exception handler
FDF2: B60800            LDA     $0800
FDF5: 7F0363            CLR     $0363
FDF8: 7F0364            CLR     $0364       ;clear custom interleave flag
FDFB: C600              LDB     #$00
FDFD: 8E030F            LDX     #$030F      ;drive device ID table pointer
FE00: CE0316            LDU     #$0316      ;DCB table pointer
FE03: A685              LDA     B,X         ;read device ID for drive
FE05: 270E              BEQ     $FE15
FE07: 8131              CMPA    #$31        ;check if D1:
FE09: 2602              BNE     $FE0D
FE0B: 6F4C              CLR     12,U
FE0D: A6C4              LDA     ,U          ;get drive status
FE0F: 8470              ANDA    #$70        ;turn off wp, bad put, c/d frame errors
FE11: A7C4              STA     ,U
FE13: 6F41              CLR     1,U         ;clear FDC status
FE15: 33C810            LEAU    16,U        ;next DCB
FE18: 5C                INCB                ;next drive
FE19: C104              CMPB    #$04        ;check if all four drives checked
FE1B: 26E6              BNE     $FE03       ;loop back if not
FE1D: 8615              LDA     #$15        ;reset ACIA to 19200 baud
FE1F: B72000            STA     $2000       ;write ACIA control
FE22: 10CE03FF          LDS     #$03FF      ;reset stack pointer
FE26: 7EF00F            JMP     $F00F       ;jump back to main loop

;===============================================================================
; Disk drive command table
;
FE29: 58 F90B       ;$58 Write memory
FE2C: 59 F92A       ;$59 Read memory
FE2F: 5A F940       ;$5A Execute
FE32: 53 F0D2       ;$53 Get status
FE35: 57 F101       ;$57 Write sector
FE38: 52 F21C       ;$52 Read sector
FE3B: 72 F21C       ;$72 High speed read sector
FE3E: 77 F101       ;$77 High speed write sector
FE41: 70 F101       ;$70 High speed put sector
FE44: 21 F32D       ;$21 Format
FE47: 50 F101       ;$50 Put sector
FE4A: 22 F3E7       ;$22 Format medium
FE4D: 74 F3E7       ;$74 Set medium density
FE50: 75 F7D8       ;$75 Set single density
FE53: 76 F7E2       ;$76 Set double density
FE56: 4E F65B       ;$4E Read PERCOM block
FE59: 4F F6AC       ;$4F Write PERCOM block
FE5C: 66 F3C7       ;$66 Set interleave (NOT format skewed)
FE5F: 78 F745       ;$78 Reset
FE62: 63 F70D       ;$63 Get drive device IDs
FE65: 64 F71E       ;$64 Set drive device IDs
FE68: 69 F74F       ;$69 Get drive count
FE6B: 43 F776       ;$43 Check disk
FE6E: 56 F7FB       ;$56 Get version
FE71: 6D FE85       ;$6D Get Easter egg
FE74: 73 F825       ;$73 Read switches
FE77: 71 F857       ;$71 Get drive speed
FE7A: 00

;===============================================================================
; Printer command table
;
FE7B: 53 FB25       ;$53 Get status
FE7E: 57 FB3D       ;$57 Write
FE80: 65 FBEA       ;$65 Set printer timeout
FE84: 00

;===============================================================================
; Get Easter egg command ($6D)
;
FE85: BDFC7A            JSR     $FC7A       ;send ACK + Complete
FE88: BDFBFA            JSR     $FBFA       ;short delay
FE8B: 8EFE96            LDX     #$FE96      ;message pointer
FE8E: 108E0019          LDY     #$0019      ;message length
FE92: BDF280            JSR     $F280       ;send frame
FE95: 39                RTS

FE96: 2052424D20        ' RBM '
FE9B: 31302F32372F3833  '10/27/83'
FEA3: 20204849204D4F4D  '  HI MOM'
FEAB: 21212121          '!!!!'

;===============================================================================
; Reset handler
;
FEAF: 1A50              ORCC    #$50
FEB1: B61000            LDA     $1000       ;load status port
FEB4: 8510              BITA    #$10        ;check if test switch on
FEB6: 1026F146          LBNE    $F000       ;begin normal init if not
FEBA: B68000            LDA     $8000       ;get SW1-4
FEBD: 8508              BITA    #$08        ;check if SW3 is on
FEBF: 1027F13D          LBEQ    $F000       ;begin normal init if so
FEC3: F68000            LDB     $8000       ;get SW1-4
FEC6: C407              ANDB    #$07        ;mask to SW1-3
FEC8: 8EFED2            LDX     #$FED2      ;load test routine table
FECB: 58                ASLB                ;2x
FECC: 3A                ABX                 ;indexing
FECD: 10AE84            LDY     ,X          ;load test routine pointer
FED0: 6EA4              JMP     ,Y          ;run test routine

;===============================================================================
; SW0-2 -> test
;
FED2: FEE2      ;111
FED4: FF08      ;110
FED6: FF29      ;101
FED8: FF3A      ;100
FEDA: FEAF      ;011 Nothing
FEDC: FEAF      ;010 Nothing
FEDE: FEAF      ;001 Nothing
FEE0: F000      ;000 Normal operation

;===============================================================================
; Test mode 7 (SIO transmit test)
;
FEE2: 7F6000            CLR     $6000
FEE5: 8603              LDA     #$03
FEE7: B72000            STA     $2000
FEEA: 8615              LDA     #$15
FEEC: B72000            STA     $2000
FEEF: B62000            LDA     $2000
FEF2: B62001            LDA     $2001
FEF5: 4F                CLRA
FEF6: F60800            LDB     $0800
FEF9: F62000            LDB     $2000       ;load ACIA status
FEFC: C502              BITB    #$02        ;check for transmit empty
FEFE: 27F9              BEQ     $FEF9       ;loop if not
FF00: B72001            STA     $2001       ;write byte to SIO
FF03: 4C                INCA                ;increment test byte
FF04: 27F0              BEQ     $FEF6
FF06: 20F1              BRA     $FEF9

;===============================================================================
; Test mode 6
;
FF08: 8E0000            LDX     #$0000
FF0B: 865A              LDA     #$5A
FF0D: A784              STA     ,X
FF0F: E680              LDB     ,X+
FF11: 8C0402            CMPX    #$0402
FF14: 26F7              BNE     $FF0D
FF16: 8E0000            LDX     #$0000
FF19: 86A5              LDA     #$A5
FF1B: A784              STA     ,X
FF1D: E680              LDB     ,X+
FF1F: 8C0402            CMPX    #$0402
FF22: 26F7              BNE     $FF1B
FF24: B60800            LDA     $0800
FF27: 20DF              BRA     $FF08

;===============================================================================
; Test mode 5
;
FF29: 8EF000            LDX     #$F000
FF2C: 8C0000            CMPX    #$0000
FF2F: 2704              BEQ     $FF35
FF31: A680              LDA     ,X+
FF33: 20F7              BRA     $FF2C
FF35: B60800            LDA     $0800
FF38: 20EF              BRA     $FF29

;===============================================================================
; Test mode 4
;
FF3A: 8600              LDA     #$00
FF3C: B71800            STA     $1800       ;write to printer port
FF3F: 8A10              ORA     #$10
FF41: B76000            STA     $6000
FF44: 4C                INCA
FF45: 26F5              BNE     $FF3C
FF47: B60800            LDA     $0800
FF4A: 20EE              BRA     $FF3A

;===============================================================================
FF4C: 0000              NEG     $00
FF4E: 0000              NEG     $00
FF50: 0000              NEG     $00
FF52: 0000              NEG     $00
FF54: 0000              NEG     $00
FF56: 0000              NEG     $00
FF58: 0000              NEG     $00
FF5A: 0000              NEG     $00
FF5C: 0000              NEG     $00
FF5E: 0000              NEG     $00
FF60: 0000              NEG     $00
FF62: 0000              NEG     $00
FF64: 0000              NEG     $00
FF66: 0000              NEG     $00
FF68: 0000              NEG     $00
FF6A: 0000              NEG     $00
FF6C: 0000              NEG     $00
FF6E: 0000              NEG     $00
FF70: 0000              NEG     $00
FF72: 0000              NEG     $00
FF74: 0000              NEG     $00
FF76: 0000              NEG     $00
FF78: 0000              NEG     $00
FF7A: 0000              NEG     $00
FF7C: 0000              NEG     $00
FF7E: 0000              NEG     $00
FF80: 0000              NEG     $00
FF82: 0000              NEG     $00
FF84: 0000              NEG     $00
FF86: 0000              NEG     $00
FF88: 0000              NEG     $00
FF8A: 0000              NEG     $00
FF8C: 0000              NEG     $00
FF8E: 0000              NEG     $00
FF90: 0000              NEG     $00
FF92: 0000              NEG     $00
FF94: 0000              NEG     $00
FF96: 0000              NEG     $00
FF98: 0000              NEG     $00
FF9A: 0000              NEG     $00
FF9C: 0000              NEG     $00
FF9E: 0000              NEG     $00
FFA0: 0000              NEG     $00
FFA2: 0000              NEG     $00
FFA4: 0000              NEG     $00
FFA6: 0000              NEG     $00
FFA8: 0000              NEG     $00
FFAA: 0000              NEG     $00
FFAC: 0000              NEG     $00
FFAE: 0000              NEG     $00
FFB0: 0000              NEG     $00
FFB2: 0000              NEG     $00
FFB4: 0000              NEG     $00
FFB6: 0000              NEG     $00
FFB8: 0000              NEG     $00
FFBA: 0000              NEG     $00
FFBC: 0000              NEG     $00
FFBE: 0000              NEG     $00
FFC0: 0000              NEG     $00
FFC2: 0000              NEG     $00
FFC4: 0000              NEG     $00
FFC6: 0000              NEG     $00
FFC8: 0000              NEG     $00
FFCA: 0000              NEG     $00
FFCC: 0000              NEG     $00
FFCE: 0000              NEG     $00
FFD0: 0000              NEG     $00
FFD2: 0000              NEG     $00
FFD4: 0000              NEG     $00
FFD6: 0000              NEG     $00
FFD8: 0000              NEG     $00
FFDA: 0000              NEG     $00
FFDC: 0000              NEG     $00
FFDE: 0000              NEG     $00
FFE0: 0000              NEG     $00
FFE2: 0000              NEG     $00
FFE4: 0000              NEG     $00
FFE6: 0000              NEG     $00
FFE8: 0000              NEG     $00
FFEA: 0000              NEG     $00
FFEC: 0000              NEG     $00
FFEE: 0000              NEG     $00
FFF0: 0000              NEG     $00
FFF2: 0000              NEG     $00
FFF4: 0000              NEG     $00

FFF6: F000      ;FIRQ
FFF8: FDEF      ;IRQ
FFFA: F000      ;SWI
FFFC: FDDF      ;NMI
FFFE: FEAF      ;Reset
