************************************************************************* * * * 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 clear 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 +************************************************** \ OSFIND %x1xxxxxx - &40 and &C0 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*********************************** \ OSFIND %x0xxxxxx - &80 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 ;set load/exec to &FFFFFFFF 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 options into &BB, set &C7=6 ;claim serial system for cassette F462 JSR &F934 ;prompt to start recording, generate error if ROMFS F465 JSR &FAF2 ;claim Tube 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 ;set block length to current value of BPUT offset F483 LDA #&80 ;A=&80 F485 LDX &039D ;get BPUT buffer offset F488 STX &0396 ;set 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 ;set start address to &FFFFxxxx F4A6 STX &B3 ;to point to cassette buffers in I/O memory F4A8 INX ;X=X+1, (X=0) F4A9 STX &B0 ;current load address low byte set to &00 F4AB LDA #&09 ;A=9 to set current load address at &900 F4AD STA &B1 ;start address set to &FFFF0900 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=1-127 set gap in 1/10ths Second ; Y=0 or Y>127 use default values F54D TXA ; A=X F54E BEQ &F57E ; *OPT 0 - set default options 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 ; keep lower two bits of each nybble F563 INY ; Y=Y+1 F564 INY ; Y=Y+1 F565 INY ; Y=Y+1 F566 BNE &F56A ; go to F56A *********** error response ********************************************* F568 LDA #&CC ; keep top two bits of each nybble F56A INY ; Y=Y+1 F56B AND &E3 ; clear lower two bits of each nybble F56D ORA &F581,Y ; ORA with table value F570 STA &E3 ; store it in &E3 F572 RTS ; return ;setting of &E3 ; ;lower nybble sets BGET/BPUT options ;upper nybble sets LOAD/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 don't use default value F578 LDA #&19 ; Else A=&19 default value 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 - default ; ; +------- load/save=short messages, retry errors ; ; +-- bget/bput=no messages, abort errors F582 DB &00 ; %0000 0000 - *OPT 2,0 - ignore errors F583 DB &22 ; %0010 0010 - *OPT 2,1 - retry errors F584 DB &11 ; %0001 0001 - *OPT 2,2 - abort errors F585 DB &00 ; %0000 0000 - *OPT 1,0 - no messages F586 DB &88 ; %1000 1000 - *OPT 1,1 - short messages F587 DB &CC ; %1100 1100 - *OPT 1,2 - long messages 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=byte read F5C3 JSR &FB78 ;set (BE/C0) to 0 F5C6 LDY #&03 ;Y=3, sync byte found 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, waiting for carrier tone 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 ;get offset into current block F5ED INC &BC ;increment offset into current block 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 with NE F606 LDA #&01 ;A=1, two bytes of CRC to fetch F608 STA &BC ;store for next call F60A LDY #&05 ;Y=5 F60C BNE &F61B ;exit, setting progress=&05, looking for CRC ; Progress=&05, fetching CRC F60E TYA ;A=Y F60F JSR &F7B0 ;perform CRC F612 DEC &BC ;decrement number of CRC bytes to fetch F614 BPL &F61D ;more to fetch, exit F616 JSR &FB46 ;reset ACIA F619 LDY #&00 ;Y=0, progress=idle F61B STY &C2 ;set progress flag F61D RTS ;return ************************************************************************* * * * FSCV &01 - 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 ; Search for file 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 current block lo on stack F63A STA &B6 ;set expected block to current block F63C LDA &B5 ;current block no. hi F63E PHA ;save current block hi F63F STA &B7 ;set expected block to current block F641 JSR &FA46 ;print inline message F644 DB 'Searching'; F64C DB &0D ;newline F64E BRK ; F64F LDA #&FF ; A=&FF for loading (A=0 for CAT) F651 JSR &F348 ; Search for header F654 PLA ; F655 STA &B5 ; Restore current block hi F657 PLA ; F658 STA &B4 ; Restore current block lo F65A LDA &B6 ; Check expected block number F65C ORA &B7 ; F65E BNE &F66D ; If expected block<>0, jump to return F660 STA &B4 ; Set current block back to zero F662 STA &B5 ; F664 LDA &C1 ; Get checksum result F666 BNE &F66D ; Bad checksum, skip setting current filename F668 LDX #&B1 ; X+1=>filename in block header F66A JSR &FB81 ; Copy filename from block header to current filename F66D LDA &0247 ; Filing system flag 0=CFS 2=RFS F670 BEQ &F685 ; If cassette, exit with Y=&FF at F685 F672 BVS &F685 ; If ROMFS and not end-of-ROM, exit F674 BRK ; ROMFS and no more ROM, give error 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