2023-11-16 18:19:54 -05:00

180 lines
3.5 KiB
Plaintext

PAGE
SBTTL "--- DISK ACCESS: ATARI ---"
; --------------------
; READ A VIRTUAL BLOCK
; --------------------
; ENTRY: TARGET V-BLOCK IN [DBLOCK]
; TARGET RAM PAGE IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
GETDSK: CLD
LDA #1 ; V-BLOCKS ALWAYS COME
STA DRIVE ; FROM DRIVE #1
; CALCULATE SECTOR OF [DBLOCK]
LDX DBLOCK+LO ; COPY LSB OF [DBLOCK]
STX SECTOR+LO ; INTO [SECTOR]
LDA DBLOCK+HI
AND #%00000001 ; MASK ALL BUT BIT 1
STA SECTOR+HI
BNE INPURE ; BLOCK IS PURE IF MSB <> 0
CPX ZPURE ; ELSE CHECK LSB
BCS INPURE ; PURE IF >= [ZPURE]
; HANDLE A PRELOAD BLOCK
ASL SECTOR+LO ; MULTIPLY BY 2
ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS
LDA SECTOR+LO
CLC
ADC #73 ; ADD DISK PRELOAD OFFSET
STA SECTOR+LO
BCC RDISK
INC SECTOR+HI
BNE RDISK ; AND READ THE SECTOR
; HANDLE A PURE BLOCK
INPURE: LDA SECTOR+LO
SEC ; STRIP OFF THE
SBC ZPURE ; VIRTUAL PRELOAD OFFSET
STA SECTOR+LO
BCS INP0
DEC SECTOR+HI
INP0: ASL SECTOR+LO ; MULTIPLY BY 2
ROL SECTOR+HI ; FOR ATARI 128-BYTE SECTORS
INC SECTOR+LO ; DISK "PURE" OFFSET IS 1
BNE RDISK
INC SECTOR+HI
; FALL THROUGH ...
; -----------------
; READ A DISK BLOCK
; -----------------
; ENTRY: TARGET SECTOR IN [SECTOR]
; TARGET DRIVE IN [DRIVE]
; PAGE TO READ IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
RDISK: LDA #$52 ; "READ" COMMAND
JSR DODISK ; GET DATA INTO [IOBUFF]
BCS IOERR ; SOMETHING WRONG IF CARRY SET
LDY #0 ; MOVE DATA IN [IOBUFF]
RDSK0: LDA IOBUFF,Y ; TO [DBUFF]
STA (DBUFF),Y
INY
BNE RDSK0
BEQ SNEXT ; UPDATE & RETURN
; ------------------
; WRITE A DISK BLOCK
; ------------------
; ENTRY: TARGET SECTOR IN [SECTOR]
; TARGET DRIVE IN [DRIVE]
; PAGE TO WRITE IN [DBUFF]
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
PUTDSK: LDY #0 ; MOVE THE PAGE
PDSK0: LDA (DBUFF),Y ; AT [DBUFF]
STA IOBUFF,Y ; INTO [IOBUFF]
INY
BNE PDSK0
LDA #$57 ; "WRITE" COMMAND
JSR DODISK
BCS IOERR ; SOMETHING WRONG IF CARRY SET
SNEXT: INC DBUFF+HI ; POINT TO NEXT RAM PAGE
INC DBLOCK+LO ; NEXT V-PAGE
BNE SNX0
INC DBLOCK+HI
SNX0: INC SECTOR+LO ; AND NEXT SECTOR
BNE SNX1
INC SECTOR+HI
SNX1: CLC ; CLEAR CARRY FOR SUCCESS
IOERR: RTS ; ELSE RETURN WITH CARRY SET
; ---------------
; ACCESS THE DISK
; ---------------
; ENTRY: [A] = $52 TO READ, $57 TO WRITE
; [DRIVE] = TARGET DRIVE (1 OR 2)
; [SECTOR] = TARGET SECTOR
; EXIT: CARRY CLEAR IF OKAY, SET IF NOT
DODISK: STA DCOMND ; SET READ/WRITE COMMAND
LDA DRIVE ; SPECIFY
STA DUNIT ; WHICH DRIVE TO USE
; CHECK VALIDITY OF SECTOR RANGE
LDX SECTOR+LO ; GET LSB AND
LDA SECTOR+HI ; MSB OF TARGET SECTOR
CMP #$02 ; MSB WITHIN RANGE?
BCC RANOK ; OKAY IF < 2
BNE RANERR ; RANGE ERROR IF > 2
CPX #$D0 ; IF MSB WAS $02, IS LSB < $CF?
BCS RANERR ; ERROR IF NOT
RANOK: STX DAUX1 ; TELL SIO
STA DAUX2 ; WHICH SECTOR TO USE
LDA #LOW IOBUFF ; POINT TO
STA DBUFLO ; THE BOTTOM HALF
LDA #HIGH IOBUFF ; OF [IOBUFF]
STA DBUFHI
JSR DSKINV ; ACCESS 1ST HALF OF [IOBUFF]
LDA DSTATS ; CHECK STATUS
BMI DERR ; ERROR IF NEGATIVE
INC SECTOR+LO ; POINT TO NEXT SECTOR
BNE DDSK0
INC SECTOR+HI
DDSK0: LDA SECTOR+LO ; UPDATE [DAUX1/2]
STA DAUX1
LDA SECTOR+HI
STA DAUX2
LDA #LOW BUFTOP ; POINT TO TOP HALF
STA DBUFLO ; OF [IOBUFF]
LDA #HIGH BUFTOP
STA DBUFHI
JSR DSKINV ; ACCESS TOP HALF OF [IOBUFF]
LDA DSTATS ; CHECK STATUS
BMI DERR ; ERROR IF NEGATIVE
CLC ; CLEAR CARRY FOR NO ERRORS
RTS
DERR: SEC ; OR SET IT IF ERROR
RTS
; *** ERROR #12: DISK ADDRESS OUT OF RANGE ***
RANERR: LDA #12
JMP ZERROR
END