*************************************************************************
*                                                                       *
*       OSFIND  ENTRY                                                   *
*       file handling                                                   *
*                                                                       *
*************************************************************************
;on entry A determines Action Y may contain file handle or
;X/Y point to filename terminated by &0D in memory
;A=0	closes file in channel Y if Y=0 closes all files
;A=&40  open a file for input  (reading) X/Y points to filename
;A=&80  open a file for output (writing) X/Y points to filename
;A=&C0  open a file for input and output (random access)
;ON EXIT Y=0 if no file found else Y=channel number in use for file

    	            ;save A X and Y
F3CA	STA &BC     ;file status or temporary store
F3CC	TXA         ;A=X
F3CD	PHA         ;save X on stack
F3CE	TYA         ;A=Y
F3CF	PHA         ;save Y on stack
F3D0	LDA &BC     ;file status or temporary store
F3D2	BNE &F3F2   ;if A is non zero open a file via F3F2


************ close a file ***********************************************

F3D4	TYA         ;A=Y
F3D5	BNE &F3E3   ;if A<> 0 close specified file else close them all
F3D7	JSR &E275   ;close spool/exec files via OSBYTE 77
F3DA	JSR &F478   ;tidy up
F3DD	LSR &E2     ;CFS status byte is shifted left and right to zero
F3DF	ASL &E2     ;bit 0
F3E1	BCC &F3EF   ;and if carry clear no input file was open so F3EF

F3E3	LSR         ;A contains file handle so shift bit 0 into carry
F3E4	BCS &F3DD   ;if carry set close input file
F3E6	LSR         ;else shift bit 1 into carry
F3E7	BCS &F3EC   ;if carry set close output file
F3E9	JMP &FBB1   ;else report 'Channel Error' as CFS can only support
    	            ;1 input and 1 output file

F3EC	JSR &F478   ;tidy up
F3EF	JMP &F471   ;and exit


************ OPEN A FILE ************************************************

F3F2	JSR &F25A   ;get filename from BUFFER
F3F5	BIT &BC     ;file status or temporary store
F3F7	BVC &F436   ;check A at input if bit 6 not set its an output file

********* Input files +**************************************************

F3F9	LDA #&00    ;else its an input file
F3FB	STA &039E   ;BGET buffer offset for next byte
F3FE	STA &03DD   ;Expected BGET file block number lo
F401	STA &03DE   ;expected BGET file block number hi
F404	LDA #&3E    ;A=&3E
F406	JSR &F33D   ;CFS status =CFS status AND A
F409	JSR &FB1A   ;claim serial system and set OPTions
F40C	PHP         ;save flags on stack
F40D	JSR &F631   ;search for file
F410	JSR &F6B4   ;check protection bit of block status and respond
F413	PLP         ;get back flags
F414	LDX #&FF    ;X=&FF increment to 0 on next instruction

F416	INX         ;X=X+1
F417	LDA &03B2,X ;get file name and
F41A	STA &03A7,X ;store as BGET filename
F41D	BNE &F416   ;until end of filename

F41F	LDA #&01    ;A=1 to show file open
F421	JSR &F344   ;set status bits from A
F424	LDA &02EA   ;CFS currently resident file block length lo
F427	ORA &02EB   ;CFS currently resident file block length hi
F42A	BNE &F42F   ;if block length is 0
F42C	JSR &F342   ;set CFS status bit 3 (EOF reached)
    	            ;else
F42F	LDA #&01    ;A=1
F431	ORA &0247   ;filing system flag 0=CFS 2=RFS
F434	BNE &F46F   ;and exit after restoring registers


******************* open an output file***********************************

F436	TXA         ;A=X

F437	BNE &F43C   ;if X=0 then zero length filename so
F439	JMP &EA8F   ;Bad String error

F43C	LDX #&FF    ;X=&FF
F43E	INX         ;X=X+1
    	            ;copy sought filename to header block
F43F	LDA &03D2,X ;sought filename
F442	STA &0380,X ;BPUT file header block
F445	BNE &F43E   ;until A=0 end of filename
F447	LDA #&FF    ;A=&FF
F449	LDX #&08    ;X=8

F44B	STA &038B,X ;set 38C/93 to &FF
F44E	DEX         ;X=X-1
F44F	BNE &F44B   ;

F451	TXA         ;A=X=0
F452	LDX #&14    ;X=14
F454	STA &0380,X ;BPUT file header block
F457	INX         ;X=X+1
F458	CPX #&1E    ;this zeros 394/D
F45A	BNE &F454   ;

F45C	ROL &0397   ;
F45F	JSR &FB27   ;Set cassette optionsinto (BB),set C7=6
    	            ;claim serial system for cassette
F462	JSR &F934   ;prompt to start recording
F465	JSR &FAF2   ;enable second processor and reset serial system
F468	LDA #&02    ;A=2
F46A	JSR &F344   ;set status bits from A
F46D	LDA #&02    ;A=2
F46F	STA &BC     ;file status or temporary store
F471	PLA         ;get back A
F472	TAY         ;Y=A
F473	PLA         ;get back A
F474	TAX         ;X=A
F475	LDA &BC     ;file status or temporary store
F477	RTS         ;return
    	;

F478	LDA #&02    ;A=2 clearing all but bit 1 of status byte
F47A	AND &E2     ;CFS status byte, with output file open
F47C	BEQ &F477   ;if file not open then exit
F47E	LDA #&00    ;else A=0
F480	STA &0397   ;setting block length to current value of BPUT offset
F483	LDA #&80    ;A=&80
F485	LDX &039D   ;get BPUT buffer ofset
F488	STX &0396   ;setting block length to current value of BPUT offset
F48B	STA &0398   ;mark current block as last
F48E	JSR &F496   ;save block to tape
F491	LDA #&FD    ;A=&FD
F493	JMP &F33D   ;CFS status =CFS status AND A


*********** SAVE BLOCK TO TAPE ********************************************

F496	JSR &FB1A   ;claim serial system and set OPTions

F499	LDX #&11    ;X=11
F49B	LDA &038C,X ;copy header block from 38C-39D
F49E	STA &03BE,X ;to 3BE/DF
F4A1	DEX         ;X=X-1
F4A2	BPL &F49B   ;
    	            ;X=&FF
F4A4	STX &B2     ;current load address high word
F4A6	STX &B3     ;current load address high word
F4A8	INX         ;X=X+1, (X=0)
F4A9	STX &B0     ;current load address lo byte set to &00
F4AB	LDA #&09    ;A=9 to set current load address at &900
F4AD	STA &B1     ;current load address
F4AF	LDX #&7F    ;X=&7F
F4B1	JSR &FB81   ;copy from 301/C+X to 3D2/C sought filename
F4B4	STA &03DF   ;copy of last read block flag
F4B7	JSR &FB8E   ;switch Motor On
F4BA	JSR &FBE2   ;set up CFS for write operation
F4BD	JSR &F7EC   ;write block to Tape
F4C0	INC &0394   ;block number lo
F4C3	BNE &F4C8   ;
F4C5	INC &0395   ;block number hi
F4C8	RTS         ;return


*************************************************************************
*                                                                       *
*                                                                       *
*       OSBGET  get a byte from a file                                  *
*                                                                       *
*                                                                       *
*************************************************************************
    	;on ENTRY       Y contains channel number
    	;on EXIT        X and Y are preserved C=0 indicates valid character
    	;           A contains character (or error) A=&FE End Of File

    	            ;push X and Y
F4C9	TXA         ;A=X
F4CA	PHA         ;save A on stack
F4CB	TYA         ;A=Y
F4CC	PHA         ;save A on stack
F4CD	LDA #&01    ;A=1
F4CF	JSR &FB9C   ;check conditions for OSBGET are OK
F4D2	LDA &E2     ;CFS status byte
F4D4	ASL         ;shift bit 7 into carry (EOF warning given)
F4D5	BCS &F523   ;if carry set F523
F4D7	ASL         ;shift bit 6 into carry
F4D8	BCC &F4E3   ;if clear EOF not reached F4E3
F4DA	LDA #&80    ;else A=&80 setting bit 7 of status byte EOF warning
F4DC	JSR &F344   ;set status bits from A
F4DF	LDA #&FE    ;A=&FE
F4E1	BCS &F51B   ;if carry set F51B

F4E3	LDX &039E   ;BGET buffer offset for next byte
F4E6	INX         ;X=X+1
F4E7	CPX &02EA   ;CFS currently resident file block length lo
F4EA	BNE &F516   ;read a byte
    	            ;else
F4EC	BIT &02EC   ;block flag of currently resident block
F4EF	BMI &F513   ;if bit 7=1 this is the last block so F513 else
F4F1	LDA &02ED   ;last character of currently resident block
F4F4	PHA         ;save A on stack
F4F5	JSR &FB1A   ;claim serial system and set OPTions
F4F8	PHP         ;save flags on stack
F4F9	JSR &F6AC   ;read in a new block
F4FC	PLP         ;get back flags
F4FD	PLA         ;get back A
F4FE	STA &BC     ;file status or temporary store
F500	CLC         ;clear carry flag
F501	BIT &02EC   ;block flag of currently resident block
F504	BPL &F51D   ;if not last block (bit 7=0)
F506	LDA &02EA   ;CFS currently resident file block length lo
F509	ORA &02EB   ;CFS currently resident file block length hi
F50C	BNE &F51D   ;if block size not 0 F51D else
F50E	JSR &F342   ;set CFS status bit 6 (EOF reached)
F511	BNE &F51D   ;goto F51D

F513	JSR &F342   ;set CFS status bit 6 (EOF reached)
F516	DEX         ;X=X-1
F517	CLC         ;clear carry flag
F518	LDA &0A00,X ;read byte from cassette buffer

F51B	STA &BC     ;file status or temporary store
F51D	INC &039E   ;BGET buffer offset for next byte
F520	JMP &F471   ;exit via F471


F523	BRK         ;
F524	DB  &DF     ;error number
F525	DB  'EOF'   ;
F528	BRK         ;


*************************************************************************
*                                                                       *
*                                                                       *
*       OSBPUT  WRITE A BYTE TO FILE                                    *
*                                                                       *
*                                                                       *
*************************************************************************
;ON ENTRY  Y contains channel number A contains byte to be written

F529	STA &C4     ;store A in temorary store
F52B	TXA         ;and stack X and Y
F52C	PHA         ;save  on stack
F52D	TYA         ;A=Y
F52E	PHA         ;save on stack

F52F	LDA #&02    ;A=2
F531	JSR &FB9C   ;check conditions necessary for OSBPUT are OK
F534	LDX &039D   ;BPUT buffer offset for next byte
F537	LDA &C4     ;get back original value of A
F539	STA &0900,X ;Cassette buffer
F53C	INX         ;X=X+1
F53D	BNE &F545   ;if not 0 F545, otherwise buffer is full so
F53F	JSR &F496   ;save block to tape
F542	JSR &FAF2   ;enable second processor and reset serial system
F545	INC &039D   ;BPUT buffer offset for next byte
F548	LDA &C4     ;get back A
F54A	JMP &F46F   ;and exit



*************************************************************************
*                                                                       *
*                                                                       *
*       OSBYTE 139      Select file options                             *
*                                                                       *
*                                                                       *
*************************************************************************
;ON ENTRY  Y contains option value  X contains option No. see *OPT X,Y
;this applies largely to CFS LOAD SAVE CAT and RUN
;X=1	is message switch
;   	Y=0 no messages
;   	Y=1 short messages
;   	Y=2 gives detailed information on load and execution addresses

;X=2	is error handling
;   	Y=0 ignore errors
;   	Y=1 prompt for a retry
;   	Y=2 abort operation

;X=3	is interblock gap for BPUT# and PRINT#
;   	Y=0-127 set gap in 1/10ths Second
;   	Y > 127 use default values


F54D	TXA         ;A=X
F54E	BEQ &F57E   ;if A=0 F57E
F550	CPX #&03    ;if X=3
F552	BEQ &F573   ;F573 to set interblock gap
F554	CPY #&03    ;else if Y>2 then BAD COMMAND error
F556	BCS &F55E   ;
F558	DEX         ;X=X-1
F559	BEQ &F561   ;i.e. if X=1 F561 message control
F55B	DEX         ;X=X-1
F55C	BEQ &F568   ;i.e. if X=2 F568 error response
F55E	JMP &E310   ;else E310 to issue Bad Command error



*********** message control *********************************************

F561	LDA #&33    ;to set lower two bits of each nybble as mask
F563	INY         ;Y=Y+1
F564	INY         ;Y=Y+1
F565	INY         ;Y=Y+1
F566	BNE &F56A   ;goto F56A




*********** error response *********************************************

F568	LDA #&CC    ;setting top two bits of each nybble as mask
F56A	INY         ;Y=Y+1
F56B	AND &E3     ;clear lower two bits of each nybble
F56D	ORA &F581,Y ;or with table value
F570	STA &E3     ;store it in &E3
F572	RTS         ;return

    	;setting of &E3
    	;
    	;lower nybble sets LOAD options
    	;upper sets SAVE options
    	
    	;0000   Ignore errors,          no messages
    	;0001   Abort if error,         no messages
    	;0010   Retry after error,      no messages
    	;1000   Ignore error            short messages
    	;1001   Abort if error          short messages
    	;1010   Retry after error       short messages
    	;1100   Ignore error            long messages
    	;1101   Abort if error          long messages
    	;1110   Retry after error       long messages



***********set interblock gap *******************************************

F573	TYA         ;A=Y
F574	BMI &F578   ;if Y>127 use default values
F576	BNE &F57A   ;if Y<>0 skip next instruction
F578	LDA #&19    ;else A=&19

F57A	STA &03D1   ;sequential block gap
F57D	RTS         ;return
    	;
F57E	TAY         ;Y=A
F57F	BEQ &F56D   ;jump to F56D



*********** DEFAULT OPT VALUES TABLE ************************************

F581	DB  &A1     ;%1010 0001
F582	DB  &00     ;%0000 0000
F583	DB  &22     ;%0010 0010
F584	DB  &11     ;%0001 0001
F585	DB  &00     ;%0000 0000
F586	DB  &88     ;%1000 1000
F587	DB  &CC     ;%1100 1100

F588	DEC &C0     ;filing system buffer flag
F58A	LDA &0247   ;filing system flag 0=CFS 2=RFS
F58D	BEQ &F596   ;if CFS F596

F58F	JSR &EE51   ;read RFS data rom or Phrom
F592	TAY         ;Y=A
F593	CLC         ;clear carry flag
F594	BCC &F5B0   ;jump to F5B0

F596	LDA &FE08   ;ACIA status register
F599	PHA         ;save A on stack
F59A	AND #&02    ;clear all but bits 0,1 A=(0-3)
F59C	BEQ &F5A9   ;if 0 F5A9 transmit data register full or RDR empty
F59E	LDY &CA     ;
F5A0	BEQ &F5A9   ;
F5A2	PLA         ;get back A
F5A3	LDA &BD     ;character temporary storage
F5A5	STA &FE09   ;ACIA transmit data register
F5A8	RTS         ;return
    	;
F5A9	LDY &FE09   ;read ACIA recieve data register
F5AC	PLA         ;get back A
F5AD	LSR         ;bit 2 to carry (data carrier detect)
F5AE	LSR         ;
F5AF	LSR         ;

F5B0	LDX &C2     ;progress flag
F5B2	BEQ &F61D   ;if &C2=0 exit
F5B4	DEX         ;X=X-1
F5B5	BNE &F5BD   ;if &C2>1 then F5BD
F5B7	BCC &F61D   ;else if carrier tone from cassette detected exit

F5B9	LDY #&02    ;Y=2

F5BB	BNE &F61B   ;
F5BD	DEX         ;X=X-1
F5BE	BNE &F5D3   ;if &C2>2
F5C0	BCS &F61D   ;if carrier tone from cassette not detected  exit
F5C2	TYA         ;A=Y
F5C3	JSR &FB78   ;set (BE/C0) to 0
F5C6	LDY #&03    ;Y=3
F5C8	CMP #&2A    ;is A= to synchronising byte &2A?
F5CA	BEQ &F61B   ;if so F61B
F5CC	JSR &FB50   ;control cassette system
F5CF	LDY #&01    ;Y=1
F5D1	BNE &F61B   ;goto F61B
F5D3	DEX         ;X=X-1
F5D4	BNE &F5E2   ;if &C2>3
F5D6	BCS &F5DC   ;
F5D8	STY &BD     ;get character read into Y
F5DA	BEQ &F61D   ;if 0 exit via F61D
F5DC	LDA #&80    ;else A=&80
F5DE	STA &C0     ;filing system buffer flag
F5E0	BNE &F61D   ;and exit

F5E2	DEX         ;X=X-1
F5E3	BNE &F60E   ;if &C2>4 F60E
F5E5	BCS &F616   ;if carry set F616
F5E7	TYA         ;A=Y
F5E8	JSR &F7B0   ;perform CRC
F5EB	LDY &BC     ;file status or temporary store
F5ED	INC &BC     ;file status or temporary store
F5EF	BIT &BD     ;if bit 7 set this is the last byte read
F5F1	BMI &F600   ;so F600
F5F3	JSR &FBD3   ;check if second processor file test tube prescence
F5F6	BEQ &F5FD   ;if return with A=0 F5FD
F5F8	STX &FEE5   ;Tube FIFO3
F5FB	BNE &F600   ;

F5FD	TXA         ;A=X restore value
F5FE	STA (&B0),Y ;store to current load address
F600	INY         ;Y=Y+1
F601	CPY &03C8   ;block length
F604	BNE &F61D   ;exit
F606	LDA #&01    ;A=1
F608	STA &BC     ;file status or temporary store
F60A	LDY #&05    ;Y=5
F60C	BNE &F61B   ;exit

F60E	TYA         ;A=Y
F60F	JSR &F7B0   ;perform CRC
F612	DEC &BC     ;file status or temporary store
F614	BPL &F61D   ;exit

F616	JSR &FB46   ;reset ACIA
F619	LDY #&00    ;Y=0
F61B	STY &C2     ;progress flag
F61D	RTS         ;return


*************************************************************************
*                                                                       *
*       FSCV xx - check for end of file                                 *
*                                                                       *
*************************************************************************
    	;
F61E	PHA         ;save A on stack
F61F	TYA         ;A=Y
F620	PHA         ;save Y on stack
F621	TXA         ;A=X to put X into Y
F622	TAY         ;Y=A
F623	LDA #&03    ;A=3
F625	JSR &FB9C   ;confirm file is open
F628	LDA &E2     ;CFS status byte
F62A	AND #&40    ;
F62C	TAX         ;X=A
F62D	PLA         ;get back A
F62E	TAY         ;Y=A
F62F	PLA         ;get back A
F630	RTS         ;return
    	;
F631	LDA #&00    ;A=0
F633	STA &B4     ;current block no. lo
F635	STA &B5     ;current block no. hi
F637	LDA &B4     ;current block no. lo
F639	PHA         ;save A on stack
F63A	STA &B6     ;next block no. lo
F63C	LDA &B5     ;current block no. hi
F63E	PHA         ;save A on stack
F63F	STA &B7     ;next block no. hi
F641	JSR &FA46   ;print message following call

F644	DB  'Searching';
F64C	DB  &0D     ;newline
F64E	BRK         ;

F64F	LDA #&FF    ;A=&FF
F651	JSR &F348   ;read data from CFS/RFS
F654	PLA         ;get back A
F655	STA &B5     ;current block no. hi
F657	PLA         ;get back A
F658	STA &B4     ;current block no. lo
F65A	LDA &B6     ;next block no. lo
F65C	ORA &B7     ;next block no. hi
F65E	BNE &F66D   ;
F660	STA &B4     ;current block no. lo
F662	STA &B5     ;current block no. hi
F664	LDA &C1     ;checksum result
F666	BNE &F66D   ;
F668	LDX #&B1    ;current load address
F66A	JSR &FB81   ;copy from 301/C+X to 3D2/C sought filename
F66D	LDA &0247   ;filing system flag 0=CFS 2=RFS
F670	BEQ &F685   ;if cassette F685
F672	BVS &F685   ;

F674	BRK         ;
F675	DB  &D6             ;Error number
F676	DB  'File Not found'
F684	BRK         ;

F685	LDY #&FF    ;Y=&FF
F687	STY &03DF   ;copy of last read block flag
F68A	RTS         ;return
    	;