home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols200
/
vol210
/
crcbuild.lbr
/
CRCBUILD.AQM
/
CRCBUILD.ASM
Wrap
Assembly Source File
|
1986-02-09
|
14KB
|
695 lines
;
; CRCBUILD.ASM version 1.0
; by John L. Raff WB2MDG/KAPP8107
; (built 830408FR)
;
;---> NOTE: MUST BE ASSEMBLED BY MAC <----
;
;CRCBUILD is a program to build a CP/M file in SIG/M
;-CATALOG format and print
;a CYCLIC-REDUNDANCY-CHECK number based on the
;CCITT standard polynominal:
; X^16 + X^15 + X^13 + X^7 + X^4 + X^2 + X + 1
;
;Define true and false
;
FALSE EQU 0
TRUE EQU NOT FALSE
;
;Conditional assembly switches
;
STDCPM EQU TRUE ;TRUE IS STANDARD CP/M
ALTCPM EQU FALSE ;TRUE IS H8 OR TRS-80
NOSYS EQU FALSE ;TRUE IF SYS FILES NOT WANTED
;
;System equates
;
BASE SET 0
IF ALTCPM
BASE SET 4200H
ENDIF ;ALTCPM
;
;Define write buffer size (presently set for 8k)
;
BSIZE EQU 8*1024 ;DISK WRITE BUFFER SIZE
;
;BDOS equates
;
RDCON EQU 1
WRCON EQU 2
PRINT EQU 9
READCONSOLE EQU 10 ;Read console buffer
CSTAT EQU 11
OPEN EQU 15
SRCHF EQU 17
SRCHN EQU 18
READ EQU 20
STDMA EQU 26
BDOS EQU BASE+5
FCB EQU BASE+5CH
FCBEXT EQU FCB+12
FCBRNO EQU FCB+32
FCB2 EQU BASE+6CH
STRLMT EQU 80 ;STRING LENGTH LIMIT
;
;Program starts here
;
ORG BASE+100H
;
MACLIB SEQIO ;DEFINE MACRO LIBRARY USED
CRCBUILD:
JMP BEGIN ;Jump around identification & alternate file name
DB 'CRCBUILD.COM 1.0 830408fr',0
;
BEGIN:
XRA A
STA NAMQUAN ;Zero the quantity of files read
LXI H,0 ;GET STACK...
DAD SP ;POINTER SO WE CAN..
SHLD STACK ;SAVE IT
LXI SP,STACK ;INITIALIZE LOCAL STACK
BGN2:
CALL CRLF ;TURN UP A NEW LINE
CALL ILPRT ;Print the heading
DB 'CRCBUILD Ver 1.0 830224TH',CR,LF
DB 'CTL-S pauses, CTL-C aborts',CR,LF,0
LDA FCB+1
CPI ' ' ;SEE IF NAME THERE
JNZ BEGIN2 ;YES, CONTINUE
LXI D,FCB+2 ;Put total directory pattern
LXI H,FCB+1 ;in FCB
MVI M,'?' ;All "?"
LXI B,10 ;4 characters
CALL MOVER ;MOVE IT
JMP BEGIN2 ;Go get um
;
THRNUM?: ;Check for three ascii numbers
CALL TWONUM?
RNZ ;Return if not numbers
CALL NUM?
RZ ;Return if a number
CPI '.' ;Check for a period
RNZ ;Return if not a period
DCX H ;Otherwise back up one character
DCR B ;And one count
CMP A ;Set zero flag
RET
;
TWONUM?:
CALL NUM?
RNZ
NUM?:
MOV A,M ;Get the character
INX H ;For next character
INR B ;Increment for next count
CPI '0' ;Is it less than 0
JC NUMNOT ;Branch if it is
CPI '9'+1 ;Is it greater than 9?
JNC NUMNOT
CMP A ;Set zero flag
RET
NUMNOT:
CPI '0' ;Should not be equal, reset zero flag
RET
;
BEG2NG:
CALL ILPRT
DB CR,LF,'Incorrect characters',CR,LF,0
;
BEGIN2:
CALL ILPRT
DB 'Enter -CATALOG.xxx number (three digits) -',0
LXI D,STR4 ;Point to string 4
MVI A,5 ;Indicate size of buffer
STAX D
MVI C,READCONSOLE ;Read console buffer
CALL BDOS ;Go get the string
LXI H,STR4+1 ;Point to quantity characters entered
MOV C,M ;Get the count
MVI A,3 ;Check for three characters
CMP C ;In buffer
JNZ BEG2NG ;Branch if not 3 characters
MVI B,0 ;Zero counter
INX H ;Point to first character
BEG2A:
CALL NUM? ;Is it a decimal number?
JNZ BEG2NG ;Branch if not a decimal number
MOV A,B ;Check quantity of characters
CPI 3
JNZ BEG2A ;Branch if not end of characters yet
MVI M,0 ;Ensure termination of string
LXI H,STR4+2 ;Copy number into file string
LXI D,FNAME1
LXI B,3 ;Count
CALL MOVER
MVI A,'F' ;Indicate write file open
STA FFLAG
;
;'Declare' FCB for output file
;(temporarily named -CATALOG.$$$)
;
FILE OUTFILE,CATALOG,,-CATALOG,$$$,BSIZE
;
AGAIN: LXI SP,STACK ;RE-INIT STACK POINTER
MVI A,0 ;Indicate in building phase
STA WHICH ;Save flag
CALL MFNAME ;SEARCH FOR NAMES
JNC NAMTST ;ANOTHER FOUND, PRINT NAME
AGN2:
LDA MFFLG2 ;NOTHING FOUND, CHECK...
ORA A ;... NAME FOUND FLAG
JZ DONE ;AT LEAST ONE WAS FOUND
CALL ABEXIT ;PRINT MSG, THEN EXIT
DB '++FILE NOT FOUND++$'
;
DONE: ;Close -CATALOG.$$$
LXI H,FNAME1
LXI D,DONEX
LXI B,3
CALL MOVER
CALL ILPRT
DB CR,LF,'SIG-M Library -CATALOG Volume Number-'
DONEX:
DB 'NNN, ',0
DONEY:
LDA NAMQUAN
CALL SHWDC
CALL ILPRT
DB ' Files cataloged.',CR,LF,0
;
FINIS CATALOG
;
LXI H,STR4+2 ;Point to beginning of string
LXI D,FCBFINAL+9 ;Location of Name TYPE
LXI B,3 ;Quantity to move
CALL MOVER
;
;Build FCB for final name of -CATALOG.nnn
;
FILE SETFILE, FINAL,,-CATALOG,NNN
;
; Erase any existing old file
;
ERASE FINAL
;
; Rename -CATALOG.$$$ to -CATALOG.NNN
RENAME FINAL,CATALOG
;
;Now exit to CP/M
DONE2:
CALL MSGEXIT ;PRINT DONE, THEN EXIT
DB CR,LF,'DONE$'
;
;Test for names to ignore
;
NAMTST: IF NOSYS
LDA FCB+10 ;GET SYS ATTRIBUTE
ANI 80H ;IS IT SYS?
JNZ AGAIN ;YES, IGNORE THIS FILE
ENDIF ;NOSYS
;
;Ignore files with .$$$ filetype (they are usually
;zero-length and clutter up our display. We also
;want to ignore our own CRCKLIST.$$$ temporary file).
;
LXI H,FCB+9 ;POINT TO FILETYPE IN FCB
PUSH H ;May need pointer for BAD check
CALL TSTBAD ;CHECK FOR .$$$ FILES
JZ AGAIN ;IF ZERO FLAG, IGNORE THEM
POP H ;Restore pointer
CALL BADTYP ;Check for .BAD files
JZ AGAIN ;Branch if it is
;
NAMTS2:
CALL ILPRT ;PRINT:
DB CR,LF
FNAME1:
DB 'NNN.',0
;
LDA NAMQUAN ;Get quantity of name
INR A ;Increment count
STA NAMQUAN
CALL SHWDC ;Show the count
;
;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
DB ' '
FNAME:
DB 'XXXXXXXX.XXX ',0
FNAME2:
CALL OPN ;Open file and build CRC
JZ AGAIN ;Branch if bad open or read
JMP ABEXT2 ;Otherwise get out
;
;Open the file
;
OPN:
LXI D,FCB
MVI C,OPEN
CALL BDOS
INR A
JNZ RDINIT
CALL ILPRT
DB '++Open Failed++',0
JMP BADRET ;Indicate Bad open
;
;Initialize CRC to zero and set Bufad to cause initial read
;
RDINIT:
LXI H,0
SHLD REM ;Init remainder to zero
SHLD QUANEK ;Quantity of eighth k
LXI H,BASE+100H
SHLD BUFAD ;Init buffer address
;
;This is the read loop
;
READIT:
LHLD BUFAD
MOV A,H ;Time to read?
CPI BASE SHR 8 ;End of buffer?
JZ NORD
MVI C,CSTAT
CALL BDOS ;Chck for operator abort
ORA A
JZ READ2 ;Branch if nothing from operator
MVI C,RDCON
CALL BDOS ;Get character from operator
CPI 'C'-40h ;Control C?
JZ ABEXT2 ;Branch if yes, exit
;
READ2:
LXI D,FCB
MVI C,READ ;Read another sector of file
CALL BDOS
ORA A ;Check return code
JNZ FINISH ;Error or EOF
LHLD QUANEK ;Get quantity of eighth K
INX H ;Add 1
SHLD QUANEK ;Put back
LXI H,BASE+80H ;Bufer location
;
NORD:
MOV A,M ;Get file character
STA MESS ;Save for DIVP
INX H
SHLD BUFAD ;Update buffer address
CALL DIVP ;Calculate new CRC
JMP READIT ;GO READ MORE CHARACTERS
;
FINISH: CPI 1 ;NORMAL END-OF-FILE?
JNZ FILERR ;NO, IT WAS A READ ERROR
LHLD QUANEK ;Get quantity of eighth K
LXI B,7
DAD B ;Round up to next K
DAD H ;Turn into full K
DAD H ;In "H" register
DAD H
DAD H
DAD H
MOV A,H
CALL SHWDEC ;Show Number of K
CALL ILPRT
DB 'K ',0
LDA REM+1 ;GET MSP OF CRC
CALL HEXO ;PRINT IT
MVI A,' '
CALL TYPE ;TYPE A SPACE
LDA REM ;GET LSP OF CRC
CALL HEXO ;PRINT IT
GOODRET:
XRA A
RET ;Return to caller with zero flag set
;
FILERR:
CALL ILPRT ;Print the message and return
DB TAB,TAB,'++FILE READ ERROR++',CR,LF,0
BADRET: ;General bad return location
XRA A ;Set zero flag
INR A ;reset zero flag
RET ;Return to caller
;
;---------------------------------------------
;An 8080 routine for generating a CYCLIC-
;REDUNDANCY-CHECK. Character leaves that
;character in location REM. By Fred Gutman.
;From 'EDN' magazine, June 5, 1979 issue, page 84.
;
DIVP:
LHLD REM ;GET REMAINDER
MOV A,H
ANI 128 ;Q-BIT MASK
PUSH PSW ;SAVE STATUS
DAD H ;2 X R(X)
LDA MESS ;MESSAGE BIT IN LSB
ADD L
MOV L,A
POP PSW
JZ QB2 ;IF Q-BIT IS ZERO
;
QB:
MOV A,H
XRI 0A0H ;MS HALF OF GEN. POLY
MOV H,A
MOV A,L
XRI 97H ;LS HALF OF GEN. POLY
MOV L,A
;
QB2:
SHLD REM
RET
;--------------------------------------------
;
;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 <10?
JC ISNUM ;YES, NOT ALPHA
ADI 7 ;ADD ALPHA BIAS
;
ISNUM: ADI '0' ;MAKE PRINTABLE
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, RET ADDR
RET ;RET PAST MSG
;
;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 PARITY BIT
MOV E,A
PUSH D
CALL WRFILE ;WRITE TO FILE IF REQUESTED
POP d
mvi c,WRCON ;send chracter to console
call bdos
pop h
pop d
pop b
ret
;
; Write character in E register to output file
;
WRFILE:
LDA FFLAG ;Get file trigger
CPI 'F' ;Is it set?
RNZ ;No?, return
MOV A,E ;Get character back
PUT CATALOG ;Send it to the file
RET ;to caller
;
;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. The routine is commented in pseudo
;code, each pseudo code statement is in <<...>>
;
MFNAME:
MVI C,STDMA
LXI D,BASE+80H
CALL BDOS
XRA A
STA FCBEXT
STA FCBRNO
;<<if first time>>
LDA MFFLG1
ORA A
JZ MFN01
;<<save the requested name>>
;save orig request
LXI H,FCB
LXI D,MFREQ
LXI B,12
CALL MOVER
LDA FCB
STA MFCUR ;Save disk in curr FCB
;<<srchf requested namd>>
LXI H,MFREQ
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHF
LXI D,FCB
CALL BDOS
;<<else>>
JMP MFN02
;
MFN01: ;<<srchf current name>>
LXI H,MFCUR
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHF
LXI D,FCB
CALL BDOS
;<<SRCHN requested name>>
LXI H,MFREQ
LXI D,FCB
LXI B,12
CALL MOVER
MVI C,SRCHN
LXI D,FCB
CALL BDOS
;<<endif>>
MFN02: ;<<return carry if not found>>
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 81H
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 SW
STA MFFLG2 ;FLAG INDICATING FOUND AT LEAST ONE
;<<return>>
RET
;------------------------------------------------
;
;Check for .$$$ files
;
TSTBAD: CALL TESTIT ;CHECK FIRST ONE FOR '$'
RNZ ;NO, RETURN
CALL TESTIT ;CHECK SECOND ONE
RNZ ;NO, RETURN
;FALL INTO TESTIT TO CHECK THIRD
;
TESTIT: MOV A,M
ANI 7FH ;STRIP ATTRIBUTE
CPI '$' ;CHECK FOR $ FILETYPE
INX H
RET
BADTYP: ;Check for BAD file type
MOV A,M
ANI 7FH
CPI 'B'
RNZ
INX H
MOV A,M
ANI 7FH
CPI 'A'
RNZ
INX H
MOV A,M
ANI 7FH
CPI 'D'
RET ;Return with zero flag set or not
;
;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
;
ABEXT2: LDA FFLAG ;SEE IF WE ARE MAKING FILE
CPI 'F'
JNZ ABEXT3 ;NO FILE, SKIP FILE STUFF
FINIS CATALOG ;CLOSE INCOMPLETE FILE
ERASE CATALOG ;ERASE INCOMPLETE FILE
;
ABEXT3: CALL ERXIT ;PRINT MSG, EXIT
DB CR,LF,CR,LF,'++ABORTED++$'
;
;Exit with message
;
MSGEXIT:EQU $ ;EXIT W/"INFORMATIONAL" MSG
ERXIT: POP D ;GET MSG
MVI C,PRINT
CALL BDOS
;
;Exit, restoring stack and return to CCP
;
EXIT: LHLD STACK
SPHL
RET ;TO CCP
;
SHWDEC: ;3 Digits, up to 255, with leading 0 suppress
MVI B,' ' ;Set for space
MVI C,0
SHWDE:
CPI 100 ;Check if greater than 100
JC NOHUNS
INR C
SUI 100
JMP SHWDE
NOHUNS:
PUSH PSW
MOV A,C
ORA A
JZ NOHN
MVI B,'0' ;Set "0" for next 0
NOHN:
ADD B ;Add space or "0"
CALL TYPE
POP PSW
MVI C,0
CKTENS:
CPI 10
JC NO10S
INR C
SUI 10
JMP CKTENS
NO10S:
PUSH PSW
MOV A,C
ORA A ;Check if any 10s
JZ NO10X
MVI B,'0'
NO10X:
ADD B ;Add space or "0"
CALL TYPE
POP PSW
ADI '0'
JMP TYPE
;
SHWDC: ;2 DIGITS ONLY, 99 only, No 0 supress
MVI C,'0' ;Set up for '0' digit
SHWDC1:
CPI 10 ;Check if greater than 10
JC NOTENS ;Branch if no tens digits
INR C ;Increment tens digit counter
SUI 10 ;Subtract 10 from number
JMP SHWDC1 ;Branch back to test again
NOTENS:
PUSH PSW ;Save the units digit quantity
MOV A,C ;Get the tens digit quantity
CALL TYPE
POP PSW ;Restore the units digit quantity
ADI '0' ;Add ascii digits numeral offset
JMP TYPE ;Display units and return to caller
;
;Program storage area
;
NAMPTR: DS 2 ;Storage for name start in catalog search
MTCH DB 0 ;CRC Match counter
NOMTCH DB 0 ;CRC Don't match counter
BADPAR DB 0 ;Bad parse counter
MISFIL DB 0 ;Missing files counter
FFLAG: DB 0 ;FILE WRITE REQUEST FLAG
FLAGAX: DB 0 ;All user check flag
REM: DW 0 ;CRC REMAINDER STORAGE
QUANEK: DW 0 ;Quantity of eighth K
MSPREM DS 1 ;Storage for CRC MSP from file
LSPREM DS 1 ;LSP from file
MESS: DB 0 ;CRC MESSAGE CHAR GOES HERE
MFFLG1: DB 1 ;1ST TIME SWITCH
MFFLG2: DB 1 ;FLAG INDICATING ONE NAME FOUND OR NOT
XFRST: DB 1 ;1st time check in read
RDCK: DB 0 ;Open file CRCKLIST or -CATALOG
VERNUM: DB 0 ;VERSION NUMBER OF CP/M IN USE
ENTUSR: DB 0 ;ENTRY USER NUMBER
NOWUSR: DB 0 ;PRESENT USER'S NUMBER
NAMQUAN: DB 0 ;Quantity of files read
FRSNAM: DB 1 ;FIRST NAME IN USER FLAG
MFREQ: DS 12 ;REQUESTED NAME
MFCUR: DS 12 ;CURRENT NAME
WHICH DS 1 ;Flag storage for phase
BUFAD: DS 2 ;READ BUFFER ADDRESS
STRCNT DS 2 ;STRING COUNT STORAGE
STRING DS 11 ;STRING STORAGE
STR1: DS 12 ;Name storage
STR2: DS 8 ;Characters after name
STR3: DS 5 ;Ascii CRC characters
STR4: DS 80 ;Buffer
DS 60 ;STACK AREA
STACK: EQU $
OLDSTK: DS 2 ;OLD STACK POINTER SAVED HERE
;
;Define location of file write buffer
BUFFERS:EQU $
;
END CRCK