;Disk Transfer
;Copy programs from SD to Disk for the PET using the C64
;and the Telesys IEEE interface

;19-05-2013 Nonax


;Set-up
;Use a IEC drive on #10, in my case a uIEC
;In the expansion port is the Telesys IEEE interface
;Attached to it is an IEEE drive on #8, in my case a CBM 8050

;Problem
;PET (BASIC) programs start at $0401 where C64 (BASIC) programs
;start at $0801. This address is saved to the header of the file.
;To get a correct header the PET file is loaded to $0401 on the
;C64 and then saved to disk.
;There are two problems to overcome which prevents normal
;BASIC commands from working:
;1. $0401 is the location of the character screen on the C64
;2. SAVE will start saving from $0801

;Solution
;The screen is moved to BANK 2 with same offset ($8400)
;The data is force loaded to $0401 from device #10
;The data is saved from $0401 to device #8

*=$C000

;KERNAL routines
SETLFS    = $FFBA ;Set logical file
SETNAM    = $FFBD ;Set file name
LOAD      = $FFD5 ;Load file with params from SETLFS and SETNAM
SAVE      = $FFD8 ;Save file with params form SETLFS and SETNAM
GETIN     = $FFE4 ;Get character from keyboard buffer
CHROUT    = $FFD2 ;Print character on screen
PLOT      = $FFF0 ;Set screen cursor location

;KERNAL config
HIBASE    = $0288 ;Page where character screen is
TXTTAB    = $2B   ;Start of basic text
VARTAB    = $2D   ;Start of basic variables (after end of text)
FREKZP    = $FB   ;Free user zeropage addresses ($FB-$FE)

;REGISTERS
CIA2_A    = $DD00 ;CIA#2 data port A, also controls VICII memory bank select
CIA2_DD_A = $DD02 ;CIA#2 data port A control register

;Telesys IEEE entry points
SWITCH_IEEE = $DFBE       ; Activate IEEE mode for KERNAL routines
SWITCH_IEC = $FD15        ; Back to standard (IEC) mode

;Parameters
fromdevice = #10 ; My uIEC is default on device #10
todevice  = #8   ; The 8040 is default on device #8
filenr    = #15  ; file channel


;Clear new screen on BANK 2
          LDA #$84
          STA HIBASE    ;Set kernal character output page
          STA FREKZP + 1
          LDY #0
          STY FREKZP
          LDX #4
          LDA #$20      ; SPACE character
mylabel   STA (FREKZP),y
          INY
          BNE mylabel
          INC frekzp + 1
          DEX
          BNE mylabel

;Redirect screen output
          LDA CIA2_DD_A  ;Set register to output
          ORA #3
          STA CIA2_DD_A
          LDA CIA2_A     ;Load VICII bank register
          AND #%11111100 ;Clear BANK
          ORA #1         ;Set BANK 2
          STA CIA2_A     ;Store setting

;Set cursor on 0,0
          CLC     ; Carry bit 0 = SET CURSOR POS, 1 = READ CURSOR POS
          LDX #0
          LDY #0
          JSR PLOT         

;Print message
          LDA #<msgenter
          STA FREKZP
          LDA #>msgenter
          STA FREKZP + 1
          JSR prn

;Read file name
;We printed a text on row 0
;Now let user type the name on row 1
readkey   JSR GETIN
          BEQ readkey
          CMP #13        ;Was enter pressed?
          BEQ go_on
          JSR CHROUT     ;Print key
          JMP readkey
go_on     LDA HIBASE     ;Scan row 1 backwards to first non SPACE
          STA FREKZP + 1
          LDA #0
          STA FREKZP
          LDY #$50     ;Start at end of line 2
lp2       LDA (FREKZP),y
          CMP #$20     ;Is there a space?
          BNE countrdy
          DEY
          JMP lp2
countrdy  TYA          ;Y now holds the filename length + 40 (row 0)
          SEC
          SBC #$27     ;-40 + 1 (39=$27) to take the character itself too
          STA filesize
          JSR translt  ;translate screen codes to PETSCII

;Loading file ----------------------------------
;Set up logical file
          LDX fromdevice
          LDA filenr
          LDY #$FF       ; use no secondary address
          JSR SETLFS

          JSR setfn      ; Set file name

;Load file
          LDA #0         ;0 = load, 1 = verify
          LDX #1         ;force load to $0401
          LDY #4         ;force load to $0401
          JSR LOAD
          BCC goodload   ;Carry flag is used to signal an error
          JMP error      ;Handle error
goodload  STX VARTAB     ;Save highest load address
          STY VARTAB + 1

;Switch to IEEE
          JSR SWITCH_IEEE

;Save file
;Set up logical file
          LDX todevice
          LDA filenr
          LDY #$FF
          JSR SETLFS

          JSR setfn

;Save file
          LDA #1         ;Put $0401 in TXTTAB=start basic text used by SAVE
          STA TXTTAB
          LDA #4
          STA TXTTAB + 1
          LDX VARTAB     ;In VARTAB we stored the highest address that was LOADed
          LDY VARTAB + 1
          LDA #<TXTTAB
          JSR SAVE
          BCC goodsave   ;Carry flag is used to signal an error
          JMP error      ;Handle error

;Switch back to IEC
goodsave  JSR SWITCH_IEC

;Restore screen output
rest      LDA CIA2_DD_A  ;Set register to output
          ORA #3
          STA CIA2_DD_A
          LDA CIA2_A     ;Load VICII bank register
          AND #%11111100 ;Clear BANK
          ORA #3         ;Set BANK 0
          STA CIA2_A     ;Store setting
          LDA #4         ;Reset output to $0400
          STA HIBASE
          RTS            ; END OF PROGRAM!


; --- Sub routines ---

; --- Print
; Zero page FREKZP and FREKZP + 1 should hold the start address of the text
; The text should end with value 0
; All text in PETSCII!
prn       LDY #0
loopp     LDA (FREKZP),Y
          BEQ returnp    ;Quit when 0
          JSR CHROUT     ;KERNAL print character routine (Y is left unchanged)
          INY
          BNE loopp      ;Also quit when Y reaches 0 again!
returnp   RTS

; -- Screen code to PETSCII
; Screen codes 0-31/$0-$1F are 64-95/$40-$5F in PETSCII
; Screen codes 32-63/$20-#3F are the same in PETSCII
; Other characters are also left untouched
translt   LDY filesize
          LDX #$28
          STX FREKZP
          LDX HIBASE
          STX FREKZP + 1
nxt       LDA (FREKZP),y
          TAX
          AND #%11100000 ;Remove first 5 bits
          BNE notrnslt   ;Character > 31, so no translation required
          TXA
          CLC
          ADC #$40
          STA (FREKZP),y
notrnslt  DEY
          BPL nxt        ;Y=0 must also run, so check on miNus bit
          RTS

; --- Set file name
setfn     LDA filesize
          LDX #$28       ; name is on screen row 1 $28 = 40
          LDY HIBASE     ; screen page
          JSR SETNAM
          RTS

; --- Error
error     CMP #0
          BNE err4
          LDX #<msg_e0
          STX FREKZP
          LDX #>msg_e0
          STX FREKZP + 1
          JMP prn
err4      CMP #4
          BNE err5
          LDX #<msg_e4
          STX FREKZP
          LDX #>msg_e4
          STX FREKZP + 1
          JMP prn
err5      CMP #5
          BNE err8
          LDX #<msg_e5
          STX FREKZP
          LDX #>msg_e5
          STX FREKZP + 1
          JMP prn
err8      CMP #8
          BNE err9
          LDX #<msg_e8
          STX FREKZP
          LDX #>msg_e8
          STX FREKZP + 1
          JMP prn
err9      CMP #9
          BNE erre
          LDX #<msg_e9
          STX FREKZP
          LDX #>msg_e9
          STX FREKZP + 1
          JMP prn
erre      RTS ;unknown error

; --- Data ---
filesize  byte 0
msgEnter  text 'ENTER FILENAME:'
          byte 13
          byte 0
msg_e0    text 'USER STOP'
          byte 0
msg_e4    text 'FILE NOT FOUND'
          byte 0
msg_e5    text 'DEVICE NOT PRESENT'
          byte 0
msg_e8    text 'FILE NAME IS MISSING'
          byte 0
msg_e9    text 'ILLEGAL DEVICE NUMBER'
          byte 0
