MODE 7
REM
REM BBC end of !BBCTape application
REM
REM (C) S. Burke, 26/2/91
REM
REM The next few lines define where the buffers are, where the
REM code goes and where the file loads to.
REM
REM This version might work with discs, but I can't test it!
REM It fits in pages B and C with 0 bytes spare!
REM
:
name       = &0B00
name_high  = &0B
name_low   = &00
block      = &0B10
block_high = &0B
block_low  = &10
code_start = &0B30
load_page  = PAGE DIV &100
:
osfind = &FFCE
osbget = &FFD7
osfile = &FFDD  :REM Page 335 of the Advanced User Guide is wrong!
osbyte = &FFF4
:
FOR opt%=0 TO 3 STEP 3
P% = code_start
[OPT opt%
.go
          LDX #0
          LDA #2
          JSR osbyte        \ disable RS423
          LDX #0
          LDA #15
          JSR osbyte        \ flush all buffers
          LDX #2
          TXA
          JSR osbyte        \ enable RS423 receive
.mainloop
          LDA #&0D
          STA name          \ null name
          JSR handshake
:
          JSR get           \ get command
          CPY #&C0
          BEQ end           \ quit
:
          CPY #&30
          BNE load
          JSR put_ok        \ confirm command
          JSR get_name      \ get filename
          JSR handshake
          JSR get
.load
          CPY #&0C
          BNE load_byte
          JSR put_ok        \ confirm command
          JSR load_file
          JSR send_file
          JMP mainloop
.load_byte
          CPY #&03
          BNE command_error
          JSR put_ok        \ confirm command
          JSR load_file
          JSR send_file
          JMP mainloop
.command_error
          LDA #0
          JSR put           \ command error
          JMP mainloop
.end
          RTS
.load_file
          LDA #name_low     \ set up parameter block
          STA block
          LDA #name_high
          STA block+1
          LDA #0
          STA block+2
          STA block+6
          LDA #load_page
          STA block+3
          LDA #&FF
          STA block+4
          STA block+5
          LDX #block_low
          LDY #block_high
          JSR osfile        \ load file
          LDA block+10
          STA &71
          LDA block+11
          STA &72           \ put file length in &71, &72
          JSR read_load_exec\ get load/exec address and name
.read_name
          LDX #&FF
.nameloop
          INX
          CPX #&C
          BEQ too_far
\         LDA &3B2,X        ! pull filename out of cassette workspace
          LDA #0            \ don't know where to get it for a disc system
          STA name,X        \ see AUG p. 279
          BNE nameloop
.too_far
          LDA #&0D
          STA name,X
          RTS
.get_name
          LDX #&FF
          STX &81           \ "get" corrupts registers
.get_char
          CPX #&B
          BEQ too_far
          JSR get           \ get filename from Arc
          TYA
          INC &81   
          LDX &81
          STA name,X
          CMP #&0D
          BNE get_char
          RTS
.read_load_exec
          LDX #8
.load_exec_loop
          LDA &3BD,X        \ load/exec address from cassette workspace
          STA &81,X
          DEX
          BNE load_exec_loop
          RTS
.handshake
          LDA #ASC("S")
          JSR put
          LDA #ASC("B")
          JSR put           \ send "SB" ...
          JSR get
          CPY #ASC("s")
          BNE handshake
          JSR get
          CPY #ASC("b")
          BNE handshake     \ ... and receive "sb" to handshake
          RTS
.send_file
          LDA &71
          JSR put
          LDA &72
          JSR put           \ send file length
:
          LDA #load_page
          STA &74
          LDA #0 
          STA &73           \ reset load address
          DEC &72           \ need this for test below
          BMI last_block    \ file length < 256 bytes?
          STA &80           \ block length = 0 ( = 256)
.send_block
          JSR put_ok        \ not eof
          LDA #3            \ send length 3 times
          STA &76           \ use CRC low byte as counter
.lenout
          LDA &80
          JSR put           \ output block length
          DEC &76
          BNE lenout        \ CRC low byte zero at exit
          LDY #0
          STY &75           \ initialise CRC high byte
.send_byte
          STY &70           \ save offset
          LDA (&73),Y       \ load next byte ...
          PHA
          JSR put
          PLA               \ get character back
          JSR crc           \ update crc
          LDY &70
          INY               \ increment offset
          CPY &80
          BNE send_byte     \ end of block?
:
          LDA &75
          JSR put           \ output CRC high byte
          LDA &76
          JSR put           \ output CRC low byte
:
          JSR get           \ look for confirmation
          TYA
          BEQ send_block    \ zero means error, so do again
:
          INC &74           \ increment address high byte
          DEC &72           \ decrement length high byte
          BPL send_block    \ are we finished?
.last_block
          LDY #0
          LDA &71           \ length of last block
          STY &71           \ set length to zero
          STA &80
          BNE send_block    \ output if non-zero
          LDA #0
          JSR put           \ zero marks eof
          JSR put_load_exec \ send the load/exec adress
.put_name                   \ fall through to put_name ...
          LDX #&FF
          STX &81           \ "put" corrupts registers
.put_char                   \ output file name
          INC &81
          LDX &81
          LDA name,X
          PHA
          JSR put
          PLA
          CMP #&0D
          BNE put_char
          RTS
.put_load_exec              \ put out load/exec address
          LDX #0
          STX &81           \ "put" corrupts registers
.put_load_exec_loop
          LDA &82,X
          JSR put
          INC &81
          LDX &81
          CPX #8
          BNE put_load_exec_loop
          RTS
.put_ok
          LDA #&FF
.put
          PHA               \ save value to output
          JSR escape
          LDX #&FD
          LDA #&80
          JSR osbyte        \ get # empty bytes in RS423 output buffer
          CPX #9
          PLA
          BCC put           \ if < 9 bytes remain, wait ...
:
          LDX #2
          TAY
          LDA #&8A
          JMP osbyte        \ ... and send it
.get
          JSR escape
          LDX #1
          LDA #&91
          JSR osbyte        \ read a byte
          BCS get
          RTS
.crc
          EOR &75           \ calculate CRC in &75, &76
          STA &75           \ algorithm from Advanced User Guide
          LDX #8            \ I hope it's right!
.crc_loop
          LDA &75
          ROL A
          BCC b7z
          LDA &75
          EOR #8
          STA &75
          LDA &76
          EOR #&10
          STA &76
.b7z
          ROL &76
          ROL &75
          DEX
          BNE crc_loop
          RTS
.escape
          LDA &FF
          BMI error
          RTS
.error
          LDA #&7E
          JSR osbyte        \ acknowledge escape
          LDX #0
          LDY #0
          LDA #0
          JSR &FFCE         \ close all files
          BRK
]
?P% = &11
P%  = P% + 1
$P% = "Escape" + CHR$0
NEXT opt%
*OPT 1,2
RUN
CALL go
