; ; STOCK 810 ROM ; ; Automata states. ; Each bit has a different ; meaning and is used to ; know what should be done ; next. ; AUT01 = $01 AUT02 = $02 AUTWAIT = $04 AUTVER = $08 AUT10 = $10 AUT20 = $20 AUT40 = $40 AUT80 = $80 ; ; Command Status bits. ; Used in LSTATCMD. ; STATNONE = $00 STATCMD = $01 STATDATA = $02 STATERR = $04 STATWP = $08 STATACT = $10 ; ; Controller Status bits. ; Used in LSTATHW. ; CTRLBUSY = $01 CTRLDRQ = $02 CTRLLOST = $04 CTRLCRC = $08 CTRLRNF = $10 CTRLTYPE = $20 CTRLWP = $40 CTRLMON = $80 ; ; Controller commands. ; These values are written ; into WCOMMAND register ; to ask the controller ; for a particular task. ; WCMDWTRK = $F4 WCMDFINT = $D0 WCMDWSEC = $A8 WCMDRSEC = $88 WCMDSEEK = $13 WCMDREST = $00 ; ; Inverted controller ; commands. ; Commands are written ; inverted int the ; controller regsiters. ; IWCWTRK = $FF-WCMDWTRK IWCFINT = $FF-WCMDFINT IWCWSEC = $FF-WCMDWSEC IWCRSEC = $FF-WCMDRSEC IWCSEEK = $FF-WCMDSEEK IWCREST = $FF-WCMDREST ; ; Length of Status answer ; Length of checksum ; Timeout for command ; STATLEN = $04 SUMLEN = $01 TIMEOUT = $E0 ; ; Answer to a command. ; ACK = $41 ; 'A' COMPLETE = $43 ; 'C' ERROR = $45 ; 'E' NACK = $4E ; 'N' ; ; WDC 1771 registers ; WSTATUS = $00 ; Read WCOMMAND = $00 ; Write WTRACK = $01 WSECTOR = $02 WDATA = $03 ; ; WDC base address ; BASEWDC = $0000 ; ; WDC addresses ; WDCSTAT = BASEWDC+WSTATUS WDCCOMND = BASEWDC+WCOMMAND WDCTRACK = BASEWDC+WTRACK WDCSECT = BASEWDC+WSECTOR WDCDATA = BASEWDC+WDATA ; ; RIOT 6532 registers ; DRA = $00 DDRA = $01 DRB = $02 DDRB = $03 EDGECTRL = $04 WR1NOIT = $14 WR8NOIT = $15 WR1IT = $1C WR64IT = $1E WR1024IT = $1F ; ; Port A bits ; SWITCH1 = $01 DRVMOTOR = $02 SWITCH2 = $04 UNUSED = $08 WPT1771 = $10 VSS6532 = $20 IRQ1771 = $40 DRQ1771 = $80 ; ; Port B bits ; DATAOUT = $01 VCCRDY = $02 PHASE4 = $04 PHASE3 = $08 PHASE2 = $10 PHASE1 = $20 COMMAND = $40 DATAIN = $80 ; ; RIOT base address ; BASERIOT = $0380 ; ; RIOT addresses ; RIOTDRA = BASERIOT+DRA RIOTDDRA = BASERIOT+DDRA RIOTDRB = BASERIOT+DRB RIOTDDRB = BASERIOT+DDRB RIOTEDGE = BASERIOT+EDGECTRL RIOTW1NO = BASERIOT+WR1NOIT RIOTW8NO = BASERIOT+WR8NOIT RIOTW1 = BASERIOT+WR1IT RIOTW64 = BASERIOT+WR64IT RIOTW1K = BASERIOT+WR1024IT ; ; Sector buffer ; SECTOR = $0080 ; ; Code equates ; L00E0 = $00E0 L00E1 = $00E1 L00E2 = $00E2 L00E3 = $00E3 L00F8 = $00F8 ; L0180 = $0180 LCMDDRV = $0181 LCMDCMD = $0182 LCMDAUX1 = $0183 LCMDAUX2 = $0184 LSNDBYTE = $0186 L0187 = $0187 LCURDRB = $01CD LCURTRK = $01CE L01CF = $01CF LSTATCMD = $01D0 LSTATHW = $01D1 LSTATTIM = $01D2 LUNUSED = $01D3 LSTATSUM = $01D4 LSAVAUX2 = $01D7 LSAVAUX1 = $01D8 LTRKNUM = $01DA LSECNUM = $01DB LAUTOM = $01DD LENDCMD = $01DE LPAUSE = $01DF L01E0 = $01E0 L01E1 = $01E1 L01E2 = $01E2 L01E3 = $01E3 L01E4 = $01E4 LJMPCMD = $01E8 LOFSCMD = $01EA L01EB = $01EB ; ; Start of code ; *= $0800 ; ; Code starts here when ; the drive is turned on. ; START CLD ; ; Configure DRVMOTOR and ; UNUSED pins as output. ; All other pins (SWITCH1, ; SWITCH2, WPT1771,...) ; are input pins. ; LDA #DRVMOTOR+UNUSED STA RIOTDRA STA RIOTDDRA ; ; Configure PHASE1-4 pins ; as output. All other pins ; are input pins even ; DATAOUT so that no data is ; sent on the SIO bus now. ; LDX #PHASE1+PHASE2+PHASE3+PHASE4 STX RIOTDDRB STX RIOTEDGE LDX #0 STX RIOTDRB ; ; Stop current controller ; operation (if any) by ; sending a Force Interrupt ; command. This will fill ; the status register. ; LDA #IWCFINT STA WDCCOMND ; ; Remember to wait so that ; Force Interrupt command ; is not cancelled. ; LDA #AUTWAIT+AUT01 STA LAUTOM ; ; Fill last part of status ; buffer returned on a ; GET STATUS command. ; LDA #TIMEOUT STA LSTATTIM LDA #0 STA LUNUSED ; ; Sleep to let Force ; Interrupt command ; terminate. ; JSR LCHKWAIT LDY #$27 JSR L0C8B STY WDCTRACK DEY STY WDCSECT JSR LCLRSTAT JSR LCHKPRT LDX #$01 STX L01EB ; ; Reset stack. ; Get ready for the next ; command from the computer. ; LRESSTK LDX #$FF TXS LDA #$D8 JSR L0C1B STY L01CF ; ; Restore head to track 0. ; L084C LDA #IWCREST STA WDCCOMND LDA #AUT20 ; ; Jump over sector table ; JMP LOVERTBL ; ; Maybe unused... ; Who knows ? ; .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0 ; ; 18 sector numbers ; LFMTTAB .BYTE $00,$FE,$FC,$FA .BYTE $F8,$F6,$F4,$F2 .BYTE $F0,$EE,$FD,$FB .BYTE $F9,$F7,$F5,$F3 .BYTE $F1,$EF ; LOVERTBL JSR LORAUT L0883 BIT RIOTDRA BVS L088E JSR L0CAB JMP L0883 L088E DEC L01EB BPL L084C L0893 LDX #$80 LDY L01CF BEQ L08AA JSR L08ED STY L01CF JSR L0CAB L08A3 LDA RIOTW8NO BPL L08A3 BMI L0893 L08AA LDA #UNUSED STA RIOTDRA LDA #0 STA RIOTDRB LDA #$DF JSR LANDAUT LDA #AUTWAIT JSR LORAUT JMP L0CAB ; ; Check if sector number ; in DAUX1/DAUX2 is valid ; ($1 to $2D0). ; LCHKSEC LDX LCMDAUX2 LDA LCMDAUX1 BEQ LSECLOW ; ; Check high limit. ; LSECHIGH CPX #$03 BCS LSECERR CMP #$D1 BCS LSECLAST ; ; Sector number is valid ; LSECOK CLC RTS ; ; Check low limit. ; LSECLOW CPX #0 BNE LSECHIGH ; ; Sector number is out of ; range. ; LSECERR SEC RTS ; ; If DAUX1 is higher than ; $D0 then DAUX2 should not ; exceed $1. ; LSECLAST CPX #$02 BEQ LSECERR JMP LSECOK RTS ; ; Sleep for a certain amount ; of time. ; LSLEEP STA LPAUSE LWAIT DEY BNE LWAIT DEC LPAUSE BNE LWAIT RTS L08ED LDA #$29 STA RIOTW64 LDA RIOTDRB AND #PHASE1+PHASE2+PHASE3+PHASE4 INX BMI L090C INC LCURTRK LSR A STA LCURDRB AND #$02 BEQ L091E LDA #$20 ORA LCURDRB BPL L0921 L090C DEC LCURTRK ASL A STA LCURDRB AND #$40 BEQ L091E LDA #$04 ORA LCURDRB BPL L0921 L091E LDA LCURDRB L0921 STA RIOTDRB DEY RTS ; ; GET SECTOR ; ---------- ; LGET JSR LCHKSEC BCS LBADSEC ; ; Wait for SIO COMMAND to ; be clear and send ACK to ; the computer. ; JSR LCMDACK JSR LMOTORON JSR LCHKWAIT JSR LSEEKTRK L0937 LDA #IWCRSEC STA WDCCOMND L093B BVS L094C LDA RIOTW1 L0940 BIT RIOTDRA BPL L093B LDA WDCDATA INX STA SECTOR,X BPL L0940 L094C JSR L0970 BCS L0965 L0951 LDA #COMPLETE L0953 STA LSNDBYTE JSR LCHKDATA STA L0187 JSR LDATAOUT JSR L0E0F JMP LRESSTK L0965 BNE L0937 L0967 LDA #ERROR JMP L0953 LBADSEC JMP LBADCMD .BYTE $AD L0970 LDA WDCSTAT STA LSTATHW EOR #$FF BNE L0984 CLC LDA #$FB JSR LANDSTAT L097F JSR L0F68 DEY RTS L0984 CPY #$02 BNE L09A3 AND #CTRLRNF BEQ L09A3 STY LPAUSE JSR LCHKWAIT LDY #$2B JSR L0C8B LDA LTRKNUM JSR L0C1B JSR L0F18 LDY LPAUSE L09A3 LDA #STATERR JSR LORSTAT SEC JMP L097F ; ; FORMAT ; ------ ; LFORMAT JSR LCMDACK JSR LMOTORON JSR LCHKWAIT LDY #$2B JSR L0C8B JSR L0F63 LDA RIOTDRA AND #WPT1771 BEQ LNWPROT LDA #STATWP JSR LORSTAT JMP L0A95 LNWPROT LDA #$FF STA L00E3 JSR L09EB L09D3 DEC L00E3 LDA L00E3 CMP #$D7 BEQ L09E3 LDX #$80 JSR L09E8 JMP L09D3 L09E3 JMP L0AA3 BCS L09E8 L09E8 JSR L0B6D L09EB LDA #LFMTTAB&$FF STA L00E0 LDA #LFMTTAB/256 STA L00E1 LDA RIOTW1NO LDA #$ED STA L00E2 LDY #$FF LDX #$FF LDA #IWCWTRK STA WDCCOMND JSR L0A8D LDA #$0D STA RIOTW1K LDY #$FF JSR L0A80 STX RIOTW1K LDY #$03 JSR L0A8D LDY #$0B JSR L0A80 L0A1C LDY #$06 JSR L0A80 LDY #$01 JSR L0A8D LDY L00E3 JSR L0A8D LDY #$FF JSR L0A8D LDY L00E2 JSR L0A8D LDY #$FF JSR L0A8D LDY #$08 JSR L0A8D LDY #$11 JSR L0A80 LDY #$04 JSR L0A8D LDY #$80 LDX #0 JSR L0A80 LDY #$08 JSR L0A8D LDY #$09 LDX #$FF JSR L0A80 JSR L0A8D INC L00E0 BMI L0A79 JSR L0A8D LDA (L00E1,X) STA L00E2 JMP L0A6F L0A6D BVS L0A95 L0A6F BIT RIOTDRA BPL L0A6D STY WDCDATA JMP L0A1C L0A79 LDA #IWCFINT STA WDCCOMND RTS L0A7E BVS L0A95 L0A80 BIT RIOTDRA BPL L0A7E STX WDCDATA DEY BNE L0A80 RTS L0A8B BVS L0A95 L0A8D BIT RIOTDRA BPL L0A8B STY WDCDATA RTS L0A95 LDX #$FF STX SECTOR STX SECTOR+1 LDA WDCSTAT STA LSTATHW JMP L0E71 L0AA3 LDX #0 STX L01E1 L0AA8 LDA LCURTRK STA WDCTRACK LDA #$FE L0AAF STA LSECNUM STA WDCSECT LDY #$02 STY L01E0 L0AB9 JSR L0F81 LDY #$01 JSR L0970 BCS L0AF3 L0AC3 LDA LSECNUM SEC SBC #$04 CMP #$EA BNE L0ACF LDA #$FB L0ACF CMP #$EB BNE L0AD5 LDA #$FC L0AD5 CMP #$EC BNE L0ADB LDA #$FD L0ADB CMP #$E9 BNE L0AAF LDA LCURTRK CMP #$FF BEQ L0AF0 LDX #0 LDY #$01 JSR L0F18 JMP L0AA8 L0AF0 JMP L0E58 L0AF3 DEC L01E0 BNE L0AB9 LDX L01E1 JMP L0E79 ; ; Get DRVMOTOR bit from ; Port A. ; LDRVBIT LDA RIOTDRA LSR A LSR A ; ; Set the STATACT bit ; (active drive) in the ; command status byte ; if the DRVMOTOR bit ; is set. ; LDA #STATACT BCS LORSTAT LDA #STATNONE ; ; modify command status ; byte. ; LORSTAT ORA LSTATCMD STA LSTATCMD RTS ; ; Set command status byte ; by clearing it and ORing ; it with the Accumulator. ; LSETSTAT PHA LDA #0 AND LSTATCMD STA LSTATCMD PLA JMP LORSTAT RTS LORAUT ORA LAUTOM STA LAUTOM RTS LANDAUT AND LAUTOM STA LAUTOM RTS ; ; Clear all status bits ; except Write Protect flag. ; LCLRSTAT LDA #STATWP ; ; Clear some status bits. ; LANDSTAT AND LSTATCMD STA LSTATCMD RTS L0B35 LDA RIOTDRB BPL L0B35 TXA BEQ L0B67 LDA L0180,X EOR #$FF STA L0180,X L0B45 NOP NOP NOP LDY #$78 L0B4A NOP NOP NOP NOP LDA RIOTDRB ROL A ROR LCMDDRV,X INY BPL L0B4A INX CPX LENDCMD BNE L0B35 LDA L0180,X EOR #$FF STA L0180,X RTS L0B67 NOP NOP NOP JMP L0B45 L0B6D LDA #$02 JSR LSLEEP JSR L08ED RTS ; ; Receive a sector (128 bytes) ; from computer. The byte is ; transmitted bit after bit ; through the DATAIN line of ; port B. ; LRCVSEC LDX #0 LDY #$07 STY LENDCMD ; ; Wait for the start bit. ; LWSTART LDA RIOTDRB BPL LWSTART ; ; Do not invert byte in the ; first iteration because we ; did not read any byte yet. ; TXA BEQ LRFIRST ; ; Invert all bits of the byte ; that has been received. ; LDA SECTOR-1,X EOR #$FF STA SECTOR-1,X ; ; Loop to receive all bytes. ; LRCVBYTE NOP NOP NOP LDY #$78 ; ; Loop to receive all bits of ; a byte. ; LRCVBIT NOP NOP NOP LDA SECTOR ; ; Get DATAIN line of port B ; and save it into SECTOR ; buffer. ; LDA RIOTDRB ROL A ROR SECTOR,X ; ; Next bit... ; INY BPL LRCVBIT ; ; Next byte... ; INX BPL LRCVNEXT ; ; All bytes have been received. ; LDX #$06 JSR L0B35 LDA L00F8,X EOR #$FF STA L00F8,X RTS ; ; One NOP for timing and get ; ready for next byte. ; LRCVNEXT NOP JMP LWSTART ; ; Spend time to wait for the ; end of the start bit ; transmission. ; LRFIRST NOP NOP NOP JMP LRCVBYTE ; ; Compute a checksum of a ; command. ; Upon entry, ; - X contains the offset ; of the command from the ; label LCMDDRV. ; - Address LENDCMD contains ; the last offset of the ; command from the label ; LCMDDRV. ; This subroutine returns ; the checksum in A. ; LCHKSUM LDA #0 CLC LCHKLOOP ADC LCMDDRV,X PHP ; ; Is it the last byte of the ; command ? ; INX CPX LENDCMD ; ; Last byte has been ; processed. Get out of the ; loop. ; BEQ LCHKEND PLP JMP LCHKLOOP ; ; The checksum is computed. ; We add the carry. ; LCHKEND PLP ADC #0 ; ; Compare checksum with the ; one from the command. This ; is useful only with the ; command received from the ; computer. ; CMP LCMDDRV,X RTS ; ; Absolute sector number ; given in DAUX1/DAUX2 is ; converted into a track ; number and a sector number. ; LCNVSEC LDA LCMDAUX2 STA LSAVAUX2 LDA LCMDAUX1 STA LSAVAUX1 ; ; Sector number is divided ; by 16. ; LDX #$04 LCNVDIV ROR LCMDAUX2 ROR A DEX BNE LCNVDIV ROR LCMDAUX2 ; ; LCMDAUX2 now contains in ; its 4 high bits the value ; of DAUX1 4 low bits. ; LCMDAUX2 is shifted right ; 4 times to have a value ; between $01 and $0F. ; LDX #$04 LCNVHI LSR LCMDAUX2 DEX BNE LCNVHI ; ; A contains absolute ; sector number divided ; by 16. A is multiplied ; by 2 to be compared to ; LCMDAUX2. ; LCNVEND ASL A ; ; If C is Clear, it means ; that A contains the track ; number multiplied by 2. ; If C is Set, it means ; that LCMDAUX2 should be ; adjusted to get the track ; number. ; CMP LCMDAUX2 BCS LCNVSET ; ; A is divided by 2 to ; get the track number. ; It is saved inverted. ; STA LCMDAUX1 LSR A EOR #$FF STA LTRKNUM SEC LDA LCMDAUX2 SBC LCMDAUX1 EOR #$FF STA LSECNUM RTS ; ; The division of LCMDAUX2 ; by 16 has to be adjusted ; to get the track number. ; LCNVSET LSR A TAX DEX LDA #$10 CLC ADC LCMDAUX2 STA LCMDAUX2 TXA JMP LCNVEND L0C1B LDX #0 LDY #0 SEC SBC LCURTRK BEQ L0C2F BPL L0C2E LDX #$80 EOR #$FF CLC ADC #$01 L0C2E TAY L0C2F RTS ; ; Check if disk is write ; protected and store the ; info in status byte. ; LCHKPRT LDA RIOTDRA AND #WPT1771 BEQ LNOPRT LDA #STATWP JSR LORSTAT RTS LNOPRT LDA #$F7 JSR LANDSTAT RTS ; ; Start drive motor (if not ; already started). ; LMOTORON LDA RIOTDRA ; ; Check DRVMOTOR bit. ; If bit is set, it's OK. ; LSR A LSR A BCS L0C59 ; ; Start drive motor now. ; LDA #DRVMOTOR+UNUSED STA RIOTDRA STA WDCDATA LDA #$16 STA WDCTRACK LDA #IWCSEEK STA WDCCOMND L0C59 LDA #$01 STA L01EB RTS L0C5F LDA LAUTOM LSR A LSR A LSR A BCC L0C71 L0C67 BIT RIOTDRA BVC L0C67 LDA #$FB JSR LANDAUT L0C71 LDA #STATACT JSR LSETSTAT RTS ; ; Wait for the SIO COMMAND ; bit to be clear. ; LCMDACK BIT RIOTDRB BVS LCMDACK ; ; Send an ACK byte to the ; Atari ; LSENDACK LDA #ACK ; ; Send a byte from the ; Accumulator to the Atari. ; LSEND STA LSNDBYTE JSR LDATAOUT JSR LSNDDATA JSR LNODATA RTS L0C8B LDX #PHASE1+PHASE4 STX RIOTDRB L0C90 JSR L08ED BMI L0C9D L0C95 LDA RIOTW8NO BPL L0C95 JMP L0C90 L0C9D STY LCURTRK TXA LDX #$14 L0CA3 DEY BNE L0CA3 DEX BNE L0CA3 TAX RTS L0CAB LDA RIOTDRB LSR A LSR A BCS L0CE4 LDA LAUTOM LSR A BCS L0CD7 BIT RIOTDRB BVC L0CCC BIT LAUTOM BVC L0CEC LDA #$29 JSR LSLEEP BIT RIOTDRB BVS L0CEC L0CCC LDA LAUTOM AND #AUT40+AUT20 BNE L0CD6 JMP L0CAB L0CD6 RTS L0CD7 LDA #$29 JSR LSLEEP LDA #$FE JSR LANDAUT JMP L0CAB L0CE4 LDA #AUT01 JSR LORAUT JMP L0CCC L0CEC LDA #AUT80 JSR LORAUT LDX #0 LDA #$05 STA LENDCMD JSR L0B35 LDX #0 DEC LENDCMD JSR LCHKSUM BEQ LREADCFG LDA #AUT02 JSR LORAUT ; ; Get drive number from ; the switches at the rear ; of the drive. This is ; done by reading 2 bits ; from Port A of the 6532. ; Here are the possible ; values: ; ; SWITCH1 SWITCH2 Drive ; ON ON 1 ; OFF ON 2 ; OFF OFF 3 ; ON OFF 4 ; ; X will hold the drive ; number (by default 4): ; LREADCFG LDX #$34 ; ; Read port A and keep only ; bits from the 2 switches. ; LDA RIOTDRA AND #SWITCH1+SWITCH2 ; ; Switch configuration: ; SWITCH1 SWITCH2 Drive ; OFF OFF 3 ; BEQ LDRV3 ; ; Switch configuration: ; SWITCH1 SWITCH2 Drive ; OFF ON 2 ; CMP #SWITCH2 BEQ LDRV2 ; ; Switch configuration: ; SWITCH1 SWITCH2 Drive ; ON OFF 4 ; CMP #SWITCH1 BEQ LDRV4 ; ; Switch configuration: ; SWITCH1 SWITCH2 Drive ; ON ON 1 ; DEX LDRV2 DEX LDRV3 DEX ; ; X now holds the drive ; number ($31-$34) from the ; switches. Check that the ; command is for our drive. ; LDRV4 CPX LCMDDRV BEQ LDRVOK ; ; Command is not for our ; drive. Wait for the SIO ; COMMAND bit to be clear. ; LCMDSET1 BIT RIOTDRB BVS LCMDSET1 LDA #$7D JSR LANDAUT JMP L0CAB ; ; Check command sent ; by computer. ; LDRVOK JSR LCHKCMD JMP L0CAB ; ; GET STATUS ; ---------- ; LSTATUS JSR LSENDACK ; ; Compute checksum on the ; status frame answer. ; LDX #LSTATCMD-LCMDDRV LDY #LSTATCMD-LCMDDRV+STATLEN STY LENDCMD JSR LCHKSUM ; ; Store checksum at the ; end of the status frame ; answer. ; STA LSTATSUM ; ; Send a COMPLETE code to ; the computer. ; LDA #COMPLETE STA LSNDBYTE JSR LDATAOUT ; ; X will hold the count of ; bytes to send. ; The loop ends when reg X ; reaches $80. X is set to ; $80 minus the COMPLETE ; byte, minus the 4 bytes ; of the status answer and ; minus the checksum byte. ; LDX #$80-1-STATLEN-SUMLEN JSR LSNDDATA ; ; Send all status bytes to ; the computer. ; LSTATLP LDY LSTATCMD-$80+STATLEN+SUMLEN,X STY LSNDBYTE JSR LSNDDAT2 BPL LSTATLP ; ; All bytes have been sent. ; Turn off DATA OUT line. ; JSR LNODATA ; ; Reset all status bits ; except Write Protect then ; set Activity bit according ; to the WD1771 status. ; JSR LCLRSTAT JSR LDRVBIT JMP LRESSTK L0D6A LDY #0 STY L01E4 LDA LSECNUM EOR #$FF STA L01E2 LDA LCURTRK EOR #$FF ASL A STA L01E3 ASL A ASL A ROL L01E4 ASL A ROL L01E4 ADC L01E3 TAY LDA #0 ADC L01E4 JMP L0DDF ; ; ? ; LCHKCMD LDA LAUTOM LSR A LSR A BCS LBADCMD ; ; The command should be in ; the range of $4F to $57. ; LDA LCMDCMD CMP #$4F BCC LISFMT CMP #$58 BCS LISFMT ; ; Command is converted ; to a Jump address. ; The 3 low bits of the ; command byte are ; multiplied by 3. ; Appearently, $4F is the ; same as $57. ; AND #$07 STA LOFSCMD ASL A ADC LOFSCMD ; ; Then, the result is ; added to LTABCMD address. ; ADC #LTABCMD&$FF STA LJMPCMD LDA #0 ADC #LTABCMD/256 STA LJMPCMD+1 ; ; Execute the routine ; corresponding to ; the command. ; JMP (LJMPCMD) ; ; Is command equal to ; $21 (format). ; LISFMT CMP #$21 BEQ LJMPFMT ; ; The command sent is ; unknown ! ; LBADCMD LDA #STATCMD JSR LSETSTAT JSR LDRVBIT ; ; Wait for the SIO COMMAND ; bit to be clear. ; LCMDSET2 BIT RIOTDRB BVS LCMDSET2 ; ; Send NACK to the Atari. ; LDA #NACK JSR LSEND LDA #$FD JSR LANDAUT RTS ; ; Jump to format routine ; LJMPFMT JMP LFORMAT .BYTE $01 L0DDF STA L01E4 TYA CLC ADC L01E2 STA SECTOR,X LDA #0 ADC L01E4 INX STA SECTOR,X RTS ; ; Compute data checksum ; and check it. ; LCHKDATA LDA #0 TAX CLC LADDBYTE ADC SECTOR,X INX BPL LADDBYTE ADC #0 CMP L0187 RTS ; ; Set DATAOUT line of port B ; as an output line. ; LDATAOUT LDX RIOTDRB STX RIOTDRB LDX RIOTDDRB INX STX RIOTDDRB RTS L0E0F LDX #$FF JSR LSNDDATA L0E14 LDY SECTOR,X STY LSNDBYTE JSR LSNDDAT2 BPL L0E14 LDY L0187 STY LSNDBYTE JSR LSNDDAT2 ; ; Set DATAOUT line of Port B ; as an input line: No more ; data is sent to the Atari. ; LNODATA LDX RIOTDDRB DEX STX RIOTDDRB RTS ; ; Send a byte to the Atari. ; Each bit of the byte is ; put on the DATAOUT line of ; Port B (LSB bit first). ; LSNDDATA LDA RIOTDRB ; ; A start bit (value 0) is ; sent before the byte. ; LSNDDAT2 AND #$FE STA RIOTDRB ; ; Y register will hold the ; bit counter (from $78 to ; $80). ; LDY #$78 BIT SECTOR LSNDLOOP BIT SECTOR NOP NOP ; ; Send one bit from LSNDBYTE. ; LSR A ROR LSNDBYTE ROL A STA RIOTDRB INY BPL LSNDLOOP ; ; A stop bit (value 1) is ; sent after the byte. ; LSR A SEC ROL A NOP NOP NOP NOP NOP NOP STA RIOTDRB INX RTS L0E58 LDA #$FF LDX L01E1 STA SECTOR,X INX STA SECTOR,X LDA LAUTOM AND #AUTVER BNE L0E6C JMP L0951 L0E6C LDA #$F7 JSR LANDAUT L0E71 LDA #STATERR JSR LORSTAT JMP L0967 L0E79 LDA #AUTVER JSR LORAUT JSR L0D6A INX STX L01E1 CPX #$7E BNE L0E8C JMP L0E58 L0E8C JMP L0AC3 ; ; This is the jump table ; for the drive commands. ; The table is the following: ; ; Command Meaning ; $50 PUT SECTOR ; $51 UNUSED ; $52 GET SECTOR ; $53 GET STATUS ; $54 UNUSED ; $55 UNUSED ; $56 UNUSED ; $4F/$57 PUT SECTOR VERIFY ; LTABCMD JMP LPUT JMP LBADCMD JMP LGET JMP LSTATUS JMP LBADCMD JMP LBADCMD JMP LBADCMD JMP LPUTVER ; ; Wait for SIO COMMAND to ; be clear and send ACK to ; computer. ; LDOPUT JSR LCMDACK JSR LMOTORON JSR LRCVSEC JSR LCHKDATA BNE LBADDATA JSR LSENDACK JSR LCHKWAIT JSR LSEEKTRK LDA RIOTDRA AND #WPT1771 BNE LWPROT L0EC5 LDA #IWCWSEC STA WDCCOMND L0EC9 BVS L0EE5 LDA RIOTW1 BIT RIOTDRA BMI L0EDD JMP L0EC9 L0ED6 BVS L0EE5 L0ED8 BIT RIOTDRA BPL L0ED6 L0EDD INX LDA SECTOR,X STA WDCDATA JMP L0ED8 L0EE5 JSR L0970 LDA #ERROR BCS L0F42 LDA LAUTOM AND #AUTVER BEQ L0EFC JSR L0F9D BCC L0EFC LDA #ERROR BCS LSENDRES L0EFC LDA #COMPLETE L0EFE JMP LSENDRES LBADDATA LDA #STATACT+STATDATA JSR LSETSTAT LDA #NACK LSENDRES JSR LSEND JMP LRESSTK LWPROT LDA #STATERR+STATWP JSR LORSTAT LDA #ERROR JMP LSENDRES L0F18 BEQ L0F31 L0F1A JSR L08ED BEQ L0F27 L0F1F LDA RIOTW8NO BPL L0F1F JMP L0F1A L0F27 LDA #$50 STA RIOTW64 L0F2C LDA RIOTW8NO BPL L0F2C L0F31 RTS ; ; PUT SECTOR with VERIFY ; ---------------------- ; LPUTVER LDA #AUTVER JSR LORAUT ; ; PUT SECTOR ; ---------- ; LPUT JSR LCHKSEC BCS L0F3F JMP LDOPUT L0F3F JMP LBADCMD L0F42 CPY #0 BEQ L0F49 JMP L0EC5 L0F49 BEQ L0EFE ; ; Convert absolute sector ; number to a track and ; a sector number then ; seek to the track. ; LSEEKTRK JSR LCNVSEC LDA RIOTDRB AND #PHASE1+PHASE2+PHASE3+PHASE4 BNE L0F5A LDA #PHASE1+PHASE2 STA RIOTDRB L0F5A LDA LTRKNUM JSR L0C1B JSR L0F18 L0F63 JSR L0C5F LDY #$04 L0F68 LDA #IWCFINT STA WDCCOMND LDX #$FF L0F6E DEX BNE L0F6E LDA LTRKNUM STA WDCTRACK LDA LSECNUM STA WDCSECT CLV DEX STX RIOTW1K RTS L0F81 JSR L0F68 LDA LCURTRK STA WDCTRACK LDA #IWCRSEC STA WDCCOMND L0F8D BVS L0F9C LDA RIOTW1 L0F92 BIT RIOTDRA BPL L0F8D LDA WDCDATA JMP L0F92 L0F9C RTS L0F9D JSR L0F68 LDY #$01 L0FA2 INX LDA #IWCRSEC STA WDCCOMND L0FA7 BVS L0FBA LDA RIOTW1 L0FAC BIT RIOTDRA BPL L0FA7 LDA WDCDATA CMP SECTOR,X BNE L0FC7 INX BNE L0FAC L0FBA JSR L0970 BCC L0FC1 BPL L0FA2 L0FC1 LDA #$F7 JSR LANDAUT RTS L0FC7 JSR L09A3 JMP L0FC1 ; ; Check the automata to ; see if we have to sleep. ; LCHKWAIT LDA LAUTOM AND #AUTWAIT BEQ LNOWAIT LDA #$50 JSR LSLEEP LNOWAIT RTS ; ; This is just a padding so ; that the last two WORDs ; starts at address $0FFC ; and $0FFE. ; .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0,0,0,0,0,0,0 .BYTE 0,0 ; ; START is both the IRQ ; and RESET address. ; ; IMPORTANT: if you modify ; this source, always check ; that this word is at ; address $0FFC. If not, add ; or remove some of the ; padding bytes above. ; .WORD START ; RESET .WORD START ; IRQ ; .END