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