;2/14/85
;
; **********************************************
; ***      C-64 END OF 1541 FAST LOADER      ***
; ***         ( WITH ERROR-CHECKING )        ***
; **********************************************
;
;***  VARIABLES  ***
       *=$02
;
TRACK  *=*+1
SECTOR *=*+1
DATA   *=*+1
TOREAD *=*+1
PTR    *=*+2 ; (2 BYTES).
STAT   *=*+1
DEVC   *=*+1 ; DEVICE NUMBER.
;
CI2PRA = $DD00
DATIN  = $80 ; PORT BITS.
CLKIN  = $40
DATOUT = $20
CLKOUT = $10
;
;
CHKIN  = $FFC6
CHKOUT = $FFC9
CHRIN  = $FFCF
CHROUT = $FFD2
CLRCHN = $FFCC
CLOSE  = $FFC3
SETNAM = $FFBD
SETLFS = $FFBA
OPEN   = $FFC0
;
RDCMD  = 1 ; DISK COMMAND TO READ IN AND SEND A SECTOR.
OFFCMD = 0 ; DISK COMMAND TO REVERT TO DOS CONTROL.
;
;
;
       *=$C000; ****  ENTRY TO INIT AND LOAD A FILE  ****
;
FLDDEF LDX #21 ; DEFAULT TRACK & SECTOR.
       LDY #4
FLD8   LDA #8 ; DEFAULT TO DRIVE #8.
;
FLD    STA DEVC
       JSR FSTART ; ** INIT DRIVE  **  (NO PARAMS)
       BCS CLSALL ; ERROR ON OPEN..
;
       LDA CI2PRA+2 ; SAVE DDR VALUE.
       PHA
       LDA #DATOUT+CLKOUT ; NEW DDR.
       STA CI2PRA+2
       JSR FLOAD    ; ** LOAD A FILE **  (X,Y = T,S)
       PLA
       STA CI2PRA+2 ; RESTORE DDR.
;
CLSALL LDA #2     ; CLOSE FILES.
       JSR CLOSE
       LDA #15
       JSR CLOSE ; *****  EXIT  *****
;
       SEC
       LDA STAT ; STATUS (.A) SHOULD BE ZERO ON EXIT.
       CMP #1
       BNE EXIT
       CLC      ; CARRY-CLEAR IF ALL OK.
       LDA #0
EXIT   RTS
;
;
;
;***********************************************************
;***  INIT :  READ DRIVE PROGRAM FROM SECTOR INTO DRIVE  ***
;***********************************************************
;
FSTART STX TRACK ;SAVE .X, .Y
       STY SECTOR
       LDA #1
       STA STAT ; START WITH NO ERROR.
;
       LDA #15
       JSR CLOSE
       LDA #2
       JSR CLOSE
       LDA #15 ; OPEN 15,8,15,"I0"
       TAY
       LDX DEVC
       JSR SETLFS
       LDA #2
       LDX #<I0
       LDY #>I0
       JSR SETNAM
       JSR OPEN
       BCC FINIT
;
ERRR   ORA #$80 ; I/O ERR: MAKE .A NON-ZERO.
ERR1   STA STAT
       SEC
       RTS
;
FINIT  LDA #2 ;OPEN THE DATA CHANNEL 2,8,2,"#2".
       LDX DEVC
       TAY
       JSR SETLFS
       LDA #2
       LDX #<DNAME1
       LDY #>DNAME1
       JSR SETNAM
       JSR OPEN
       BCS ERRR
;
       LDX #15 ; SEND 'B-P: 2 0'
       JSR CHKOUT
       LDY #0
SBP01  LDA BFPNT,Y
       BEQ SBP05
       JSR CHROUT
       INY
       BNE SBP01
SBP05  JSR CLRCHN
;
       LDX #2     ;SEND DRIVE CODE TO $0500.
       JSR CHKOUT ; (256 BYTES)
       BCS ERRR
       LDY #0
       FNT0 LDA DRVCOD,Y
       JSR CHROUT
       INY
       BNE FNT0
FNT5   JSR CLRCHN ;SEND EOI.
;
       LDX #15
       JSR CHKOUT ; SEND REST OF CODE IN 'M-W' CMD.
       LDY #5
MW0010 LDA MWR1,Y
       JSR CHROUT
       DEY
       BPL MW0010
       LDY #0    ; 31 MORE BYTES.
MW0020 LDA DRVCOD+256,Y
       JSR CHROUT
       INY
       CPY MWR1
       BNE MW0020
       JSR CLRCHN
;
       LDX #$0F  ;DRIVE: JMP TO $0500.
       JSR CHKOUT
       LDA #'U
       JSR CHROUT
       LDA #'3
       JSR CHROUT
       JSR CLRCHN ;DONE INIT.
;
       LDX TRACK
       LDY SECTOR ;RECOVER .X, .Y
       CLC
       RTS
;
;
I0     .BYT 'I0'
DNAME1 .BYT '#2'
BFPNT  .BYT 'B-P: 2 0',0
MWR1   .BYT 31,6,0,'W-M'
;
;
;
;**********************************************************
;**   LOAD A FILE:   GIVE STARTING TRACK=.X, SECTOR=.Y   **
;**********************************************************
; *
; * DRIVE REVERTS TO NORMAL DOS CONTROL AFTER
; *   FILE IS LOADED.
; * DRIVE MUST BE INITIALIZED, READY FOR RDCMD.
; *
;
FLOAD  STX TRACK  ; SAVE FILE'S STARTING T,S.
       STY SECTOR
       LDA CI2PRA ; CLEAR LINES.
       AND #$FF-CLKOUT-DATOUT
       STA CI2PRA
FL0    BIT CI2PRA ; WAIT FOR LINES TO CLEAR.
       BPL FL0
       BVC FL0
;
       LDA #RDCMD ; DISK COMMAND TO GET A SECTOR.
       JSR SNDBYT
       LDA TRACK  ; GIVE FIRST T,S.
       JSR SNDBYT
       LDA SECTOR
       JSR SNDBYT
;
       JSR GETBYT ; GET JOB STATUS FIRST.
       STA STAT
;
FL1    JSR GETBYT
       STA TRACK  ; GET T,S LINK (NEXT SECTOR).
       JSR GETBYT
       STA SECTOR
;
       JSR GETBYT ; GET FILE STARTING ADDRESS.
       STA PTR
       JSR GETBYT
       STA PTR+1
;
       LDA #252   ; 252 BYTES LEFT IN THIS BLOCK.
       STA TOREAD
;
;                  ; GET A BYTE.
FLO010 JSR GETBYT
       LDX TRACK   ; IS THIS LAST SECTOR?
       BNE FLO015  ; (NO)
       TAX
       LDA SECTOR  ; (YES) ARE WE PAST END OF FILE?
       EOR #$FF
       CMP TOREAD
       BCS FLO017  ; (YES) WAIT OUT REST OF SECTOR.
       TXA
;
FLO015 LDY #0      ; (NO) STORE BYTE.
       STA (PTR),Y
;
FLO017 INC PTR    ; INCREMENT POINTER.
       BNE FLO020
       INC PTR+1
;
FLO020 DEC TOREAD ; # BYTES LEFT IN THIS BLOCK.
       BNE FLO010
;
;
       LDA STAT   ; WAS READ OK?
       CMP #1
       BNE FLFIN  ; NO - DON'T FINISH LOAD.
;
       LDA TRACK  ; WAS THIS LAST SECTOR OF FILE?
       BNE FLO030
FLFIN  LDA #OFFCMD ; (YES) SEND "OFF" COMMAND TO DRIVE.
       JSR SNDBYT
       RTS        ; EXIT THE LOAD ROUTINE ("STAT").
;
;
FLO030 LDA #RDCMD ; (NO) READ ANOTHER SECTOR:
       JSR SNDBYT
       LDA TRACK  ; SEND OUT NEXT TRACK, SECTOR.
       JSR SNDBYT
       LDA SECTOR
       JSR SNDBYT
;
       JSR GETBYT ; GET JOB STATUS.
       STA STAT
;
       JSR GETBYT ; GET NEW T,S LINK.
       STA TRACK
       JSR GETBYT
       STA SECTOR
;
       LDA #254   ; 254 BYTES LEFT IN BLOCK.
       STA TOREAD
       JMP FLO010
;
;
;
;      ***************************
;      ***   SERIAL ROUTINES   ***
;      ***    (ANDY FINKEL)    ***
;      ***************************
;
;
;
;******************************
;*  GET BYTE FROM DISK DRIVE  *
;******************************
;
GETBYT LDA #$80
       STA DATA
;
GETBIT LDA CI2PRA ; SET CLOCK-HI.
       ORA #CLKOUT
       STA CI2PRA
;
GETBO0 LDA CI2PRA ; WAIT FOR DATA-HI.
       TAY
       AND #DATIN
       BNE GETBO0
;
       TYA       ; SET CLOCK-LO.
       AND #$FF-CLKOUT
       STA CI2PRA
;
GETBO1 LDA CI2PRA ; WAIT FOR DATA-LO.
       TAY
       AND #DATIN
       BEQ GETBO1
;
GETBO2 TYA       ; SET CLK-HI.
       ORA #CLKOUT
       STA CI2PRA
;
       LDX #7    ; ...WAIT FOR DRIVE TO SEND A BIT...
GETBO3 DEX
       BNE GETBO3
;
       LDA CI2PRA
       TAY         ; GET DATA BIT.
       AND #$FF-CLKOUT
       STA CI2PRA ; SET CLK-LOW.
       TYA
       ASL A
       ROR DATA
       BCC GETBO2  ; GET REST OF DATA BITS.
;
       LDA DATA
       EOR #$FF
       RTS
;
;
;*****************************
;*  SEND BYTE TO DISK DRIVE  *
;*****************************
;
SNDBYT STA DATA
       LDX #8
ABIT   JSR SCLK1  ; SET CLOCK-HI.
;
WAITD  JSR SETTLE ; WAIT FOR DATA-HI.
       AND #DATIN
       BNE WAITD
       JSR SCLK0  ; SET CLOCK-LO.
;
SNDB01 JSR SETTLE ; WAIT FOR DATA-LO.
       TAY
       AND #DATIN
       BEQ SNDB01
;
       TYA
       ORA #CLKOUT
       LSR DATA
       BCC SNDBO2
       ORA #DATOUT
SNDBO2 STA CI2PRA ; SEND A BIT WITH CLOCK-HI.
;
       LDY #7     ; ...WAIT...
SNDBO3 DEY
       BNE SNDBO3
;
       JSR SCLK0  ; CLEAR CLOCK.
;
       DEX
       BNE ABIT  ; DO OTHER BITS IN BYTE.
       RTS
;
;
;**********************
;*  DEBOUNCE IO PORT  *
;**********************
;
SETTLE LDA CI2PRA
       CMP CI2PRA
       BNE SETTLE
       RTS
;
;************************
;*  SET CLOCK OUT HIGH  *
;************************
;
SCLK1  LDA CI2PRA
       ORA #CLKOUT
       AND #$FF-DATOUT
       BNE PUTPRT
;
;***********************
;*  SET CLOCK OUT LOW  *
;***********************
;
SCLK0  LDA CI2PRA
       AND #$FF-DATOUT-CLKOUT
;
PUTPRT STA CI2PRA
       NOP
       NOP
       RTS
;
;
DRVCOD *=*+287 ; DISK DRIVE CODE AT END.
;
;
.END
