; CHEK v1.5 CYCLIC REDUNDANCY CHECK 04/11/83 ; ; CHEK can read any CP/M file then print a CRC (CYCLIC-REDUNDANCY-CHECK) ; number based on the CCITT standard polynominal for asynchronous use: ; ; X^16 + X^12 + X^5 + 1 ; ; Useful for checking accuracy of file transfers. Far more accurate ; than a simple checksum. It will optionally write an output file to ; the default drive, listing the CRC's of all files requested. ; ; = = = = = = = = = = = = = = = = = = = = = = = = ; ; COMMANDS: CHEK [drive:] [F] ; ; Examples: ; CHEK B:HELLO.ASM check only HELLO.ASM ; CHEK *.ASM check all .ASM files ; CHEK *.* check all files, check disk quality ; CHEK *.* F makes disk file named CHEKLIST.CRC ; CHEK *.* FF makes disk file named FF.CRC ; CHEK *.* FILE makes disk file named FILE.CRC ; CHEK *.* HELLO.ABC makes disk file named HELLO.ABC ; ; NOTE: If 0103H is 0, no disk file is made regardless of request. ; ; NOTE TO SYSOPS: Set FILEOK: and SYSOK: (0103 and 0104) both to '0' ; to prevent remote users from creating a file or to ; find restricted '.SYS' files. ; ; (If 0103H is 0, no disk file is made, regardless of ; request.) ; ; * * * * * * * * * * * * ; ; 04/11/83 Message added if disk attempt is made with disk system dis- ; v1.5 abled. (Most RCPM systems will put 0103H and 0104H to 0 to ; prevent disk copy). This lets the user know immediately if ; he cannot make a disk copy. - Irv Hoff ; ; 04/09/83 Minor changes. Assembled .COM file is now 17 records long ; v1.4 instead of 23. Buffer size now divisible by 1024 vice 128. ; - Irv Hoff ; ; 04/07/83 Introduced a version of the table-driven CRC look-up table ; developed by Dave Barker. Speed is similar to earlier ap- ; v1.3 proach of Keith Petersen but with full security of an 8-bit ; algorithm. The resultant 2-byte CRC value is identical to ; that produced by CHEK11 and CHEK12. CRC copyright notice ; removed as a different approach has been implemented for the ; public domain algorithm. -Frank Gaude' ; ; 03/30/83 Restored the character count. A series of tests were made ; using 14 files totalling 2596 records. With character count ; v1.2 it took 5:02, with 1.1 version took 5:01. The difference in ; time is too trivial to abandon an informative feature. Re- ; stored the heading line to any disk file, which was always ; my intent. Numerous trivial changes to improve the appear- ; ance of the source code. - Irv Hoff ; ; 03/26/83 Fixed bug in register usage. Upon completion of the program ; FINCRC was making the ending calculation with the character ; v1.1 in the wrong register. Restored the copyright notice to the ; CRC area. Removed the character count as redundant and time- ; consuming. Removed the heading from the disk file to make ; the file easily machine-readable. ; - Gary Novosielski ; ; 02/02/83 Started this program. It is similar to the CRCK series but ; with a different algorithm (as shown above). This one has ; v1.0 been accepted as the standard by a number of programs, such ; as the COMM700, MDM700, MODEM200, MODEM700 and XMODEM series. ; Packet radio and other SDLC networking systems use the same ; algorithm. This now standardizes CHEK with these other pro- ; programs. ; Added total records in file for additional check. Also ; show the total character count for general information. Re- ; formatted the dipsplayed results. The heading and version ; number now appear in any disk file. Minor additional changes. ; Optional disk file named CHEKLIST.CRC by default with a ; "F", or whatever name you prefer if you type something dif- ; ferent, such as FILE.CHK. See examples. ; - Irv Hoff ; ; 06/27/79 CRCK v4.2 by Keith Petersen, W8SDZ ; ; * * * * * * * * * * * * ; ; ; DEFINE TRUE AND FALSE ; TRUE: EQU 0FFH FALSE: EQU 0 ; ; ; CONDITIONAL ASSEMBLY SWITCHES ; STDCPM: EQU TRUE ;TRUE FOR STANDARD CP/M ALTCPM: EQU FALSE ;TRUE FOR H8 OR TRS-80 ; ; ; SYSTEM EQUATES ; IF STDCPM BASE: EQU 0000H ;FOR STANDARD CP/M USERS ENDIF ; IF ALTCPM ;FOR H8 OR TRS-80 BASE: EQU 4200H ENDIF ; ; ; BDOS EUATES ; RDCON: EQU 1 WRCON: EQU 2 PRINT: EQU 9 CSTAT: EQU 11 OPEN: EQU 15 CLOSE: EQU 16 SRCHF: EQU 17 SRCHN: EQU 18 DELET: EQU 19 READ: EQU 20 WRITE: EQU 21 MAKE: EQU 22 RENAM: EQU 23 STDMA: EQU 26 ; ; ; FILE HANDLING EQUATES ; BUFSIZ: EQU 80H ;BUFFER SIZE (128 BYTES) BDOS: EQU BASE+5 FCB: EQU BASE+5CH FCB2: EQU BASE+6CH FCBEXT: EQU FCB+12 FCBRNO: EQU FCB+32 TBUF: EQU BASE+80H ;TEMPORARY BUFFER (DEFAULT) ADDRESS ; ; ; CONTROL CHARACTERS ; CTLC: EQU 'C'-40H ;CONTROL-C CHARACTER EOF: EQU 'Z'-40H ;END-OF-FILE CHARACTER LF: EQU 'J'-40H ;LINE FEED CHARACTER CR: EQU 'M'-40H ;CARRIAGE RETURN CHARACTER TAB: EQU 'I'-40H ;TAB CHARACTER BELL EQU 7 ;BELL CHARACTER ; ; ; * * * * * * * * * * * * * * * * * * ; ; ORG BASE+100H ; ; CHEK: JMP BEGIN ;JUMP AROUND PATCH PARAMETERS ; ; FILEOK: DB TRUE ;TRUE TO ALLOW DISK FILE OF RESULTS SYSOK: DB TRUE ;TRUE TO ALLOW HANDLING '.SYS' FILES ; ; ;*********************************************************************** ; ; ; PROGRAM STARTS HERE ; ; ; ;*********************************************************************** ; ; BEGIN: POP H ;GET CCP RETURN ADDRESS SHLD EXIT+1 LXI SP,STACK ;INITIALIZE LOCAL STACK MVI A,1 STA MFFLG1 ;INIT 1ST TIME SWITCH STA NFLAG ;NO FILES FOUND YET MVI A,' ' ;NO OUTPUT FILE YET STA FFLAG ;'CRC' DISK FILE FLAG LDA FCB+1 CPI ' ' ;SEE IF NAME THERE JNZ BEGIN2 ;YES, CONTINUE ; CALL ERXIT ;PRINT MSG, THEN EXIT DB CR,LF,LF,LF,' ++ No file name specified ++' DB CR,LF,LF,LF,LF,' ' DB 'COMMANDS: CHEK [drive:] FILE' DB CR,LF,LF,LF,' ' DB 'Examples: CHEK B:HELLO.ASM check only HELLO.ASM' DB CR,LF,' ' DB 'CHEK *.ASM check only .ASM files' DB CR,LF,' ' DB 'CHEK *.* check all files, check disk quality' DB CR,LF,' ' DB 'CHEK *.* F makes disk file named CHEKLIST.CRC' DB CR,LF,' ' DB 'CHEK *.* FF makes disk file named FF.CRC' DB CR,LF,' ' DB 'CHEK *.* FILE makes disk file named FILE.CRC' DB CR,LF,' ' DB 'CHEK *.* HELLO.ABC makes disk file named HELLO.ABC' DB CR,LF,LF,LF,' ' DB 'NOTE: If byte 0103 is 0, no disk file is made regard' DB 'less of request' DB CR,LF,LF,'$' ; ; ; FIND AMOUNT OF SPACE FOR BUFFER ; BEGIN2: CALL INITCRC ;GENERATE TABLE FOR FAST CRC CALCULATIONS LXI D,FILADR ;START OF BUFFER ADDRESS LDA BDOS+2 ;GET 'BDOS' ADDRESS SUI 8 ;PROTECT 'CCP' MOV H,A ;GET THE MAIN PAGE XRA A ;CLEAR CARRY IF SET ; ; ; CALCULATE THE DIFFERENCE TO GET SPACE AVAILABLE ; SUB E MOV L,A MOV A,H SBB D ANI 0FCH MOV H,A MVI L,0 ; ; ; FREE SPACE AVAILABLE NOW IN 'HL', SO STORE FOR BUFFER SIZE ; SHLD FILLEN ;STORE BUFFER LENGTH ; ; ; DECLARE 'FCB' FOR OUTPUT FILE (TEMPORARILY NAMED CHEKLIST.$$$) ; LDA FCB2+1 ;GET OPTION STA FFLAG ;'CRC' DISK FILE FLAG CPI ' ' ;FILE WANTED? JZ AGAIN ;NO, SKIP FILE INITIALIZATION LDA FILEOK ;OK TO MAKE A '.CRC' DISK FILE? ORA A JNZ BEGIN3 ;EXIT, IF NOT CALL ILPRT DB CR,LF,BELL,'++ Disk file disabled ++',CR,LF,0 JMP EXIT ; BEGIN3: XRA A STA FCBFIL+12 ;CLEAR EXTENT STA FCBFIL+32 ;CLEAR CURRENT RECORD COUNT LXI H,0 SHLD FILEPTR ;RESET FILE POINTERS MVI C,DELET ;'DELETE FILE' FUNCTION LXI D,FCBFIL ;DELETE 'OLD' CHEKLIST FILE CALL BDOS MVI C,MAKE ;'MAKE FILE' FUNCTON LXI D,FCBFIL ;MAKE 'NEW' CHEKLIST FILE CALL BDOS INR A ;MAKE THE NEW FILE OK? JNZ CPYNAM ;COPY THE FILE NAME REQUESTED MVI C,PRINT ;PRINT STRING FUNCTION LXI D,DIRFUL ;INDICATE THAT DIRECTORY IS FULL CALL BDOS JMP FILERR ;... ; ; CPYNAM: LDA FCB2+1 ;CHECK FOR FILE NAME CPI 'F' ;SEE IF "QUICK NAME FOR CHEKLIST.CRC JNZ CPYN1 ;IF NOT, USE FILE NAME ASKED FOR LDA FCB2+2 ;IF "F" CHECK NEXT COLUMN CPI ' ' ;BLANK? JZ AGAIN ;IF YES, LEAVE NAME CHEKLIST.CRC ; CPYN1: LDA FCB2+9 ;EXTENT REQUESTED BY OPERATOR? CPI ' ' JZ CPYN2 ;IF NOT USE OUR '.CRC' BY DEFAULT MVI A,12 ;OTHERWISE USE THE ONE REQUESTED STA CPYN3+1 ; CPYN2: LXI H,FCB2 ;TRANSFER THE REQUESTED NAME LXI D,FCBFIN ; CPYN3: MVI C,9 ;FILENAME IS 1+8 LENGTH ; CPYN4: MOV A,M STAX D INX H INX D DCR C JNZ CPYN4 ;... ; ; AGAIN: LXI SP,STACK ;RE-INIT STACK POINTER CALL MFNAME ;SEARCH FOR NAMES JNC NAMTST ;ANOTHER FOUND, PRINT NAME LDA NFLAG ;NOTHING FOUND, CHECK... ORA A ;... FIRST TIME FLAG JZ DONE ;AT LEAST ONE WAS FOUND CALL ABEXIT ;PRINT MSG, THEN EXIT DB CR,LF,'++ File not found ++$' ; DONE: LDA FFLAG ;MAKING A '.CRC' DISK FILE? CPI ' ' JZ DONE1 ;NO, SKIP THE FILE STUFF ; ; ; CLOSE CHEKLIST.$$$ ; CLSFIL: LHLD FILEPTR MOV A,L ANI 07FH JNZ CLSF1 SHLD FILLEN ; CLSF1: MVI A,EOF PUSH PSW CALL PTFIL POP PSW JNZ CLSFIL MVI C,CLOSE LXI D,FCBFIL CALL BDOS INR A JNZ ERASE MVI C,PRINT LXI D,NOCLOS CALL BDOS ; ; ; ERASE ANY EXISTING OLD FILE ; ERASE: MVI C,DELET LXI D,FCBFIN CALL BDOS ; ; ; RENAME CHEKLIST.$$$ TO CHEKLIST.CRC ; LXI H,FCBFIL LXI D,FCBFIN PUSH H LXI B,16 DAD B ; MOVNAM: LDAX D MOV M,A INX D INX H DCR C JNZ MOVNAM POP D MVI C,RENAM CALL BDOS ; ; ; NOW EXIT TO CP/M ; DONE1: CALL MSGXIT ;PRINT 'DONE' THEN EXIT DB CR,LF,'Done',CR,LF,'$' ;..... ; ; ; TEST FOR NAMES TO IGNORE ; NAMTST: LDA SYSOK ;SEE IF '.SYS' FILES ALLOWED ORA A JNZ DOSYS ;IF ALLOWED, EXIT LDA FCB+10 ;GET 'SYS' ATTRIBUTE ANI 80H ;IS IT 'SYS'? JNZ AGAIN ;YES, IGNORE THIS FILE ; ; ; IGNORE FILES WITH .$$$ FILETYPE (THEY ARE USUALLY ZERO-LENGTH AND ; CLUTTER UP OUR DISPLAY. WE ALSO WANT TO IGNORE OUR CHEKLIST.$$$ ; TEMPORARY FILE). ; DOSYS: LXI H,FCB+9 ;POINT TO FILETYPE IN 'FCB' CALL TSTBAD ;CHECK FOR .$$$ FILES JZ AGAIN ;IF ZERO FLAG, IGNORE THEM XRA A ;FOUND SOME NAMES STA NFLAG CALL SIGNON ; ; ; MOVE 8 CHARACTERS FROM FCB+1 TO FNAME ; LXI H,FCB+1 LXI D,FNAME LXI B,8 CALL MOVER ; ; ; MOVE 3 CHARACTERS FROM FCB+9 TO FNAME+9 ; LXI H,FCB+9 LXI D,FNAME+9 LXI B,3 CALL MOVER ; ; ; NOW PRINT FILENAME.TYPE ; CALL ILPRT ; PRINT: ; FNAME: DB 'XXXXXXXX.XXX ',0 ; ; ; OPEN THE FILE ; LXI D,FCB MVI C,OPEN CALL BDOS INR A JNZ RDINIT ; CALL ABEXIT DB '++ OPEN FAILED ++$' ; ; ; INITIALIZE 'CRC' TO ZERO AND SET 'BUFAD' TO CAUSE INITIAL READ ; RDINIT: LXI H,0 SHLD CRCVAL ;RESET VALUE TO ZERO FOR NEW CHECK LXI H,BASE+100H SHLD BUFAD ;INIT BUFFER ADRRESS ; ; ; INITIALIZE CHARACTER COUNT TO ZERO ; LXI H,COUNTN ;CLEAR THE CHARACTER COUNTER MVI B,6 CALL RDIN1 ; ; ; INITIALIZE RECORD COUNT TO ZERO ; LXI H,COUNTR ;CLEAR THE RECORD COUNTER MVI B,3 CALL RDIN1 JMP READIT ; RDIN1: MVI M,' ' INX H DCR B JNZ RDIN1 MVI M,'0' ;USE A DECIMAL '0' FOR EMPTY FILE RET ;... ; ; ; THIS IS THE READ LOOP ; READIT: LHLD BUFAD MOV A,H ;TIME TO READ? CPI BASE SHR 8 JZ NORD ;NO READ MVI C,CSTAT CALL BDOS ;CHECK FOR OPERATOR ABORT ORA A JZ READ1 ;NOTHING TO READ, EXIT MVI C,RDCON CALL BDOS ;GET CHARACTER INPUTTED CPI CTLC ;CONTROL-C? JZ ABEXT1 ;YES EXIT ; READ1: LXI D,FCB MVI C,READ ;READ ANOTHER SECTOR OF FILE CALL BDOS ORA A ;CHECK RETURN CODE JNZ FINISH ;ERROR OR 'EOF' CALL COUREC ;INCREMENT THE RECORD COUNT LXI H,TBUF ;BUFFER LOCATION ; NORD: MOV A,M ;GET FILE CHARACTER INX H SHLD BUFAD CALL UPDCRC ;UPDATE THE 'CRC' VALUE CALL COUCHR ;INCREMENT THE CHARACTER COUNT JMP READIT ;GO READ MORE CHARACTERS ;..... ; ; FINISH: CPI 1 ;NORMAL END-OF-FILE? JNZ FILERR ;NO, IT WAS A READ ERROR ; LDA CRCVAL+1 ;GET 'MSP' OF 'CRC' CALL HEXO ;PRINT IT MVI A,' ' ;SEPARATE 'LSP' AND 'MSP' CALL TYPE LDA CRCVAL ;GET 'LSP' OF 'CRC' CALL HEXO ;PRINT IT CALL ILPRT ;PRINT FOLLOWING MESSAGE DB ' ' ; COUNTN: DB ' ' ;GIVES CHARACTER COUNT DB ' ' ; COUNTR: DB ' ',0 ;GIVES RECORD COUNT CALL CRLF ;TURN UP NEW LINE JMP AGAIN ;SEE IF MORE FILES TO DO ;..... ; ; FILERR: CALL ABEXIT ; ABORT BECAUSE OF FILE READ ERROR DB '++ File read error ++$' ;..... ; ; HEX OUTPUT ; HEXO: PUSH PSW ;SAVE FOR RIGHT DIGIT RAR ;RIGHT.. RAR ;..JUSTIFY.. RAR ;..LEFT.. RAR ;..DIGIT.. CALL NIBBL ;PRINT LEFT DIGIT POP PSW ;RESTORE RIGHT ; NIBBL: ANI 0FH ;ISOLATE DIGIT CPI 10 ;IS IS LESS THAN 10? JC ISNUM ;YES, NOT ALPHA ADI 7 ;ADD ALPHA BIAS ; ISNUM: ADI '0' ;CONVERT FROM BINARY TO ASCII JMP TYPE ;PRINT IT, THEN RETURN ;..... ; ; ; INLINE PRINT ROUTINE ; ILPRT: XTHL ;SAVE 'HL', GET MSG ; ILPLP: MOV A,M ;GET CHAR CALL TYPE ;OUTPUT IT INX H ;POINT TO NEXT MOV A,M ;TEST ORA A ;..FOR END JNZ ILPLP XTHL ;RESTORE 'HL', RETURN ADDRESS RET ;RETURN PAST MSG ;..... ; ; ; COUNT RECORDS CHECKED ; COUREC: PUSH H ;SAVE THE CURRENT ADDRESS LXI H,COUNTR+3 MVI C,4 JMP COUNT ;COUNTS UP TO 9,999 RECORDS ;... ; ; ; COUNT CHARACTERS CHECKED ; COUCHR: PUSH H LXI H,COUNTN+6 ;CHARACTER COUNT STORAGE MVI C,7 ;COUNTS UP TO 9,999,999 CHARACTERS ; ; ; COUNTER FOR CHARACTERS / RECORDS CHECKED ; COUNT: PUSH D ;SAVE THE REGISTER VALUES PUSH B ; COUNT1: CALL COUNT2 ;INCREMENT THE STORAGE COUNT JNZ COUNT4 ;FINISHED IF NOT GOING ANY FURTHER DCX H ;DECREMENT STORAGE LOCATION DCR C ;ONE COLUMN LESS TO DO JNZ COUNT1 ;IF NOT ZERO, PROCESS NEXT COLUMN JMP COUNT4 ;FINISHED IF ALL COLUMNS PROCESSED ;... ; ; COUNT2: MOV A,M ;SET DIGIT TO "1" IF NOW A SPACE CPI ' ' ;SEE IF A SPACE JNZ COUNT3 ;EXIT IF NOT MVI A,'0' ;OTHERWISE CALL IT A DECIMAL '0' ; COUNT3: INR A ;INCREMENT THE DIGIT MOV M,A ;STORE NEW VALUE CPI '9'+1 ;READY TO GO PAST DECIMAL '9'? RNZ ;FINISHED IF NOT MVI A,'0' ;OTHERWISE CALL IT A ZERO MOV M,A ;STORE NEW VALUE RET ;RETURN TO AND INCREMENT NEXT COLUMN ;... ; ; COUNT4: POP B ;RESTORE THE REG. VALUES POP D POP H RET ;ALL DONE ;..... ; ; ; SEND CARRIAGE RETURN, LINE FEED TO OUTPUT ; CRLF: MVI A,CR ;CARRIAGE RETURN CALL TYPE MVI A,LF ;LINE FEED, FALL INTO 'TYPE' ; ; ; SEND CHARACTER IN 'A' REGISTER TO OUTPUT ; TYPE: PUSH B PUSH D PUSH H ANI 7FH ;STRIP OFF ANY PARITY MOV E,A PUSH D CALL WRFILE ;WRITE TO FILE IF REQUESTED POP D MVI C,WRCON ;SEND CHARACTER TO CONSOLE CALL BDOS POP H POP D POP B RET ;..... ; ; PTFIL: PUSH PSW ;SAVE OUTPUT CHARACTER LHLD FILLEN ;GET CURRENT BUFFER LENGTH XCHG ;'DE' HAS LENGTH LHLD FILEPTR ;LOAD NEXT TO GET/PUT TO 'HL' MOV A,L ;COMPUTE CURRENT LENGTH SUB E MOV A,H SBB D ;CARRY IF NEXT < LENGTH JC PTCRC4 ;CARRY IF LENGTH > CURRENT LXI H,0 ;END OF BUFFER, FILL (EMPTY) BUFFERS SHLD FILEPTR ;CLEAR NEXT TO GET/PUT ; PTCRC1: XCHG ;FILE POINTER TO 'DE' LHLD FILLEN ;'HL' IS MAXIMUM BUFFER LENGTH MOV A,E ;COMPUTE NEXT LENGTH SUB L ;TO GET CARRY, IF MORE FILL MOV A,D SBB H JNC PTCRC3 LXI H,FILADR ;GOT CARRY, MORE TO FILL YET DAD D ;'HL' IS NEXT BUFFER ADDRESS XCHG MVI C,STDMA ;SET 'DMA' ADDRESS CALL BDOS LXI D,FCBFIL ;'FCB' ADDRESS TO 'DE' MVI C,WRITE ;FILE WRITE CALL BDOS ORA A ;CHECK RETURN CODE JNZ PTCRC2 ;END-OF-FILE YET? LXI D,BUFSIZ ;NOT 'EOF', INCREMENT LENGTH BY 128 LHLD FILEPTR ;NEXT TO FILL DAD D SHLD FILEPTR ;SAVE NEW POINTER JMP PTCRC1 ;PROCESS ANOTHER SECTOR ;... ; ; PTCRC2: MVI C,PRINT ;PRINT STRING FUNCTION LXI D,DSKFUL ;DISK IS FULL CALL BDOS POP PSW ;CLEAN STACK JMP FILERR ;FILE ERROR, EXIT ;... ; ; PTCRC3: LXI D,TBUF ;POINT TO TEMPORARY BUFFER MVI C,STDMA ;SET 'DMA' FUNCTION CALL BDOS LXI H,0 ;RESET POINTER FOR NEXT TO GET SHLD FILEPTR ; PTCRC4: XCHG ;INDEX TO GET/PUT IN 'DE' LXI H,FILADR ;BASE OF BUFFER DAD D ;ADDRESS OF CHARACTER IN 'HL' XCHG ;AND SWAP TO 'DE' POP PSW ;GET SAVE CHARACTER STAX D ;CHARACTER TO BUFFER LHLD FILEPTR ;INDEX TO GET/PUT INX H ;AND UPDATE FOR NEXT CHARACTER SHLD FILEPTR RET ;..... ; ; ; PRINT SIGNON MESSAGE, AND INCLUDE ON DISK FILE ; SIGNON: DB 0 ;GETS OVERWRITTEN TO "RET" CALL ILPRT ;PRINT THE MESSAGE ; SOM: DB CR,LF,'----CHEK--------ver 1.5-------04/11/83----',CR DB LF,LF,' FILE CRC CHARS RECORDS' DB CR,LF,LF,0 MVI A,0C9H ;'RET' TO ALLOW ONLY ONE SIGNON STA SIGNON RET ;..... ; ; ; WRITE CHARACTER IN 'E' REGISTER TO OUTPUT FILE ; WRFILE: LDA FFLAG ;MAKING A 'CRC' DISK FILE? CPI ' ' ;IS IT SET? RZ ;NO, RETURN MOV A,E ;GET CHARACTER BACK CALL PTFIL RET ;..... ; ; ; MULTI-FILE ACCESS SUBROUTINE. ALLOWS PROCESSING OF MULTIPLE FILES ; (I.E., *.ASM) FROM DISK. THIS ROUTINE BUILDS THE PROPER NAME IN THE ; FCB EACH TIME IT IS CALLED. CARRY IS SET IF NO MORE NAMES CAN BE ; FOUND. ; MFNAME: MVI C,STDMA ;INIT 'DMA' ADDRESS AND 'FCB' LXI D,TBUF CALL BDOS XRA A STA FCBEXT STA FCBRNO ; ; ; IF FIRST TIME ; LDA MFFLG1 ORA A JZ MFN01 ; ; ; SAVE THE REQUESTED NAME - SAVE ORIGINAL REQUEST ; LXI H,FCB LXI D,MFREQ LXI B,12 CALL MOVER LDA FCB STA MFCUR ;SAVE DISK IN CURRENT 'FCB' ; ; SEARCH FOR THE FIRST REQUESTED NAME ; LXI H,MFREQ LXI D,FCB LXI B,12 CALL MOVER MVI C,SRCHF ;SEARCH FOR FIRST NAME LXI D,FCB CALL BDOS JMP MFN02 ; MFN01: LXI H,MFCUR LXI D,FCB LXI B,12 CALL MOVER MVI C,SRCHF ;SEARCH FOR FIRST NAME LXI D,FCB CALL BDOS ; ; ; SEARCH FOR NEXT REQUESTED NAME ; LXI H,MFREQ LXI D,FCB LXI B,12 CALL MOVER MVI C,SRCHN ;SEARCH FOR NEXT NAME LXI D,FCB CALL BDOS ; MFN02: INR A STC RZ ; ; ; MOVE NAME FOUND TO CURRENT NAME ; DCR A ANI 3 ADD A ADD A ADD A ADD A ADD A ADI 128+1 MOV L,A MVI H,BASE SHR 8 PUSH H ;SAVE NAME POINTER LXI D,MFCUR+1 LXI B,11 CALL MOVER ; ; ; MOVE NAME FOUND TO FCB ; POP H LXI D,FCB+1 LXI B,11 CALL MOVER ; ; ; SETUP FCB ; XRA A STA FCBEXT STA FCBRNO STA MFFLG1 ;TURN OFF 1ST TIME SWITCH RET ;..... ; ; ; CHECK FOR .$$$ FILES ; TSTBAD: CALL TESTIT ;CHECK FIRST ONE FOR '$' RNZ ;NO, RETURN CALL TESTIT ;CHECK SECOND ONE RNZ ;NO, RETURN ;... ; ; TESTIT: MOV A,M ANI 7FH ;STRIP ATTRIBUTE CPI '$' ;CHECK FOR $ FILETYPE INX H RET ;..... ; ; ; MOVE (BC) BYTES FROM (HL) TO (DE) ; MOVER: MOV A,M STAX D INX H INX D DCX B MOV A,B ORA C JNZ MOVER RET ;..... ; ; ; ABORTED - PRINT REASON. IF MAKING OUTPUT FILE, CLOSE THE INCOMPLETE ; FILE TO UPDATE CP/M'S BIT MAP, THEN ERASE IT. ; ABEXIT: POP D ;GET MSG ADRS MVI C,PRINT CALL BDOS ;PRINT MSG ; ABEXT1: LDA FFLAG ;SEE IF WE ARE MAKING A DISK FILE CPI ' ' JZ ABEXT4 ;IF NOT, EXIT ; ABEXT2: LHLD FILEPTR MOV A,L ANI 07FH JNZ ABEXT3 SHLD FILLEN ; ABEXT3: MVI A,EOF PUSH PSW CALL PTFIL POP PSW JNZ ABEXT2 MVI C,CLOSE LXI D,FCBFIL CALL BDOS INR A JNZ ERACRC MVI C,PRINT LXI D,NOCLOS CALL BDOS ; ; ; ERASE INCOMPLETE FILE ; ERACRC: MVI C,DELET LXI D,FCBFIL CALL BDOS ; ABEXT4: CALL ERXIT ;PRINT MSG, EXIT DB CR,LF,LF,'++ ABORTED ++',CR,LF,'$' ; ; ; EXIT WITH MESSAGE ; MSGXIT: DS 0 ;EXIT WITH "INFORMATIONAL" MESSAGE ; ERXIT: POP D ;GET MSG MVI C,PRINT CALL BDOS ; ; ; EXIT, RESTORING STACK AND RETURN TO 'CCP' ; EXIT: JMP 0000H ;OVERWRITTEN WITH 'CCP' RETURN ;..... ; ; DIRFUL: DB CR,LF DB '++ NO DIRECTORY SPACE FOR CRC FILE ++',CR,LF,'$' ; DSKFUL: DB CR,LF DB '++ NO DISK SPACE FOR CRC FILE ++',CR,LF,'$' ; NOCLOS: DB CR,LF DB '++ CANNOT CLOSE CRC FILE ++',CR,LF,'$' ;..... ; ; ;----------------------------------------------------------------------- ; ; CRCSUBS (Cyclic Redundancy Code Subroutines) for 8080 Mneumonics ; ; These subroutines compute and check a true 16-bit Cyclic Redundancy ; Code for a message of arbitrary length. ; ; This algorithm produces the same results as obtained in COMM700, ; DISK7, MDM700, and MODEM700 programs. ; ; ; Builds the 512-byte look-up table ; INITCRC: LXI H,CRCTBL ;ADDRESS OF THE 512-BYTE LOOK-UP TABLE MVI C,0 ;TABLE INDEX ; GLOOP: XCHG LXI H,0 ;INITIALIZE 'CRC' REGISTER PAIR MOV A,C PUSH B ;SAVE THE INDEX IN 'C' REG. MVI B,8 XRA H MOV H,A ; LLOOP: DAD H JNC LSKIP MVI A,10H ;GENERATOR IS x^16 + x^12 + x^5 + x^0 AS XRA H ;RECOMMENDED BY 'CCIT' FOR ASYNCHRONOUS MOV H,A ;COMMUNICATIONS MVI A,21H XRA L MOV L,A ; LSKIP: DCR B JNZ LLOOP POP B XCHG ;'DE' PAIR NOW HAS 'CRC', 'HL' POINTING MOV M,D ;INTO TABLE. STORE HIGH BYTE OF 'CRC' INR H MOV M,E ;STORE LOW BYTE DCR H INX H ;MOVE TO NEXT TABLE ENTRY INR C ;NEXT INDEX JNZ GLOOP RET ;..... ; ; ; Updates the CRC value. Finds its value by indexing into the look-up ; table. Character arrives in the 'A' register. ; UPDCRC: LHLD CRCVAL ;PICK UP PARTIAL REMAINDER XCHG ;'DE' PAIR NOW HAS PARTIAL MVI B,0 XRA D MOV C,A LXI H,CRCTBL ;INDEX INTO THE 512-BYTE 'CRC' TABLE DAD B MOV A,M XRA E MOV D,A INR H MOV E,M XCHG SHLD CRCVAL ;STORE THE CURRENT 'CRC' VALUE RET ;..... ; ; ;----------------------------------------------------------------------- ; ; PROGRAM STORAGE AREA ; BUFAD: DB 0,0 ;READ BUFFER ADDRESS CRCVAL: DB 0,0 ;'CRC' VALUE STORAGE FFLAG: DB 0 ;FILE WRITE REQUEST FLAG MFCUR: DB ' ' ;CURRENT NAME MFFLG1: DB 1 ;1ST TIME SWITCH MFREQ: DB ' ' ;REQUESTED NAME NFLAG: DB 0 ;SET TO ZERO IF FILE(S) FOUND FILLEN: DB 0,0 ;FILLED AUTOMATICALLY FILEPTR: DB 0,0 ; ; ; BUILD FCB FOR FINAL NAME OF CHEKLIST.CRC ; FCBFIN: DB 0,'CHEKLISTCRC' DB 0 DS 20 ; ; ; OUTPUT FILE (TEMPORARILY NAMED CHEKLIST.$$$) ; FCBFIL: DB 0,'CHEKLIST$$$' DB 0 DS 20 DS 24 ;MINIMUM STACK AREA ; SETEVN: EQU ($+127)/128*128 ;SET BUFFER TO EVEN PAGE ; ; ORG SETEVN ; STACK: DS 0 ; CRCTBL: DS 512 ;CRC DOUBLE-TABLE STORAGE ; FILADR: DS 0 ;BUFFER ALL 'CRC' FILE DATA HERE ;..... ; ; END BEGIN