;
; 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