; IFILEOPS.MAC VERS: 01.25 DATE: 06/10/87 TIME: 21:01 ; COPYRIGHT 1987 William P.N. Smith - Commercial use prohibited! ; ;Input file operations for single byte chunks. ; ; The IOPEN routine will open the input file. When calling this routine ;the DE must contain a pointer to a 16 byte data area containing the file name ;and type in standard FCB format. This data will be copied into a private FCB ;inside this routine, the file will be opened, and the first record read out of ;the file. If the file will not open or there is no first record (file size of ;zero bytes), the program will be aborted and CP/M will be rebooted. Note that ;IOPEN _must_ be called before making calls to GETBYT. IOPEN will trash any ;of your registers that it feels like trashing. ; ; The GETBYT routine will return with the A register containing the next ;byte read from the file and the ZERO flag not_true. It will continue to read ;sectors and open new extents until the end of file is encountered. At that ;time it will return with an FF in the A register and the ZERO flag true. It ;should be noted that an FF in the A register and ZERO not_true means that the ;end of file has not yet been encountered, but that an FF byte has been read ;from the file. GETBYT will only disturb the AF register. ; ; The ICLOSE routine will close the input file and mark it closed. This ;is optional under CP/M, but if you want to do another file, you better close ;things properly. ICLOSE will stomp all over your silly little registers, ;there was nothing interesting in them anyway! TRUE EQU 0FFH FALSE EQU 00H ZERO EQU 00H BOOT EQU 0000H ;reboot CP/M CR EQU 0DH LF EQU 0AH NULL EQU 00H BDOS EQU 0005H ;jump to BDOS NONZERO EQU 0FFH DEBUG EQU FALSE ;be silent! ;------------------------------------------------------------------------------ ; IOPEN open the input file and set up housekeeping. IOPEN:: LD A,(IFIO) ;get the 'open' flag CP ZERO ;is it already open? JR Z,MOVFCB ;nope, OK to try FAO: LD DE,FAOERR ;tell the console CALL STROUT## LD DE,IFCB ;show him the file name CALL PFN## LD DE,FE2 ;tell him what's wrong CALL STROUT## JP BOOT ;and reboot CP/M FAOERR: DB CR,LF DB 'Programming error - file ' DB 00H,'$' FE2: DB ' already open in IOPEN module' DB CR,LF,NULL,'$' MOVFCB: EX DE,HL ;source from passed parameter LD DE,IFCB ;destination is input file control block LD BC,16 ;16 bytes to move LDIR ;move them WLDCHK: LD HL,IFCB ;start at input FCB LD BC,16 ;check each of those bytes LD A,'?' ;look for wild card CPIR JR NZ,NOWILD ;if not found, skip the error message ISWILD: LD DE,IWERR ;tell the console CALL STROUT## JP BOOT ;and reboot CP/M IWERR: DB CR,LF DB 'Error - no wild cards allowed! Abort in IOPEN module.' DB CR,LF,NULL,'$' NOWILD: LD DE,IFCB ;point at the FCB LD C,0FH ;open_file function CALL BDOS CP 0FFH ;FF if file not found JP NZ,ISOPEN UNFOUND:LD DE,FNF ;tell him there's something wrong CALL STROUT## LD DE,IFCB ;show him the file name CALL PFN## LD DE,FNFEND ;tell him what the problem is CALL STROUT## JP BOOT ;and restart CP/M FNF: DB CR,LF DB 'Input file - ' DB 00H,'$' FNFEND: DB ' - not found! ' DB 'Abort in IOPEN module.' DB CR,LF,NULL,'$' ;if we get this far, there is a file by that name, and it's open ISOPEN: LD A,ZERO ;clear out some stuff LD (IFCB+32),A ;the current record they tell us to clear LD (IFCB+12),A ;the current extent is a secret LD DE,IBUFR ;set the default DMA area to input buffer LD C,1AH CALL BDOS LD DE,IFCB ;get a sector from the file into the buffer LD C,14H ;read_sequential command CALL BDOS CP 00H ;read sucessful if 00 JR Z,READOK BADRD: LD DE,MTFILE ;tell operator file is empty CALL STROUT## JP BOOT ;and reboot CP/M MTFILE: DB CR,LF DB 'Error, input file is empty! Abort in IOPEN module.' DB CR,LF,NULL,'$' ;if we got here, the first read was sucessful READOK: LD A,NONZERO ;set the flag for 'input file is open' LD (IFIO),A LD A,00H ;set up the byte pointer LD (IPOINT),A RET ;and run along ;------------------------------------------------------------------------------ ; GETBYT get next byte from input file. GETBYT::PUSH BC ;save everything PUSH DE PUSH HL ;sanity check to make sure file was opened LD A,(IFIO) ;is input file open? CP ZERO JR NZ,WASOPN ;yup, go right ahead! NOTOP: LD DE,FNO ;tell the operator CALL STROUT## JP BOOT ;and reboot CP/M FNO: DB CR,LF DB 'Programming error - ' DB 'File was not opened in GETBYT module!' DB CR,LF,NULL,'$' WASOPN: LD A,(IPOINT) ;get the input pointer (offset) CP 128 ;past the end of the buffer? JR Z,RDMORE ;yup, we must read another sector ;once we have the byte _somewhere_ in the buffer... HAVBYT: LD HL,IBUFR ;point at the base of the buffer ADD A,L ;add pointer and offset LD L,A ;that's low byte JR NC,GB2 ;if no carry, skip the increment INC H ;if carry, 'add' it to the upper byte GB2: LD A,(IPOINT) ;get the pointer again INC A ;bump it LD (IPOINT),A ;put it back [NOTE: Z flag always not_true!] LD A,(HL) ;pick up the byte GBEX: POP HL ;recover everything POP DE POP BC RET ;and run along home with your byte ; here we find that we have to read another sector from the file RDMORE: LD A,ZERO ;reset the pointer LD (IPOINT),A IF DEBUG LD E,'I' ;tell the console you read another input record LD C,02H CALL BDOS ENDIF LD DE,IBUFR ;set the default DMA area to input buffer LD C,1AH CALL BDOS LD DE,IFCB ;get a sector from the file into the buffer LD C,14H ;read_sequential command CALL BDOS CP 00H ;read sucessful if 00 JR Z,HAVBYT ;also A reg holds offset[!] NOMORE: LD A,0FFH ;set up the error condition CP 0FFH ;set the Z flag true JR GBEX ;and exit ;------------------------------------------------------------------------------ ; ICLOSE close out input file and mark it closed ICLOSE::LD A,(IFIO) ;is input file open? CP ZERO JR NZ,WSOPN ;yup, go right ahead! LD DE,IFNO ;tell the operator CALL STROUT## JP BOOT ;and reboot CP/M IFNO: DB CR,LF DB 'Programming error - ' DB 'File was not opened in ICLOSE module!' DB CR,LF,NULL,'$' WSOPN: LD DE,IFCB ;point at the input FCB LD C,10H ;close_file command CALL BDOS CP 0FFH ;FF means error JR NZ,ICEX ICERR: LD DE,CLSERR ;tell the console CALL STROUT## JP BOOT ;and run away to hide CLSERR: DB CR,LF DB 'Strange Error - file will not close in ICLOSE module' DB CR,LF,NULL,'$' ICEX: LD A,ZERO ;mark it closed LD (IFIO),A RET ;and run along ;------------------------------------------------------------------------------ ;some data areas. ; input file control block IFCB: DS 36 ;max size IFIO: DB 00H ;input file is open flag (open if FF) IBUFR: DS 128 ;128 byte sector buffer IPOINT: DB 00H ;pointer (offset) to next byte out .REQUEST strout,pfn END