	processor 6502

	include "jmptab.inc"

#if target & pet4001
	include "include/petram34.lib"
	include "include/petrom4.lib"
#endif
#if target & pet3001
	include "include/petram34.lib"
	include "include/petrom3.lib"
#endif
#if target & (c64 | c128 | vic20)
	include "include/cbmrom.lib"
#endif

	seg code
	org prutils

entry:
	lda #0		; send ack
	jsr send_switch

loop:
	; read a file protocol:
	; C=		     PC or Amiga
	; ack (00) ->
	;		     <- <length>filename
	;		     <- device #
	;		     <- secondary address
	; st: ok (00) or error (!= 00) ->
	; <length><chksum>datablock (255 bytes max) ->
	;		     <- ok (80) or again (81) or stop (82)
	; send same or next block, accordingly
	; last block has length 0 and no checksum or data.

	jsr receive_switch	; get length of file name
	sta fnlen
	tax		; test length
	bpl noexit
	jmp exit	; reinstall server and exit.
noexit:
	beq nofnam
	ldx #0		; receive file name
fnam:
	jsr receive	; preserves x but sets y to 0.
	sta filebuf,x
	inx
	cpx fnlen
	bcc fnam

nofnam:
	lda #<filebuf
	sta fnadr
	lda #>filebuf
	sta fnadr+1
	lda #0
	sta status	; clear ST

myfileno = 45
	lda #myfileno	; a hopefully unused file number
	sta la
	jsr close	; close file first just in case

	jsr receive	; receive device number
	sta fa
	jsr receive	; secondary addr, usually 0 for file read
	sta sa
	jsr open	; now open the file
	lda status	; and test for ourselves if we must continue
	bne abortst2

	; This bit here is special for disk commands.
	; If we sent a command to device >= 8, sa 15,
	; then don't read any data back.
	; The way to read the error channel is an empty file name.

	lda fa
	cmp #8
	bcc readfile
	lda sa
	and #$0f
	cmp #15
	bne readfile
	lda fnlen
	beq readfile

dont_read_file:
	lda #0		; send 00 ok, going ahead code
	jsr send_switch
	tya
	jsr send	; send 0 length (end) code
	jmp loop

readfile:
	ldx #myfileno	; go and select the file for reading
	jsr chkin
	lda status
	bne abortst
	jsr send_switch ; send 00 ok, going ahead code

		; loop to send blocks from the file
nextblock:
	ldx #0
loop2:	bne loop	; branch entry point (never branch in actual program)
abortst2:
	bne abortst	; another trampoline
	stx filebuf	; clear checksum
	inx
rd:			; read max 255 bytes from the file
	lda status	; test ST for EOI on previous byte
	bne eof
	jsr stop	; test stop key
	beq abortst
	jsr chrin
	sta filebuf,x
	clc		; add into checksum
	adc filebuf
	sta filebuf
	inx		; x ranges from 01 to max FF
	bne rd

eof:
	lda status	; test if we did indeed stop because of EOF
	and #<~$40
	beq .noerr
	dex		; subtract last garbage byte
.noerr
	dex		; exclude checksum from count
	stx blklen
			; now go send the buffer
sameblock:
	lda blklen
	jsr send_switch ; send length
	lda blklen
	beq return3	; 0 length is special: we're finished.
	lda filebuf	; checksum
	jsr send
	ldx #0
snd:
	lda filebuf+1,x
	jsr send
	inx
	cpx blklen
	bne snd
			; wait for go on, repeat, or abort.
	jsr receive_switch
	cmp #$80
	beq nextblock
	cmp #$81
	beq sameblock
	bne return3	; $82 (or other values) abort

abortst:
	jsr send_switch ; send non-zero ST value
return3:
	jsr clrchn
	lda #myfileno
	jsr close

	lda #1
	bne loop2	; branch always

	nop

endcode = .

	seg.u bss
	org endcode

blklen:
	ds.b 1		; save block length
filebuf:
	ds.b 256	; checksum followed by 255 bytes of file data

endbss = .
