;
;  PROGRAM:  CRC
;  VERSION:  2.0
;  DATE:  16 Jan 83
;  AUTHOR:  RICHARD CONN
;  PREVIOUS VERSIONS:  1.2 (6 Jan 83), 1.1 (1 Jan 83), 1.0 (12 Dec 82)
;
VERS    equ     20
z3env   SET     0f400h

;
;  CRC Command --
;       CRC is used to compute the CRC of one or more files.  CRC
; permits ambiguous file names and supports an Inspect mode that
; allows the user to confirm each file before the computation is done.
; Additionally, there is a Disk Output Mode which allows the user to send
; the output from the operation to disk as well as to his screen with optional
; comments.
;
;       The CRC command may be of the following forms:
;               CRC dir:afn,dir:afn1,... o
;       CRCs are computed for the indicated sets of files in the indicated
; directories.
;
;       The option characters (o) are none or more of the following:
;               C -- Comment Output; add comments if output is to disk
;               D -- Disk Output; send output to disk file CRC.CRC
;               I -- Inspect and approve each rename
;               P -- Printer Output
;
;       Examples:
;               CRC A1:MYFILE.*,B2:HELLO.TXT    <-- Compute CRCs of files
;               CRC *.* DC                      <-- CRCs of all files in
;                                                   current user/disk with
;                                                   disk output and comments
;               CRC *.* DCI                     <-- As above, but inspect and
;                                                   approve files first
;

FALSE   EQU     0
TRUE    EQU     NOT FALSE

ESIZE   EQU     16      ; SIZE OF DIR ENTRY (FROM SYSLIB DIRF ROUTINE)

       EXT     DIRQS   ; DIRECTORY PROCESSOR
       EXT     DPARAMS ; DISK PARAMETERS
       EXT     DIRPACK ; DIR PACK ROUTINE
       EXT     FSIZE   ; COMPUTE FILE SIZE

       EXT     Z3INIT  ; INIT BUFFERS
       EXT     ZFNAME  ; FILE NAME PROCESSOR
       EXT     Z3LOG   ; LOG INTO Z3 DU

       EXT     FO0$OPEN        ; OPEN FILE FOR BYTE-ORIENTED OUTPUT
       EXT     FO0$CLOSE       ; CLOSE FILE
       EXT     F0$PUT          ; WRITE BYTE TO FILE

       EXT     F$MAKE  ; CREATE FILE
       EXT     F$OPEN  ; OPEN FILE
       EXT     F$READ  ; READ BLOCK FROM FILE
       EXT     F$CLOSE ; CLOSE FILE
       EXT     F$DELETE        ; DELETE FILE

       EXT     CONDIN  ; CONDITIONAL INPUT

       EXT     MA2HC   ; MEMORY STORE OF A AS 2 HEX CHARS
       EXT     MHLDC   ; MEMORY STORE OF HL AS UP TO 5 DEC CHARS W/LEADING SP

       EXT     BBLINE  ; INPUT LINE EDITOR
       EXT     INITFCB ; INIT FCB
       EXT     BDOS    ; BDOS ENTRY
       EXT     RETUD   ; RETURN CURRENT USER/DISK
       EXT     PUTUD   ; SAVE CURRENT USER/DISK
       EXT     GETUD   ; RESTORE CURRENT USER/DISK
       EXT     LOGUD   ; LOG INTO USER/DISK
       EXT     MOVEB   ; COPY ROUTINE
       EXT     EPRINT  ; PRINT STRING PTED TO BY RET ADR
       EXT     LOUT    ; LST: OUTPUT ROUTINE
       EXT     COUT    ; CONSOLE OUTPUT ROUTINE
       EXT     CIN     ; CONSOLE INPUT ROUTINE
       EXT     CAPS    ; CAPITALIZE ROUTINE
       EXT     CRLF    ; NEW LINE ROUTINE
       EXT     CODEND  ; CODE END COMPUTATION ROUTINE

;
;  CP/M EQUATES
;
CPM     EQU     0       ; WARM BOOT
FCB     EQU     5CH     ; FCB
FCB2    EQU     6CH     ; FCB 2
TBUFF   EQU     80H     ; INPUT LINE BUFFER
CR      EQU     13      ; <CR>
LF      EQU     10      ; <LF>
CTRLC   EQU     3       ; ^C

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
;
;  DISK OUTPUT FCB
;
DSKFCB:
       DB      0
       DB      'CRC     '      ; FILE NAME
       DB      'CRC'           ; FILE TYPE
       DS      4
       DS      16
       DS      4       ; 36 BYTES

start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
;
;  DISK OUTPUT FCB
;
DSKFCB:
       DB      0
       DB      'CRC     '      ; FILE NAME
       DB      'CRC'           ; FILE TYPE
       DS      4
       DS      16
       DS      4       ; 36 BYTES

start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3init  ;initialize the ZCPR3 Env and the VLIB Env
;
       LXI     H,0     ; GET STACK PTR
       DAD     SP
       SHLD    STACK   ; SAVE IT
;
; Compute Buffer Locations
;
       CALL    CODEND  ; DETERMINE FREE SPACE
       SHLD    CMDLNE  ; SET PTR TO COMMAND LINE
       LXI     D,100H  ; BUFFER SIZE
       DAD     D       ; COMMAND LINE
       SHLD    CRCFCB  ; FCB FOR CRCS
       DAD     D
       SHLD    CMTLNE  ; BUFFER FOR COMMENT LINE
       DAD     D
       SHLD    DIRBUF  ; SET PTR TO DIRECTORY BUFFER
       SPHL            ; SET STACK PTR
;
; Save Location
;
       CALL    PUTUD   ; SAVE CURRENT USER/DISK AWAY
;
; Print Banner
;
       CALL    EPRINT
       DB      'CRC  Version '
       DB      VERS/10+'0','.',(VERS MOD 10)+'0',0
       LDA     FCB+1   ; GET FIRST CHAR OF FILE NAME
       CPI     ' '     ; NO FILE SPEC?
       JZ      HELP
       CPI     '/'     ; OPTION CAUGHT?
       JNZ     ECONT

;  PRINT HELP INFORMATION
HELP:
       CALL    EPRINT
       DB      CR,LF,' CRC dir:afn1,dir:afn2,... o...'
       DB      CR,LF,'Options:'
       DB      CR,LF,' C -- Comment Mode (Allow user to comment each entry '
       DB      'on disk)'
       DB      CR,LF,' D -- Disk Output (Send Output to Disk in file CRC.CRC)'
       DB      CR,LF,' I -- Inspect Mode (Give user approval option)'
       DB      CR,LF,' L -- Count Lines of Code'
       DB      CR,LF,' P -- Printer Output'
       DB      0

;  RETURN TO OS
RETURN:
       CALL    GETUD   ; RESET DIR
       LHLD    STACK   ; GET OLD STACK
       SPHL            ; SET IT
       RET

;
;  SKIP UNTIL NON-BLANK
;
SBLANK:
       MOV     A,M     ; LOOK FOR BLANK
       INX     H       ; PT TO NEXT
       CPI     ' '     ; BLANK?
       JZ      SBLANK
       DCX     H       ; BACK UP
       RET

;
;  SKIP UNTIL BLANK OR EOL
;
SNBLANK:
       MOV     A,M     ; GET CHAR
       INX     H       ; PT TO NEXT
       CPI     ' '     ; BLANK?
       JZ      SNB1
       ORA     A       ; EOL?
       JNZ     SNBLANK
SNB1:
       DCX     H       ; BACK UP
       RET

;
;  COPY BUFFER INTO TEMP BUFFER
;
ECONT:
       LHLD    CMDLNE  ; PT TO COMMAND LINE
       XCHG            ; ... IN DE
       LXI     H,TBUFF+1       ; PT TO BUFFER
       MVI     B,80H   ; BUFFER SIZE (MAX)
       CALL    MOVEB   ; COPY INTO COMMAND LINE BUFFER

;  EXTRACT FLAGS IF PRESENT
       XRA     A       ; A=0
       STA     LOC     ; SET NO LINES OF CODE COUNT
       STA     INSPECT ; SET NO INSPECT
       STA     COMMENT ; SET NO COMMENT MODE
       STA     PRTOUT  ; SET NO PRINTER OUTPUT
       STA     DSKOUT  ; SET NO DISK OUTPUT
       LXI     H,0     ; SET FILE COUNT
       SHLD    FILECNT
       LHLD    CMDLNE  ; PT TO BUFFER
;
;  SKIP TO FILE NAME STRING
;
       CALL    SBLANK  ; SKIP OVER BLANKS
;
;  SKIP TO END OF FILE NAME STRING
;
       CALL    SNBLANK ; SKIP OVER NON-BLANKS
;
;  SKIP TO FIRST OPTION CHAR
;
       CALL    SBLANK  ; SKIP OVER BLANKS

;
;  CHECK FOR LEADING SLASH ON OPTION AND SKIP IT IF SO
;
OPT:
       CPI     '/'     ; OPTION CHAR?
       JNZ     OPTION
       INX     H       ; SKIP SLASH
;  PROCESS LIST OF OPTIONS
OPTION:
       MOV     A,M     ; GET BYTE
       ORA     A       ; DONE?
       JZ      DSPEC
       INX     H       ; PT TO NEXT CHAR
       CPI     ' '     ; SKIP OVER SPACES
       JZ      OPTION
       CPI     '/'     ; IF OPTION LETTER, OBVIOUS ERROR, SO HELP
       JZ      HELP
       CPI     'P'     ; PRINTER OUTPUT?
       JZ      OPTPRT
       CPI     'L'     ; LINES OF CODE?
       JZ      OPTLOC
       CPI     'C'     ; COMMENT?
       JZ      OPTCMT
       CPI     'I'     ; INSPECT?
       JZ      OPTINS
       CPI     'D'     ; DISK OUTPUT?
       JNZ     HELP

; SET DISK OUTPUT OPTION
       MVI     A,0FFH  ; DISK OUTPUT
       STA     DSKOUT
       JMP     OPTION

; SET PRINTER OUTPUT OPTION
OPTPRT:
       MVI     A,0FFH  ; PRINTER OUTPUT
       STA     PRTOUT
       JMP     OPTION

; SET LINES OF CODE OPTION
OPTLOC:
       MVI     A,0FFH  ; LINES OF CODE COUNTER
       STA     LOC
       JMP     OPTION

; SET COMMENT OPTION
OPTCMT:
       MVI     A,0FFH  ; COMMENT MODE
       STA     COMMENT
       JMP     OPTION

; SET INSPECT OPTION
OPTINS:
       MVI     A,0FFH  ; INSPECT
       STA     INSPECT
       JMP     OPTION

;
;  EXTRACT DISK, USER, AND FILE NAME INFORMATION
;
DSPEC:
       LDA     DSKOUT  ; DISK OUTPUT?
       ORA     A       ; Z=NO
       JZ      DSPEC0
       LXI     D,DSKFCB        ; OUTPUT FCB
       CALL    INITFCB         ; CLEAR FCB
       CALL    F$DELETE        ; DELETE FILE
       CALL    INITFCB         ; CLEAR FCB
       CALL    F$MAKE          ; CREATE FILE
       CALL    FO0$OPEN        ; OPEN FILE
DSPEC0:
       LHLD    CMDLNE  ; PT TO FIRST BYTE
       CALL    SBLANK  ; SKIP TO NON-BLANK
;
;  MAJOR REENTRY POINT WHEN FILE SPECS ARE SEPARATED BY COMMAS
;    HL PTS TO FIRST BYTE OF NEXT FILE SPEC
;
DSPEC1:
       CALL    GETUD   ; RETURN TO HOME DIRECTORY
       LXI     D,FCB   ; PT TO FCB IN DE, PT TO FIRST CHAR OF FILE NAME IN HL
       MVI     A,0     ; SCAN FOR DIR FORM BEFORE DU
       CALL    ZFNAME  ; EXTRACT FILE NAME INTO FCB, AND GET DISK AND USER
       SHLD    NEXTCH  ; SAVE PTR TO DELIMITER WHICH ENDED SCAN

;
;  LOAD DIRECTORY AND PERFORM FUNCTION
;
FCT:
       LXI     D,FCB   ; PT TO FCB
       CALL    Z3LOG   ; LOG INTO DIR
       CALL    RETUD   ; SAVE DIRECTORY WE ARE IN
       MOV     A,B     ; SAVE DISK
       STA     CDISK
       MOV     A,C     ; SAVE USER
       STA     CUSER
       LHLD    DIRBUF  ; PT TO DIRECTORY BUFFER
       MVI     A,11000000B     ; SELECT SYS AND NON-SYS FILES
       LXI     D,FCB   ; PT TO FCB
       CALL    INITFCB ; INIT THE FCB
       CALL    DIRQS   ; LOAD DIR, SELECT FILES, PACK, AND ALPHABETIZE
       CALL    DPARAMS ; GET DISK PARAMETERS FOR FILE SIZE COMPUTATION
       CALL    ICHECK  ; CHECK FOR INSPECT OPTION AND INSPECT IF SET
       CALL    HEADER  ; PRINT COLUMN HEADER
       CALL    GETUD   ; RETURN TO BASE USER/DISK

;
;  PERFORM FUNCTION; HL PTS TO FILE AND BC CONTAINS NUMBER OF FILES
;
FCTL:
       MOV     A,B             ; CHECK FOR COMPLETION (COUNT = 0)
       ORA     C
       JZ      FCTL1
       DCX     B               ; COUNT DOWN
       PUSH    H               ; SAVE PTR AND COUNT
       PUSH    B
       CALL    FUNCTION        ; PERFORM FUNCTION
       POP     B               ; GET COUNT AND PTR
       POP     H
       LXI     D,ESIZE         ; PT TO NEXT ENTRY
       DAD     D
       JMP     FCTL

;
;  CHECK FOR NEXT FILE SPEC
;
FCTL1:
       LHLD    NEXTCH  ; GET PTR
       MOV     A,M     ; GET DELIM
       CPI     ','     ; ANOTHER FILE?
       JNZ     DRETURN
       INX     H       ; PT TO CHAR AFTER COMMA
       JMP     DSPEC1  ; CONTINUE PROCESSING

;
;  FUNCTION COMPLETE -- EXIT
;
DRETURN:
       CALL    DCRLF   ; NEW LINE
       LDA     DSKOUT  ; DISK OUTPUT USED?
       ORA     A       ; NZ=YES
       CNZ     FO0$CLOSE       ; CLOSE FILE
       JMP     RETURN

;
;  EMERGENCY ABORT
;
ABORT:
       CALL    EPRINT
       DB      CR,LF,'** CRC Abort **',CR,LF,0
       CALL    GETUD   ; RETURN HOME
       JMP     DRETURN

;
;  PRINT COLUMN HEADER
;
HEADER:
       CALL    DPRINT
       DB      CR,LF,'      Filename.Typ   Size  Recs   CRC',0
       LDA     LOC     ; LINES OF CODE?
       ORA     A
       JZ      HDR1
       CALL    DPRINT
       DB      '  Lines',0
HDR1:
       LDA     COMMENT ; COMMENT FIELD ALSO?
       ORA     A       ; 0=NO
       RZ
       CALL    DPRINT
       DB      '  Comment',0
       RET
;
;  FUNCTION -- COMPUTE CRCS OF SELECTED FILES
;
FUNCTION:

;
;  PRINT FILE NAME
;
CRCLP:
       CALL    DCRLF   ;NEW LINE
       PUSH    H       ;SAVE PTR
       LHLD    FILECNT         ; INCREMENT FILE COUNT
       INX     H
       SHLD    FILECNT
       CALL    DVAL    ;OUTPUT DECIMAL VALUE
       POP     H       ;GET PTR
       MVI     A,' '   ;LEADING SPACE
       CALL    DOUT
       CALL    PRFN    ; PRINT FILE NAME
       MVI     A,' '   ; SPACE SEPARATOR
       CALL    DOUT
       CALL    FSIZE   ; COMPUTE SIZE IN DE
       XCHG            ; HL=SIZE
       CALL    DVAL    ; OUTPUT VALUE
       MVI     A,'K'   ; OUTPUT K
       CALL    DOUT
       LHLD    CRCFCB  ; PT TO FCB
       XCHG            ; HL = PTR TO FIRST BYTE OF FILE FCB PART
       MVI     B,12    ; 12 BYTES
       CALL    MOVEB
       XRA     A       ; ZERO FIRST BYTE
       STAX    D       ; SELECT CURRENT DISK OF CRCFCB
       JMP     DOIT    ; PERFORM FUNCTION

;
;  TEST FOR COMMENT AND DISK OUTPUT, AND ACCEPT COMMENT IF SET
;
CTEST:
       LDA     COMMENT ; GET FLAG
       ORA     A       ; ZERO IF NONE
       RZ
       CALL    EPRINT
       DB      ' ?',0
       XRA     A       ; DON'T CAPITALIZE
       CALL    BBLINE  ; GET LINE FROM USER
       XCHG            ; SAVE HL
       LHLD    CMTLNE  ; COPY INTO COMMENT LINE BUFFER FOR NOW
       XCHG            ; RESTORE HL AND NEW DE
CTEST1:
       MOV     A,M     ; GET CHAR
       STAX    D       ; PUT CHAR
       ORA     A       ; END?
       RZ
       INX     H       ; PT TO NEXT
       INX     D
       JMP     CTEST1

;
;  PRINT FILE NAME PTED TO BY HL
;       OUTPUT TO CON: AND OPTIONALLY DISK
;
PRFN:
       PUSH    H       ; SAVE PTR
       INX     H       ; PT TO FILE NAME
       MVI     B,8     ; PRINT NAME
       CALL    PRNT
       MVI     A,'.'   ; DECIMAL
       CALL    DOUT
       MVI     B,3     ; PRINT TYPE
       CALL    PRNT
       POP     H       ; GET PTR
       RET

;
;  PRINT CHARS PTED TO BY HL FOR B BYTES
;       OUTPUT TO CON: AND OPTIONALLY DISK
;
PRNT:
       MOV     A,M     ; GET CHAR
       CALL    DOUT
       INX     H       ; PT TO NEXT
       DCR     B       ; COUNT DOWN
       JNZ     PRNT
       RET

;
;  PRINT FILE NAME PTED TO BY HL
;       OUTPUT TO CON:
;
PRFNC:
       PUSH    H       ; SAVE PTR
       INX     H       ; PT TO FILE NAME
       MVI     B,8     ; PRINT NAME
       CALL    PRNTC
       MVI     A,'.'   ; DECIMAL
       CALL    COUT
       MVI     B,3     ; PRINT TYPE
       CALL    PRNTC
       POP     H       ; GET PTR
       RET

;
;  PRINT CHARS PTED TO BY HL FOR B BYTES
;       OUTPUT TO CON:
;
PRNTC:
       MOV     A,M     ; GET CHAR
       CALL    COUT
       INX     H       ; PT TO NEXT
       DCR     B       ; COUNT DOWN
       JNZ     PRNTC
       RET

;
;  CHECK FOR INSPECT OPTION AND INSPECT FILES IF SET
;    FIRST FILE PTED TO BY HL, COUNT IN BC
;
ICHECK:
       LDA     INSPECT ; INSPECT?
       ORA     A       ; 0=NO
       RZ
       CALL    EPRINT
       DB      CR,LF,CR,LF,'** File Inspection **'
       DB      CR,LF,'Y(def)=Select  N=Don''t Select'
       DB      CR,LF,'S=Skip Rest    Q=Quit (Abort)'
       DB      CR,LF,0
       PUSH    H       ; SAVE POINTER TO FIRST FILE
       PUSH    B       ; SAVE FILE COUNT
ICKL:
       PUSH    B       ; SAVE COUNT
       CALL    CRLF    ; NEW LINE
       CALL    PRFNC   ; PRINT FILE NAME TO CONSOLE ONLY
       CALL    CRCQ    ; CRC QUESTION
       POP     B       ; GET COUNT
       CPI     'S'     ; SKIP REST?
       JZ      ISKIP
       CPI     'Q'     ; QUIT?
       JZ      QUIT
       CPI     'N'     ; NO?
       JZ      NODO
       CALL    EPRINT
       DB      '     Selected',0
       MOV     A,M     ; GET BYTE
       ORI     80H     ; SET MSB
       MOV     M,A     ; PUT BYTE
       JMP     ICKNXT

;  DON'T CRC FILE
NODO:
       CALL    EPRINT
       DB      ' NOT Selected',0

;  CONTINUE SCAN OF FILES
ICKNXT:
       LXI     D,ESIZE ; SIZE OF FILE ENTRY
       DAD     D       ; PT TO NEXT ENTRY
       DCX     B       ; COUNT DOWN
       MOV     A,B     ; DONE?
       ORA     C
       JNZ     ICKL
ISKIP:
       POP     B       ; RESTORE ORIGINAL COUNT
       POP     H       ; RESTORE PTR TO FIRST FILE
       CALL    DIRPACK ; PACK DIRECTORY BASED ON SELECTION
       CALL    EPRINT
       DB      CR,LF,'** Inspection Complete **',CR,LF,0
       RET

;
;  PROMPT USER FOR INSPECT
;
CRCQ:
       CALL    EPRINT  ; PRINT PROMPT
       DB      ' -- Select (Y/N/S/Q)? ',0
       CALL    CIN     ; GET RESPONSE
       CALL    CAPS    ; CAPITALIZE
       CALL    COUT    ; ECHO
       RET

;
;  QUIT CRC PROGRAM
;
QUIT:
       CALL    EPRINT
       DB      ' Quit to Z3',0
       JMP     DRETURN

;
;  COMPUTE CRC; NAME IN CRCFCB
;
DOIT:
       LDA     CDISK           ; GOTO DIRECTORY OF FILE
       MOV     B,A
       LDA     CUSER
       MOV     C,A
       CALL    LOGUD           ; LOG INTO FILE'S DIRECTORY
       CALL    CRCCLR          ; CLEAR CRC ACCUMULATOR
       LXI     H,0             ; HL=0
       SHLD    RECNT           ; RESET RECORD COUNT
       SHLD    LOCNT           ; RESET LINES OF CODE COUNT
       LHLD    CRCFCB          ; PT TO FCB
       XCHG                    ; ... IN DE
       CALL    INITFCB         ; INIT IT
       CALL    F$OPEN          ; OPEN IT FOR INPUT
DOITL:
       CALL    F$READ          ; READ BLOCK INTO TBUFF
       ORA     A               ; ERROR?
       JNZ     DOITD           ; DONE IF SO
       PUSH    H               ; SAVE HL
       LHLD    RECNT           ; INCREMENT RECORD COUNT
       INX     H
       SHLD    RECNT
       POP     H
       CALL    CONDIN          ; CHECK FOR ABORT
       JZ      DOITL0
       CPI     CTRLC           ; ABORT?
       JZ      ABORT           ; QUICK ABORT
DOITL0:
       LXI     H,TBUFF         ; PT TO FIRST BYTE
       MVI     B,128           ; 128 BYTES
DOITL1:
       MOV     A,M             ; GET BYTE
       CALL    CRCUPD          ; UPDATE CRC
       LDA     LOC             ; COUNT LINES OF CODE?
       ORA     A               ; 0=NO
       JZ      DOITL2
       MOV     A,M             ; GET BYTE
       ANI     7FH             ; MASK
       CPI     LF              ; LINE FEED IS KEY
       JNZ     DOITL2
       PUSH    H               ; INCREMENT LOC COUNTER
       LHLD    LOCNT
       INX     H
       SHLD    LOCNT
       POP     H
DOITL2:
       INX     H               ; PT TO NEXT
       DCR     B               ; COUNT DOWN
       JNZ     DOITL1
       JMP     DOITL           ; CONTINUE THRU FILE
DOITD:
       CALL    GETUD           ; RETURN TO HOME DIRECTORY
       CALL    DPRINT          ; SEPARATOR
       DB      ' ',0
       LHLD    RECNT           ; PRINT RECORD COUNT
       CALL    DVAL            ; PRINT IN DECIMAL
       CALL    DPRINT
       DB      '  ',0
       CALL    CRCDONE         ; RETURN CRC IN HL
       CALL    HVAL            ; PRINT VALUE AS HEX
       LDA     LOC             ; LINES OF CODE?
       ORA     A
       JZ      DOITD1
       CALL    DPRINT          ; LEADING SPACES
       DB      ' ',0
       LHLD    LOCNT           ; GET COUNT
       CALL    DVAL            ; PRINT AS DECIMAL
DOITD1:
       CALL    CTEST           ; GET FOR AND INPUT COMMENT
       LDA     COMMENT         ; CHECK FOR COMMENT AND OUTPUT IF SO
       ORA     A               ; ZERO IF ONE NOT SELECTED
       RZ
       CALL    DPRINT          ; SEPARATOR
       DB      '  ',0
       LHLD    CMTLNE  ; OUTPUT COMMENT LINE
CMTLP:
       MOV     A,M             ; GET CHAR
       ORA     A               ; EOL?
       RZ                      ; EXIT WHEN DONE
       CALL    DPOUT           ; OUTPUT CHAR
       INX     H               ; PT TO NEXT
       JMP     CMTLP

;
;  OUTPUT CHAR TO CONSOLE AND OPTIONALLY PRINTER OR DISK
;
DOUT:
       PUSH    PSW     ; SAVE CHAR
       PUSH    B       ; SAVE BC
       MOV     B,A     ; CHAR IN B
       CALL    COUT    ; OUTPUT TO CONSOLE
DOUT0:
       LDA     PRTOUT  ; PRINTER OUTPUT?
       ORA     A       ; Z=NO
       JZ      DOUT1
       MOV     A,B     ; GET CHAR
       CALL    LOUT    ; OUTPUT TO PRINTER
DOUT1:
       LDA     DSKOUT  ; DISK OUTPUT?
       ORA     A       ; Z=NO
       JZ      DOUT2
       MOV     A,B     ; GET CHAR
       CALL    F0$PUT  ; OUTPUT TO DISK
DOUT2:
       POP     B       ; RESTORE REGS
       POP     PSW
       RET

;
;  OUTPUT CHAR TO OPTIONALLY PRINTER OR DISK
;
DPOUT:
       PUSH    PSW     ; SAVE CHAR
       PUSH    B       ; SAVE BC
       MOV     B,A     ; CHAR IN B
       JMP     DOUT0   ; USE DOUT ROUTINES

;
;  OUTPUT CHARS PTED TO BY RET ADR TO CONSOLE AND DISK OR PRINTER
;
DPRINT:
       XTHL            ; GET PTR AND SAVE HL AT SAME TIME
DPRL:
       MOV     A,M     ; GET CHAR
       INX     H       ; PT TO NEXT
       ORA     A       ; END?
       JZ      DPRL1
       CALL    DOUT    ; OUTPUT IT
       JMP     DPRL
DPRL1:
       XTHL            ; SET RET ADR AND RESTORE HL
       RET

;
;  NEW LINE TO ALL
;
DCRLF:
       PUSH    PSW     ; SAVE PSW
       MVI     A,CR    ; NEW LINE
       CALL    DOUT
       MVI     A,LF
       CALL    DOUT
       POP     PSW     ; RESTORE PSW
       RET

;
;  OUTPUT VALUE IN HL TO ALL IN HEX
;
HVAL:
       PUSH    H       ; SAVE HL
       PUSH    D       ; SAVE DE
       LXI     D,NUMBUF        ; PT TO NUMBER BUFFER
       MOV     A,H
       CALL    MA2HC   ; OUTPUT IN HEX
       MOV     A,L
       CALL    MA2HC
       MVI     A,' '   ; TRAILING SPACE
       STAX    D
       JMP     DVAL0

;
;  OUTPUT HL AS UP TO 5 DECIMAL DIGITS TO ALL
;
DVAL:
       PUSH    H       ; SAVE REGS
       PUSH    D
       LXI     D,NUMBUF        ; PT TO BUFFER
       CALL    MHLDC   ; OUTPUT IN DECIMAL
DVAL0:
       LXI     H,NUMBUF        ; PT TO BUFFER
       MVI     D,5     ; 5 CHARS
DVAL1:
       MOV     A,M     ; GET CHAR
       INX     H       ; PT TO NEXT
       CALL    DOUT    ; OUTPUT IT
       DCR     D       ; COUNT DOWN
       JNZ     DVAL1
       POP     D       ; RESTORE REGS
       POP     H
       RET

;
;  **** START OF CRC ROUTINES ****
;

;
;  CRCCLR -- Clear CRC Accumulator
;
;  No Registers are Affected
;
CRCCLR:
       PUSH    H       ;SAVE HL
       LXI     H,0     ;INIT TO ZERO
       SHLD    CRCACC
       POP     H
       RET

;
;  CRCDONE -- Return the CRC Value in HL
;
CRCDONE:
       LHLD    CRCACC  ;GET VALUE
       RET


;
;  CRCUPD -- Update CRC Accumulator
;
;An 8080 routine for generating a CYCLIC-REDUNDANCY-CHECK.
;Adapted from Keith Petersen's CRCK 4.2 program.
;By Fred Gutman.
;From 'EDN' magazine, June 5, 1979 issue, page 84.
;
;  Byte to be updated is passed in A
;  No Registers are Affected
;
CRCUPD:
       PUSH    H       ;SAVE HL
       PUSH    B       ;SAVE BC
       PUSH    PSW     ;SAVE BYTE TO UPDATE
       MOV     B,A     ;BYTE IN B
       LHLD    CRCACC  ;GET REMAINDER
       MOV     A,H
       ANI     128     ;Q-BIT MASK
       PUSH    PSW     ;SAVE STATUS
       DAD     H       ;2 X R(X)
       MOV     A,B     ;GET BYTE
       ADD     L
       MOV     L,A
       POP     PSW
       JZ      CRCU1   ;IF Q-BIT IS ZERO
;
       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
;
CRCU1:
       SHLD    CRCACC  ;SAVE RESULT
       POP     PSW     ;RESTORE REGS
       POP     B
       POP     H
       RET

;
;  CRC Accumulator
;
CRCACC:
       DS      2       ;2 BYTES

;
;  **** END OF CRC ROUTINES ****
;

;
;  BUFFERS
;
CDISK:
       DS      1       ; DISK WHERE FILES ARE
CUSER:
       DS      1       ; USER WHERE FILES ARE
LOC:
       DS      1       ; LINES OF CODE FLAG (0=NO, 0FFH=YES)
INSPECT:
       DS      1       ; INSPECT FLAG (0=NO, 0FFH=YES)
COMMENT:
       DS      1       ; CONTROL FLAG (0=NO, 0FFH=YES)
DSKOUT:
       DS      1       ; DISK OUTPUT (0=NO, 0FFH=YES)
PRTOUT:
       DS      1       ; PRINTER OUTPUT (0=NO, 0FFH=YES)
LOCNT:
       DS      2       ; LINES OF CODE COUNT
RECNT:
       DS      2       ; RECORD COUNT
NEXTCH:
       DS      2       ; PTR TO NEXT CHAR IN MULTIFILE COMMAND LINE
FILECNT:
       DS      2       ; COUNT OF NUMBER OF FILES RENAMED
NUMBUF:
       DS      5       ; NUMBER STORAGE BUFFER
DIRBUF:
       DS      2       ; PTR TO DIRECTORY BUFFER
CRCFCB:
       DS      2       ; PTR TO FCB FOR CRC
CMTLNE:
       DS      2       ; PTR TO COMMENT LINE BUFFER
CMDLNE:
       DS      2       ; PTR TO COMMAND LINE
STACK:
       DS      2       ; OLD STACK PTR

       END