home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / z3util / cr28src.lbr / COMMON28.LZB / COMMON28.LIB
Encoding:
Text File  |  1991-05-05  |  68.5 KB  |  2,438 lines

  1. ;************************************************************************
  2. ;*                                    *
  3. ;*               COMMON.LIB v2.8                *
  4. ;*                                    *
  5. ;*    This is an "include" file used in both CRUNCH and UNCRunch.    *
  6. ;*    Occasional differences are handled by conditional assembly    *
  7. ;*    (i.e., "CRUNCH" is TRUE if CRUNCH is being assembled, but    *
  8. ;*    FALSE if UNCR is being assembled).                *
  9. ;*                                    *
  10. ;*         Copyright (c) 1987 by Steven Greenberg            *
  11. ;*                                    *
  12. ;*    This file has been released with the permission of Steven    *
  13. ;*    Greenberg, the original author, who owns the copyright.        *
  14. ;*    You can distribute it AS IS or modify it for your OWN use,    *
  15. ;*    but public release of modified versions (source or object    *
  16. ;*    files) without permission is prohibited, nor can it be sold.    *
  17. ;*                                    *
  18. ;************************************************************************
  19.  
  20. ; Copy (pip) routine. All files are assumed closed on entry. The name
  21. ; of the input file should be in place in INFCB. No other assumptions
  22. ; are made. This is a no frills byte by byte copy; the main objective
  23. ; was to keep this simple by using existing routines.
  24.  
  25. COPY:    CALL    INTRAM        ; Mostly to init the i/o pointers
  26.     LD    A,(DIFDU)    ; Do not copy a file onto itself
  27.     ADD    A,0FFH
  28.     CCF
  29.     RET    C        ; If input du: = output du:, rtn w/ c set
  30.  
  31.     LD    DE,MSGCPY    ; "Copying..."
  32.     CALL    MESAG2
  33.     LD    HL,INFCB
  34.     CALL    PRNFIL        ; Type the filename being copied
  35.  
  36.     LD    DE,INFCB+12    ; Zero out the input fcb except d: & filename
  37.     CALL    CLRFC2
  38.     CALL    OPNIN        ; Open the input file
  39.     RET    C        ; Failed to open, forget it (** add msg why?)
  40.  
  41.     LD    DE,OUTFCB    ; Set up the output fcb
  42.     CALL    CLRFCB        ; First clr it
  43.     CALL    CPYNAM        ; Now copy the name from the input fcb
  44.     CALL    OPNOUT        ; Open the output file
  45.     JR    NC,IOOK        ; Br if all's ok so far
  46.     CALL    CLSIN        ; Else close the input file and return
  47.     SCF            ; (indicates no copy took place)
  48.     RET
  49.  
  50. IOOK:    LD    A,'$'        ; Set this flag to "$" (convenient later)
  51.     LD    (DIRFLG),A    ; (non-zero val indicates doing "direct" copy)
  52.     LD    A,(QUIFM)
  53.     OR    A
  54.     CALL    Z,CRLF        ; Do an extra CRLF in "quiet" mode here
  55.  
  56. XFERLP:    CALL    GETBYT        ; }
  57.     JR    C,XFRDUN    ; } Main copying loop.
  58.     CALL    OUTB        ; } Get bytes and output them till done.
  59.     JR    XFERLP        ; }
  60.  
  61. XFRDUN:    CALL    DONE        ; Flush the output buffer
  62.     CALL    CLSOUT        ; Close input and output files
  63.     CALL    CLSIN
  64.  
  65.     AND    A        ; Guarantee clr carry for successful return
  66.     RET
  67.  
  68. ;................................
  69.  
  70. CPYNAM:    LD    HL,INFCB+1    ; Copies filename from input fcb to output fcb
  71.     LD    DE,OUTFCB+1
  72.     LD    B,11        ; Char count
  73.  
  74. LDRLP2:    LD    A,(HL)        ; }
  75.     AND    7FH        ; }
  76.     LD    (DE),A        ; } Like LDIR, but strip hi-bit
  77.     INC    HL        ; }
  78.     INC    DE        ; }
  79.     DJNZ    LDRLP2        ; }
  80.  
  81.     RET
  82.  
  83. ;-----------------------------------------------------------------------
  84. ;
  85. ; Tag (sweep) mode code. Go thru the expanded wildcard filname list,l
  86. ; allowing the user to tag individual files.
  87.  
  88. TAG:    LD    DE,MSGTAG    ; Instructions for tagging files
  89.  
  90. RESTRT:    CALL    MESAGE        ; Come back here if he wants to try again
  91.  
  92.     LD    HL,0
  93.     LD    (FILNUM),HL    ; Which file number we're on. Init to zero.
  94.     LD    HL,FNBUFF    ; Buffer containing all the filenames
  95.  
  96. TAGLP:    PUSH    HL
  97.     LD    HL,(FILNUM)    ; Incr file number each time thru loop
  98.     INC    HL
  99.     LD    (FILNUM),HL    ; (a maximum of 255 filnames are allowed)
  100.     POP    HL
  101.  
  102.     LD    D,H        ; Keep a copy of ptr to this filename in DE
  103.     LD    E,L
  104.     LD    A,(HL)        ; The first byte is a flag, next 11 are chars
  105.     OR    A        ; Get the files status (tagged / untagged)
  106.     JP    M,TDUN        ; If msb set, must be "FF" (end of list flag)
  107.     PUSH    AF        ; Else save zero / non-zero status
  108.  
  109. ;...............................
  110.  
  111.     PUSH    BC        ; Type out the filename's number,
  112.     PUSH    DE        ; Followed by a period & space.
  113.     PUSH    HL
  114.     LD    HL,(FILNUM)
  115.     CALL    DECOUT
  116.     LD    A,'.'
  117.     CALL    TYPE
  118.     LD    A,' '
  119.     CALL    TYPE
  120.     POP    HL        ; (DECOUT wrecks all the registers)
  121.     POP    DE
  122.     POP    BC
  123.  
  124. ;...............................
  125.  
  126.     INC    HL        ; Move to first filename char position
  127.     LD    B,8        ; Spec 8 chars to be typed
  128.     CALL    PCHRS        ; Do that
  129.     LD    A,'.'        ; Follow that w/ a period
  130.     CALL    TYPE
  131.     LD    B,3
  132.     CALL    PCHRS        ; Now type the three ext chars of the filename
  133.     LD    A,":"        ; Follow that with a colon.
  134.     CALL    TYPE
  135.     POP    AF        ; Get stat back
  136.     JR    Z,NOSTAR    ; Br if not already tagged
  137.  
  138. ;.......................................................................
  139. ;
  140. ; Get user response. This code for a filename which is already tagged
  141.  
  142.     LD    A,'*'        ; Already tagged, so type a "*"
  143.     CALL    TYPE
  144.     CALL    RESPT        ; Get user's response
  145.     CP    'U'        ; Untag?
  146.     JR    NZ,CKBACK    ; If not, leave it alone (but go check for 'b')
  147.  
  148. ;................................
  149.                 ; "Untag" a filename. Overwrite the "*",
  150.     LD    A,BS        ; Already on the screen, with
  151.     CALL    TYPE        ; Destructive backspace.
  152.     LD    A,' '
  153.     CALL    TYPE
  154.     XOR    A
  155.     JR    PUTTAG        ; And go zero out the tag
  156.  
  157. ;.......................................................................
  158. ;
  159. ; Get user response. This code for a filename which is NOT already tagged
  160.  
  161. NOSTAR:    CALL    RESPT        ; Get user response
  162.     CP    'T'        ; Tag it?
  163.     JR    NZ,CKBACK    ; No, leave it (but go check for 'b')
  164.     LD    A,'*'        ; Yes, tag the file
  165.     CALL    TYPE
  166.     LD    A,01H        ; "01" for tagged files ("00" = untagged)
  167.  
  168. PUTTAG:    LD    (DE),A        ; Set the flag byte as "tagged" or "untagged"
  169. LEAVIT:    CALL    CRLF        ; (entry here leaves it the way it was)
  170.     JR    TAGLP        ; Loop to next file
  171.  
  172. ;.......................................................................
  173. ;
  174. ; Check if user issued the "B" ("back one file") command and process it
  175. ; if so
  176.  
  177. CKBACK:    CP    'B'        ; Did he type "B"?
  178.     JR    NZ,LEAVIT    ; No, leave file the way it was and move on
  179.  
  180.     PUSH    HL
  181.     LD    HL,(FILNUM)    ; Yes, move back one file
  182.     DEC    HL        ; Decrement the file number counter
  183.     LD    A,L
  184.     LD    D,H
  185.     OR    D
  186.     JR    NZ,BKUPOK    ; We will not allow backing up past file #1
  187.     POP    HL        ; clean up stack
  188.     LD    DE,MSGBEL    ; So beep if he tries that
  189.     JP    RESTRT
  190.  
  191. BKUPOK:    DEC    HL        ; Decr again to make up for the upcoming incr
  192.     LD    (FILNUM),HL
  193.     POP    HL
  194.     LD    DE,-24        ; Also decr the filname pointer "twice"
  195.     ADD    HL,DE        ; (ie 2 x 12 bytes per filename w/ flag byte)
  196.     CALL    CRLF
  197.     JR    LEAVIT        ; And continue...
  198.  
  199. ;.......................................................................
  200. ;
  201. ; Done with tagging process for all files (hopefully, but we will allow the
  202. ; user to reconsider). If he's happy, then return.
  203.  
  204. TDUN:    LD    DE,MSGOK    ; "Selections OK? (Y/N):"
  205.     CALL    MESAGE
  206.  
  207. TRYAGN:    CALL    RESPT        ; Get his response
  208.     LD    DE,MSGCLF    ; CR/LF/LF
  209.     CP    'N'        ; Was it "no"?
  210.     JP    Z,RESTRT    ; If so, restart
  211.     CP    'Y'        ; Was it "Yes"?
  212.     JR    Z,ALRITE    ; Br if so.
  213.     LD    A,BELL        ; He must answer "Y "or "N" to this; no default
  214.     CALL    TYPE        ; So beep at him and let him answer again
  215.     JR    TRYAGN
  216.  
  217. ALRITE:    LD    A,'Y'        ; Simulated "Y" echo
  218.     CALL    TYPE        ; That's all. Return to main code with "flag"
  219.     CALL    CRLF
  220.     RET            ; Bytes for filenames appropriately set.
  221.  
  222. ;...............................
  223.  
  224. PCHRS:    LD    A,(HL)        ; Aux routine to type "B" chars from (HL)
  225.     AND    7FH
  226.     INC    HL
  227.     CALL    TYPE
  228.     DJNZ    PCHRS
  229.     RET
  230.  
  231. ;-----------------------------------------------------------------------
  232. ;
  233. ; Get a user response using direct BIOS to avoid echoing the character.
  234. ; Check for and process a ^C if one is detected.
  235.  
  236. RESPT:    CALL    DIRCIO        ; Direct console i/o via bios, no echo
  237.     AND    7FH        ; Just in case
  238.     CP    CTRLC        ; ^C ?
  239.     JR    NZ,NCTC        ; Br if not
  240.     LD    DE,ABORT    ; If so, det up "aborted" message
  241.     JP    FATAL        ; And abort
  242.  
  243. NCTC:    AND    0DFH        ; Else perform a cheap and dirty upcase
  244.     RET            ; On his response and return it in A.
  245.  
  246. ;-----------------------------------------------------------------------
  247.  
  248. DIRCIO:    PUSH    BC        ; Routine does a direct BIOS console input
  249.     PUSH    DE        ; Call, and returns w/ registers intact.
  250.     PUSH    HL
  251.     LD    HL,(0001)    ; Get addr of bios jump table (+3)
  252.     LD    DE,6        ; Additional offset to function 3, conin
  253.     ADD    HL,DE
  254.     CALL    JPHL
  255.     POP    HL
  256.     POP    DE
  257.     POP    BC
  258.     RET
  259.  
  260. JPHL:    JP    (HL)        ; Jump to it, return direct from there to
  261.                 ; The POP HL instruction above.
  262.  
  263. ;-----------------------------------------------------------------------
  264. ;    Command tail parsing, Wildcard expansion, other startup stuff
  265. ;-----------------------------------------------------------------------
  266.  
  267. STRTUP:    LD    A,(BDOS+2)    ; Size up the tpa
  268.     SUB    ENDHI+11    ; (includes 2k+ for the ccp)
  269.     JR    C,INSUFF    ; Not enough memory at all
  270.     CP    4        ; Chk if reasonable additional amt for out bfr
  271.     JR    NC,ENOUGH    ; Ok, go compute an output buffer size
  272. INSUFF:    LD    DE,LAKMEM    ; "not enough memory..."
  273.     LD    HL,0        ; zero-out number of files processed
  274.     LD    (NFP),HL
  275.     JP    FATAL        ; (fatal error)
  276.  
  277. ;.......................................................................
  278.  
  279. ENOUGH:    CP    64        ; Clamp output bfr size to 64 page (16k) max
  280.     JR    C,NOCLMP
  281.     LD    A,64        ;
  282. NOCLMP:    LD    (OBSZ),A    ; Output buffer size, in pages
  283.     ADD    A,OBUFHI    ; Add ofset to beg of output bfr, hi
  284.     LD    (EOBHI),A    ; And save that here
  285.  
  286. ;.......................................................................
  287. ;
  288. ; If this is ZCPR3, we can get the name we call ourself from the external
  289. ; file control block.  If COMNAM is not spaces, we must be running from
  290. ; the GO command, so we've already got the name.
  291.  
  292.     LD    HL,(Z3ED)    ; print program name
  293.     LD    A,L
  294.     OR    H        ; is there an environment address?
  295.     JR    Z,SKPNAM    ; (no, so forget it)
  296.     EX    DE,HL        ; save env address in DE
  297.     LD    HL,COMNAM    ; point to COMNAM storage
  298.     LD    A,(HL)
  299.     CP    ' '        ; anything there?
  300.     JR    NZ,SKPNAM    ; (yes, don't do it again)
  301.     LD    HL,36        ; offset to address of external FCB
  302.     ADD    HL,DE
  303.     LD    E,(HL)        ; get address into DE
  304.     INC    HL
  305.     LD    D,(HL)
  306.     LD    A,E
  307.     OR    D
  308.     JR    Z,SKPNAM    ; (no address, no external FCB)
  309.     EX    DE,HL
  310.     INC    HL
  311.     LD    DE,COMNAM    ; point to COMNAM storage
  312.     LD    BC,8
  313.     LDIR            ; move name
  314.  
  315. ;.......................................................................
  316.  
  317. SKPNAM:    LD    A,(QUIFL)    ; Move patches to data area for flag use
  318.     LD    (QUIFM),A    ; (allows the program to be re-executable
  319.     LD    A,(NPROFL)    ; - even if the patch corresponds to a
  320.     LD    (NPROFM),A    ; - command line option)
  321.     LD    A,(TRBOFL)
  322.     LD    (NOMSFM),A
  323.     LD    A,(CNFRFL)
  324.     LD    (CNFRFM),A
  325.     LD    A,(SYSFL)
  326.     LD    (SYSFM),A
  327.  
  328.   IF CRUNCH    ; (this patch / flag only applicable to CRUNCH)
  329.     LD    A,(ARCHIV)
  330.     LD    (ARCHVM),A
  331.   ENDIF    ; CRUNCH
  332.  
  333.     XOR    A        ; Make sure the "stamp" defaults to a leading 0
  334.     LD    (STAMP+0),A
  335.     LD    (NFP),A        ; Init # of files processed to zero
  336.     LD    (NFP+1),A
  337.  
  338. ;.......................................................................
  339. ;
  340. ; Four user # variables are used:  USERNO is the original, saved for re-
  341. ; storation before exit.  CURUSR is the currently "logged" user, INUSR
  342. ; contains the input file's user code; OUTUSR is the output's.    Both are
  343. ; defaulted to USERNO.    Routines LOGIN and LOGOUT log to appropriate user
  344. ; areas when called.  Unnecessary BDOS 'set user area' calls are inhibi-
  345. ; ted at all times, for what it's worth.
  346.  
  347.     CALL    GETUSR        ; Get user # guy started with
  348.     LD    A,(USERNO)    ; (above routine put the number here)
  349.     LD    (CURUSR),A    ; Define this as the "current" user #
  350.     LD    (INUSR),A    ; And the default user for both input & output
  351.     LD    (OUTUSR),A
  352.  
  353.   IF NOT ZSYS
  354.  
  355. ; If the ZCPR environment descriptor address is non-zero, go use
  356. ; ZCPR-specific command tail processing, else use regular
  357.  
  358.     LD    HL,(Z3ED)    ; Get the environment descriptor
  359.     LD    A,H
  360.     OR    L        ; If 0000, program was not installed by Z3INS
  361.     JR    NZ,ZCPR        ; ..or loaded by Z33+ CPR
  362.  
  363. ;.......................................................................
  364. ;
  365. ; Non-ZCPR command tail processing.  Here we are limited by PARSEFCB
  366. ; to users 0 to 15.
  367.  
  368.     CALL    GTOPTS        ; Get & process any "slash" options
  369.  
  370.     LD    HL,2000H    ; Init outfcb to default drive & 1 blank char
  371.     LD    (OUTFCB+0),HL
  372.  
  373.     LD    DE,DDMA+1    ; Beg of string to be parsed
  374.     LD    HL,INFCB    ; 37 byte fcb, where fcb-1 will have user #
  375.     CALL    PARSEU        ; Parse. (note- 'fcb'-1 is 'inusr')
  376.  
  377.     PUSH    HL        ; Save command line pointer
  378.     LD    IX,INFCB    ; Spec fcb for "CHKVLD" call below.
  379.     CALL    CHKVLD        ; Check validity of drive / user (saves HL)
  380.     LD    A,(INFCB+1)    ; Make sure we have a non-blank filename
  381.     CP    ' '
  382.     JP    Z,GIVUSG    ; Give usage & exit
  383.     CALL    AUX1        ; Aux processing handles special delimiters
  384.     POP    DE        ; Get back command line pointer, pushed as HL
  385.     JR    C,DONE1        ; Aux1 rtns w/ carry set if cmnd tail is dun
  386.  
  387.     LD    HL,OUTFCB    ; New fcb to be filled
  388.     CALL    PARSEU        ; Do it.
  389.     LD    IX,OUTFCB    ; Spec for "chkvld"
  390.     CALL    CHKVLD        ; Check validity of "OUTFCB"
  391.     CALL    AUX1        ; As above
  392.  
  393.     LD    A,(OUTFCB+1)    ; Additional check- 2nd filename should be blnk
  394.     CP    ' '
  395.     JR    Z,DONE1
  396.  
  397.     LD    DE,PRSER5    ; Error if not
  398.     JP    FATALU
  399.  
  400.   ENDIF    ; NOT ZSYS
  401.  
  402. ;.......................................................................
  403. ;
  404. ; ZCPR3 command tail processing.
  405.  
  406. ZCPR:    LD    HL,DFCB+1    ; Input file spec will come from default fcb1
  407.     LD    A,(HL)        ; But first check for zcpr help invocation
  408.     CP    '/'
  409.     JP    Z,GIVUSG    ; If so, give usage and exit
  410.     CP    ' '        ; No filename spec'd req's help also
  411.     JP    Z,GIVUSG
  412.  
  413.     DEC    HL        ; Else set to beg of dfcb1
  414.     LD    DE,INFCB    ; The input fcb
  415.     CALL    CLRFCB        ; Init it to blanks and zeroes
  416.     LD    BC,16        ; Copy drive, filename, user, et al
  417.     LDIR            ; Now the input fcb is set up, but...
  418.  
  419.     LD    A,(DFCB+13)    ; Get the system supplied user # into the
  420.     LD    (INUSR),A    ; - byte where the program expects it
  421.     LD    A,(DFCB+15)    ; check for invalid directory
  422.     OR    A
  423.     JP    NZ,RETER9    ; (yep)
  424.  
  425.     LD    A,(DFCB2+13)    ; Similarly for the output file
  426.     LD    (OUTUSR),A    ; Goes there
  427.     LD    A,(DFCB2+15)    ; check for invalid directory
  428.     OR    A
  429.     JP    NZ,RETER9    ; (it is)
  430.  
  431.     LD    A,(DFCB2+0)    ; Output drive spec stays here.
  432.     LD    (OUTFCB+0),A    ; Rest of fcb filled in later, for each file.
  433.  
  434.     LD    HL,DDMA        ; Look for "[...]" stamp
  435.     LD    C,(HL)
  436.     LD    B,0        ; # of chars to search
  437.     LD    A,'['        ; Char to search for
  438.     CPIR
  439.     DEC    HL        ; Move back to match point, if any
  440.     LD    A,B        ; Was there a match?
  441.     OR    C
  442.     CALL    NZ,PRCSTM    ; (misses if "[" was last char, but that's ok)
  443.  
  444.     CALL    GTOPTS        ; Get and process any "slash options"
  445.  
  446. ; Continue w/ "DONE1" below...
  447. ;
  448. ;.......................................................................
  449. ;
  450. ; More preliminaries. Set the "difdu" flag (clear IFF input drive AND
  451. ; user are identical, else set).  Determine if multi-sector I/O is in-
  452. ; dicated; type program intro to console; expand ambiguous wildcard
  453. ; filespecs.
  454.  
  455. DONE1:    LD    A,(INFCB+0)    ; Input drive
  456.     OR    A
  457.     JR    NZ,NTDEF1    ; Br if not default
  458.     LD    A,(DEFDRV)    ; If default, use the default drive spec
  459. NTDEF1:    LD    (IDSPEC),A    ; Actual input drive spec, for later ref
  460.     LD    B,A        ; Put that there
  461.     LD    A,(OUTFCB+0)    ; As above for output drive
  462.     OR    A
  463.     JR    NZ,NTDEF2
  464.     LD    A,(DEFDRV)
  465. NTDEF2:    LD    (ODSPEC),A
  466.     CALL    CNVEC        ; (cnv to a vec, in "odrvec"  for later use)
  467.     XOR    B        ; B now non-zero if drives are different
  468.     LD    (DIFD),A    ; Save that flag for possible later use
  469.     LD    B,A        ; Put a copy aside for a sec
  470.     LD    A,(INUSR)    ; Input user #
  471.     LD    C,A
  472.     LD    A,(OUTUSR)    ; Output user #
  473.     XOR    C        ; Non zero if different
  474.     OR    B        ; A now zero iff drives and user #'s identical
  475.     LD    (DIFDU),A    ; Goes there for possible future reference
  476.  
  477.     LD    A,'?'        ; Set wldflg if prgm invoked w/ any wildcards
  478.     LD    HL,INFCB+1
  479.     LD    BC,11
  480.     CPIR
  481.     JR    Z,YESWLD    ; Br if "?" found in any of the filename chars
  482.     XOR    A        ; Else zero A
  483. YESWLD:    LD    (WLDFLG),A    ; Flag now either 0 or '?' (arbitrary non-0 #)
  484.  
  485.     XOR    A
  486.     LD    (ZSDSFL),A    ; default to non-ZSDOS, no date stamp
  487.     LD    A,(NOMSFM)    ; set multi-sec i/o default
  488.     CPL            ; ..according to flag
  489.     LD    (CPM3FL),A
  490.  
  491.     LD    C,GETVER    ; Get CP/M version #
  492.     CALL    BDOS        ; Will return result in l
  493.     LD    A,30H-1
  494.     CP    L        ; 3.0 or greater?
  495.     JR    C,NODSTP    ; Yes, don't reset flag
  496.     XOR    A
  497.     LD    (CPM3FL),A    ; Else reset it
  498.     LD    C,EXDOSV    ; get extended DOS version, if any
  499.     CALL    BDOS
  500.     LD    A,H        ; ZSDOS?
  501.     CP    'S'
  502.     JR    Z,DODSTP    ; (yes)
  503.     CP    'D'
  504.     JR    NZ,NODSTP    ; (no, no date stamp)
  505. DODSTP:    LD    (ZSDSFL),A
  506. NODSTP:    LD    DE,INTRO    ; Version #, etc.
  507.     CALL    MESAG2        ; Type that to console
  508.  
  509.     CALL    LOGIN        ; Log to the input files's user area
  510.  
  511.   IF NOT CRUNCH
  512.     CALL    FIXFCB        ; Uncr may convert ? in middle of ext to "Z"
  513.   ENDIF    ; NOT CRUNCH
  514.  
  515.     LD    DE,INFCB    ; Spec input fcb for below call
  516.     CALL    WILDEX        ; Perform wildcard expansion
  517.     JR    NZ,SOME        ; Br if any matches at all (subr set z flag)
  518.  
  519.     LD    DE,ERR1        ; No matches- "Input file not found"
  520.     JP    FATAL
  521.  
  522. SOME:    CALL    SORT        ; Sort the file list
  523.     LD    A,(CNFRFM)    ; Confirm flag set?
  524.     OR    A
  525.     CALL    NZ,TAG        ; If so, go thru the tagging procedure
  526.     CALL    EXCLUD        ; In any event, "exclude" designated filetypes
  527.  
  528.     LD    HL,FNBUFF    ; Init this pointer to 1st matching filename
  529.     LD    (BUFPTR),HL    ; (advances as we work on each file)
  530.     RET            ; This completes all the common preliminaries
  531.  
  532. ;-----------------------------------------------------------------------
  533. ;    Support subroutines for above
  534. ;-----------------------------------------------------------------------
  535.  
  536. ;.......................................................................
  537. ;
  538. ; Get and process one or two options.  The options are the last item in
  539. ; the command tail, and must be preceded by a space and slash i.e., al-
  540. ; low slashes in filenames.  If found, zero out the slash so it becomes
  541. ; the effective end of the command tail before doing the real parsing.
  542.  
  543. GTOPTS:    LD    A,(DDMA)    ; Get # of chars in command tail
  544.     OR    A        ; None?
  545.     RET    Z        ; Return if so
  546.  
  547.     LD    B,A        ; (will be used as loop limiter below)
  548.     ADD    A,DDMA        ; Add offset to beg of command tail
  549.     LD    L,A        ; Put result in HL
  550.     LD    H,0        ;
  551.     LD    A,' '        ; Now eliminate trailing blanks
  552.  
  553. BLNKLP:    CP    (HL)        ; Blank?
  554.     JR    NZ,LSTCHR    ; Br out at last real char
  555.     DEC    HL        ;
  556.     DJNZ    BLNKLP        ; ("B" still has length of cmnd tail)
  557.     RET            ;
  558.  
  559. LSTCHR:    LD    C,1        ; # of options to process counter (increments)
  560.  
  561. ;...............................
  562.  
  563. SLSHLP:    DEC    HL        ; Next to last char (1st loop)
  564.     LD    A,(HL)
  565.     CP    '/'        ; Slash?
  566.     JR    NZ,NSLASH    ; Br if not
  567.  
  568.     DEC    HL
  569.     LD    A,(HL)
  570.     CP    ' '
  571.     INC    HL
  572.     JR    Z,DOWOPS
  573.  
  574. NSLASH:    INC    C        ; Incr # of options counter
  575.     LD    A,C
  576.     CP    5+1        ; Past max # of options supported?
  577.     RET    NC        ; If so, forget it
  578.     DJNZ    SLSHLP        ; Else keep checking, if there's still chars
  579.  
  580. ;...............................
  581.  
  582.     RET            ; Return on loop fall thru
  583.  
  584. DOWOPS:    LD    B,C        ; # of options to process
  585.     LD    (HL),0        ; First, zero out the slash
  586.  
  587. WOPLP:    INC    HL        ; Now pointing to first (or only) option
  588.     CALL    PRCOPT        ; Process it
  589.     DJNZ    WOPLP        ; Possibly process more options
  590.     RET
  591.  
  592. ;.......................................................................
  593. ;
  594. ; Process a single letter option pointed to by HL.  The existance of a
  595. ; switch on the command always toggles the user defined default for that
  596. ; option.  In the distribution version of the program, all default to
  597. ; zero.
  598.  
  599. PRCOPT:    LD    A,(HL)        ; Get the letter
  600.     EX    DE,HL        ; Save HL in DE
  601.     AND    0DFH        ; Upcase it
  602.     CP    'S'
  603.     JR    Z,SYSFIL    ; flip system file inclusion
  604.     CP    'Q'
  605.     JR    Z,QUIET        ; Flip quiet mode
  606.     CP    'I'
  607.     JR    Z,CNFRM        ; flip tag mode
  608.     CP    'T'
  609.     JR    Z,CNFRM        ; allow T instead of I for tag mode
  610.     CP    'C'
  611.     JR    Z,CNFRM        ; allow C instead of I for tag mode
  612.     CP    'E'
  613.     JR    Z,OVRWRT    ; flip overwrite without prompt mode
  614.     CP    'O'
  615.     JR    Z,OVRWRT    ; allow O instead of E for overwrite mode
  616.  
  617.   IF CRUNCH    ; Archive mode option only supported by CRUNCH
  618.     CP    'A'
  619.     JR    Z,ARCH        ; Flip archive bit mode
  620.   ENDIF    ; CRUNCH
  621.  
  622.     LD    DE,PRSER4    ; Else option is bad, guy needs help
  623.     JP    FATALU
  624.  
  625. SYSFIL:    LD    HL,SYSFM    ; point to system file inclusion flag
  626.     JR    FLPOPT        ; flip it
  627.  
  628. QUIET:    LD    HL,QUIFM    ; Point to quiet mode flag
  629.     JR    FLPOPT        ; Go flip option
  630.  
  631. CNFRM:    LD    HL,CNFRFM    ; Likewise, confirm (tag) mode flag
  632.     JR    FLPOPT
  633.  
  634.   IF CRUNCH
  635. ARCH:    LD    HL,ARCHVM    ; Likewise, confirm (tag) mode flag
  636.     JR    FLPOPT
  637.   ENDIF    ; CRUNCH
  638.  
  639. OVRWRT:    LD    HL,NPROFM    ; Prompt before overwrite flag
  640.  
  641. ;...............................
  642.                 ; Toggle the option pointed to by HL and rtn
  643. FLPOPT:    XOR    A        ; (does not assume the non-zero vals are FF)
  644.     OR    (HL)        ; Is flag now zero?
  645.     JR    Z,FIS0        ; Br if so
  646.     LD    (HL),0        ; Else zero it now
  647.     EX    DE,HL        ; Restore HL from DE (was saved there on entry)
  648.     RET            ; (HL points to option letter again)
  649.  
  650. FIS0:    LD    (HL),0FFH    ; Put ff in it if it was zero
  651.     EX    DE,HL        ; Restore HL from DE (points to option letter)
  652.     RET
  653.  
  654. ;.......................................................................
  655.   IF NOT ZSYS
  656. ;
  657. ; Check the validity of the drive and user specified.  This routine also
  658. ; a user code of "FF", returned by "PARSEFCB" when none is specified, to
  659. ; the actual value of the current user area.  Called with IX pointing to
  660. ; the FCB in question.
  661.  
  662. CHKVLD:    PUSH    HL        ; Don't clobber command line pointer
  663.     LD    A,H        ; First check for HL=ffff, the generic error
  664.     AND    L        ; - return from parsefcb
  665.     INC    A        ;
  666.     JR    Z,RETER1    ; Br if that is the case
  667.  
  668.     LD    A,(IX-1)    ; Else get the user # generated by parsefcb
  669.     CP    0FFH        ; (at fcb-1). "FF" means current user
  670.     JR    NZ,NTDEFU    ; Br if user is not "default"
  671.  
  672.     LD    A,(USERNO)    ; Else convert "FF" to actual current user #
  673.     LD    (IX-1),A    ; And stick it
  674.  
  675. NTDEFU:    LD    HL,(MAXUSR)    ; L=maximum user, H=maximum drive
  676.     INC    L        ; compare user to MAXUSR+1
  677.     CP    L
  678.     JR    NC,RETER2    ; Br if invalid
  679.  
  680.     LD    A,(IX+0)    ; user ok, now get the drive spec
  681.     INC    H        ; compare drive to MAXDRV+1
  682.     CP    H
  683.  
  684.     POP    HL        ; Restore command line pointer
  685.     RET    C        ; return if okay
  686.  
  687.     LD    DE,PRSER3    ; "invalid drive" (fatal error)
  688.     JP    FATALU
  689.  
  690. RETER2:    LD    DE,PRSER2    ; "invalid user" (nothing personal..)
  691.     JP    FATALU
  692.  
  693. RETER1:    LD    DE,PRSER1    ; "invalid argument" (illogical...)
  694.     JP    FATALU
  695.  
  696.   ENDIF    ; NOT ZSYS
  697.  
  698. ;.......................................................................
  699.  
  700. RETER9:    LD    DE,PRSER9    ; "invalid directory" (ZCPR3 only...)
  701.     JP    FATALU
  702.  
  703. ;.......................................................................
  704.   IF NOT ZSYS
  705. ;
  706. ; This routine analyzes what "PARSEFCB" stopped at.  If its the end of
  707. ; the command tail, indicate that and return.  If its a "[...]" stamp,
  708. ; process that and return.  If its just the end of the (first) filename,
  709. ; indicate that.
  710.  
  711. AUX1:    LD    A,H        ; See if "parseu" says tail is done
  712.     OR    L        ; (it does that by returning zero)
  713.     JR    Z,RTNDUN    ; Rtn w/ carry set if that is the case.
  714.  
  715.     LD    A,(HL)        ; Delim; else beg of blanks foll last filename
  716.     CP    '['        ; "stamp"?
  717.     JR    NZ,NTSTMP    ; Br if not
  718.     CALL    PRCSTM        ; If so, process stamp & rtn. we are done.
  719.  
  720. RTNDUN:    SCF            ; Flag that we are done
  721.     RET
  722.  
  723. NTSTMP:    INC    HL        ; Skip past delimiter or 1 blank & rtn
  724.     AND    A        ; (indicates 'might not be done')
  725.     RET
  726.  
  727.   ENDIF    ; NOT ZSYS
  728.  
  729. ;.......................................................................
  730. ;
  731. ; Convert the drive specified in "A" to a "drive vector" in ODRVEC.  The
  732. ; vector may be used should a disk reset become necessary.
  733.  
  734. CNVEC:    PUSH    AF        ; Save everything
  735.     PUSH    BC
  736.     PUSH    DE
  737.     LD    DE,0000H    ; Init to all zeroes
  738.     DEC    A        ; Normalize to a=0, b=1, etc
  739.     LD    B,16        ; Loop counter
  740.  
  741. VECLP:    SUB    1        ; Decr
  742.     RR    D
  743.     RR    E        ; Shift in the result of any carry
  744.     DJNZ    VECLP
  745.  
  746.     LD    (ODRVEC),DE
  747.     POP    DE        ; Restore all regs and rtn
  748.     POP    BC
  749.     POP    AF
  750.     RET
  751.  
  752. ;-----------------------------------------------------------------------
  753. ;    File I/O subroutines:  Input
  754. ;-----------------------------------------------------------------------
  755.  
  756. ;.......................................................................
  757. ;
  758. ; Open the input file whose fcb is "INFCB"
  759.  
  760. OPNIN:    CALL    LOGIN        ; Log to the input file's user area
  761.   IF CRUNCH
  762.     LD    A,(ZSDSFL)    ; is this ZSDOS?
  763.     OR    A
  764.     JR    Z,OPNIN2    ; (no, skip date stamp)
  765.     LD    DE,INFCB
  766.     LD    HL,DDMA
  767.     CALL    GETSTP        ; get date stamp
  768.     JR    NZ,OPNIN2
  769.     LD    DE,DATBUF    ; store stamp for later
  770.     LD    BC,15
  771.     LDIR
  772.     LD    A,0FFh        ; set embedded date stamp flag
  773.     LD    (DATFLG),A
  774.     LD    DE,INFCB+12
  775.     CALL    CLRFC2        ; re-initialize FCB
  776.   ENDIF    ; CRUNCH
  777. OPNIN2:    LD    DE,INFCB    ; open input file
  778.     LD    C,OPEN
  779.     CALL    BDOSAV
  780.     INC    A
  781.     AND    A        ; (clr carry for successful return)
  782.     RET    NZ        ; Return if successful
  783.  
  784.     SCF            ; Return, indicating failure
  785.     RET
  786.  
  787. ;.......................................................................
  788. ;
  789. ; Close the input file whose fcb is "INFCB".
  790.  
  791. CLSIN:    CALL    LOGIN        ; Log to the input file's user area
  792.     LD    DE,INFCB
  793.     LD    C,CLOSE
  794.     CALL    BDOSAV        ; And close it
  795.     RET
  796.  
  797. ;.......................................................................
  798. ;
  799. ; Set the input file ("INFCB") to "archived", if in the option was selected
  800.  
  801.   IF CRUNCH    ; (this routine used by CRUNCH only)
  802. ARCIT:    LD    A,(ARCHVM)    ; Check if the option was selected
  803.     OR    A
  804.     RET    Z        ; If not, just return
  805.  
  806.     LD    DE,INFCB    ; Set for bdos call
  807.     LD    HL,INFCB+11    ; Byte containing archive status
  808.     SET    7,(HL)        ; Set it
  809.     LD    C,SETATR    ; Bdos "set attribute" function
  810.     CALL    BDOSAV
  811.     RET
  812.   ENDIF    ; CRUNCH
  813.  
  814. ;.......................................................................
  815. ;
  816. ; "A" <-- Next byte from ("physical") input stream.
  817. ;      Returns with carry set on EOF.
  818.  
  819.   IF LZH
  820. GLZHUN    EQU    $        ; entry for UNLZH module
  821.   ENDIF    ; LZH
  822. GETCHR:
  823. GETBYT:    EXX            ; Switch to i/o regs
  824.     LD    A,L        ; Pointer to next avail char
  825.     SLA    A        ; See if 00h or 80h
  826.     OR    A        ; (init carry flag [rtn stat] to clear)
  827.     CALL    Z,POSRLD    ; "possibly reload" the buffer if 00 or 80H
  828.     LD    A,(HL)        ; Get byte to return (garbage if eof)
  829.     INC    HL        ; Advance input pointer
  830.     EXX            ; Back to normal regs & rtn
  831.     RET
  832.  
  833. ;................................
  834.  
  835. POSRLD:                ; "possibly reload" the input buffer
  836.                 ; I/o regs are active
  837.     LD    A,(SECNT)    ; Decr sector count (for this buffer)
  838.     DEC    A
  839.     LD    (SECNT),A
  840.     AND    A        ; (clr carry)
  841.     CALL    Z,RELOAD    ; Reload buffer if empty (resets HL)
  842.     RET    C        ; (also sets carry if eof is encountered)
  843.     CALL    PROGI        ; Incr # of recs read
  844.     AND    A        ; Guarantee clr carry if not eof yet
  845.     RET
  846.  
  847. ;.......................................................................
  848. ;
  849. ; Reload  the input buffer, & reset HL' to point to the beginning of
  850. ; it.  Assumes input BFR starts page boundary and is of page multiple
  851. ; length.  The I/O registers are active.
  852.  
  853. RELOAD:    PUSH    BC
  854.     PUSH    DE
  855.  
  856.     CALL    LOGIN        ; Log to the input file user area
  857.  
  858.     LD    B,IBUFSZ    ; Loop counter, buffer length in pages
  859.     LD    DE,IBUF        ; Beg of buffer
  860.     LD    L,0        ; Will count sectors actually read
  861.  
  862.     LD    A,(CPM3FL)    ; See if multi-sector i/o is desired
  863.     OR    A
  864.     JP    NZ,MSECI    ; Br if so, else continue w/ conventional
  865.  
  866. RLDLP:    LD    E,0        ; Lo byte of current dma
  867.     CALL    RDSEC        ; Read in 128 bytes (1/2 page)
  868.     JR    NZ,RLDRTN    ; (return if eof enecountered)
  869.     INC    L        ; Incr "sectors read" count
  870.     LD    E,80H        ; To read in the next half page
  871.     CALL    RDSEC        ; Do that
  872.     JR    NZ,RLDRTN    ; As above
  873.     INC    L
  874.     INC    D        ; Next page
  875.     DJNZ    RLDLP        ; Loop till done
  876.  
  877. RLDRTN:    LD    A,L        ; Put count of sectors read into "secnt"
  878.  
  879. RLDRT2:    LD    (SECNT),A
  880.     POP    DE        ; Restore regs
  881.     POP    BC        ;
  882.     AND    A        ; Return w/ clr carry
  883.     JR    Z,ZEREAD    ; Br if # of sectors read was zero
  884.  
  885.     LD    HL,IBUF        ; Reset input pointer to beg of input buffer
  886.     RET            ; Rtn with carry clr (from "and" instr)
  887.  
  888. ZEREAD:    SCF            ; Set flg indicating no sectors were read (eof)
  889.     RET
  890.  
  891. ;.......................................................................
  892. ;
  893. ; Multi sector I/O refill buffer routine.  Fills whole buffer at once.
  894.  
  895. MSECI:    LD    C,SETDMA    ; De already contains pntr to beg of input bfr
  896.     CALL    BDOSAV        ;
  897.  
  898.     LD    E,IBUFSZ*2    ; Spec multi sector count (secs = 2 x pages)
  899.     LD    C,SETMS        ; Bdos func #
  900.     CALL    BDOSAV        ;
  901.  
  902.     LD    DE,INFCB    ; Input file fcb
  903.     LD    C,READ        ;
  904.     CALL    BDOSAV        ; Fill it up!
  905.     OR    A        ; Did it fill all the way up?
  906.     JR    NZ,DIDNOT    ; Br if it didn't
  907.  
  908.     LD    A,IBUFSZ*2    ; If it did, then put the full # here & cont.
  909.     JR    RLDRT2        ; (rest is same as above)
  910.  
  911. DIDNOT:    LD    A,(BDOSHL+1)    ; Get the value bdos returned in h (# read)
  912.     JR    RLDRT2        ; (rest is same as above)
  913.  
  914. ;.......................................................................
  915. ;
  916. ; Subr for [ non multi-] reload, reads 128 bytes to memory starting at DE
  917.  
  918. RDSEC:    PUSH    DE        ; Save DE before clobbering it with fcb
  919.     LD    C,SETDMA    ; Set dma to val in DE
  920.     CALL    BDOSAV
  921.     LD    DE,INFCB    ; Input fcb
  922.     LD    C,READ
  923.     CALL    BDOSAV        ; Read a record
  924.     POP    DE        ; Restore DE to value on entry
  925.     OR    A        ; Set zero flag based on error val rtn'd in "a"
  926.     RET            ; & rtn
  927.  
  928. ;-----------------------------------------------------------------------
  929. ;    File I/O subroutines:  Output
  930. ;-----------------------------------------------------------------------
  931.  
  932. ;.......................................................................
  933. ;
  934. ; Open the output file.  Also type an arrow, followed by it's name.
  935.  
  936. OPNOUT:    CALL    LOGOUT        ; Log to the output user #
  937.     LD    DE,ARROW    ; Print " ---> "
  938.     LD    A,(CPM3FL)    ; But use a different arrow for ms i/o
  939.     OR    A
  940.     JR    Z,REGARW
  941.     LD    DE,ARROW3
  942.  
  943. REGARW:    CALL    MESAG2        ; (Prints without a leading cr/lf)
  944.     LD    HL,OUTFCB
  945.     CALL    PRNFIL        ; Print output filename
  946.     LD    A,(NPROFM)    ; See if "no prompt" flag set
  947.     OR    A
  948.     JR    NZ,ERASIT    ; If so, go perf a "blind erase"
  949.  
  950. CHK4IT:    LD    C,SETDMA    ; (re-direct the crap from the below call)
  951.     LD    DE,DDMA        ; Def dma is a good unused area
  952.     CALL    BDOSAV        ;
  953.     LD    C,SFIRST    ; Else see if output filename exists
  954.     LD    DE,OUTFCB
  955.     CALL    BDOSAV
  956.     INC    A        ; Now zero if file does not already exist
  957.     JR    Z,MAKFIL    ; If that is the case, just go make the file
  958.  
  959.     LD    DE,PROMPT    ; File exist, prompt the user
  960.     CALL    MESAG2
  961.     CALL    RSPNSE        ; Get response
  962.     JR    Z,ERASIT    ; Erase it if response is positive
  963.  
  964. NOPE:    CALL    CRLF        ; Extra cr/lf for file skip
  965.     SCF            ; Set flag: "mission not accomplished"
  966.     RET            ;
  967.  
  968. ERASIT:    LD    A,(QUIFM)    ; For aesthetics, must do an extra crlf if
  969.     OR    A        ; - in quiet mode & a prompt was asked
  970.     JR    Z,NOAEST    ; (br if not in quiet mode)
  971.     LD    A,(NPROFM)
  972.     OR    A
  973.     JR    NZ,NOAEST    ; Br if no prompt was asked
  974.  
  975.     CALL    CRLF        ; Else do it
  976.  
  977. NOAEST:    LD    DE,OUTFCB    ; Erase existing file w/ same name
  978.     LD    C,ERASE        ; (if erase fails, "make" below will, too)
  979.     CALL    BDOSAV
  980.  
  981. MAKFIL:    LD    C,MAKE        ; Make the new file
  982.     CALL    BDOSAV
  983.     INC    A
  984.     JR    NZ,OUTOK    ; Err cond check
  985.  
  986.     LD    DE,ERR2A    ; "file creation error"
  987.     JP    FATAL        ; (this is fatal)
  988.  
  989. OUTOK:    AND    A        ; Guarantee clr carry
  990.     RET
  991.  
  992. ;.......................................................................
  993. ;
  994. ; Close the output file whose fcb is "OUTFCB".
  995.  
  996. CLSOUT:    CALL    LOGOUT        ; Log to the output file's user area
  997.     LD    DE,OUTFCB
  998.     LD    C,CLOSE
  999.     CALL    BDOSAV        ; And close it
  1000.     RET
  1001.  
  1002. ;.......................................................................
  1003. ;
  1004. ; DATSTP -- Get create and modify stamps from original file, if 
  1005. ; available, and transfer them to new file.
  1006.  
  1007. DATSTP:    LD    A,(ZSDSFL)    ; check for ZSDOS
  1008.     OR    A
  1009.     RET    Z        ; (it's not, so forget it)
  1010.     CALL    LOGIN        ; setup for input file
  1011.     LD    DE,INFCB+12
  1012.     CALL    CLRFC2        ; initialize FCB
  1013.     LD    DE,INFCB
  1014.     LD    HL,DDMA        ; point to DMA buffer
  1015.     CALL    GETSTP        ; get ZSDOS file stamp
  1016.     RET    NZ        ; (error, must be no date stamping)
  1017.   IF NOT CRUNCH
  1018.     LD    A,(DATFLG)    ; do we have an embedded date?
  1019.     OR    A
  1020.     JR    Z,DATST1    ; (no)
  1021.     LD    HL,DATBUF    ; move embedded create date
  1022.     LD    DE,DDMA
  1023.     LD    BC,5
  1024.     LDIR
  1025.     LD    HL,DATBUF+10    ; move embedded modify date
  1026.     LD    DE,DDMA+10
  1027.     LD    BC,5
  1028.     LDIR
  1029.   ENDIF    ; NOT CRUNCH
  1030. DATST1:    LD    DE,DDMA+11    ; point to modify date month
  1031.     LD    A,(DE)
  1032.     DEC    DE        ; point back to modify date
  1033.     OR    A        ; do we have one?
  1034.     JR    NZ,DATST2    ; (yes, so continue)
  1035.     LD    HL,DDMA        ; no, move create date to modify date
  1036.     LD    BC,5        ; move create date to modify date
  1037.     LDIR            ; DE -> modify date
  1038. DATST2:    CALL    LOGOUT        ; setup for output file
  1039.     LD    DE,OUTFCB+12
  1040.     CALL    CLRFC2        ; initialize FCB
  1041.     LD    DE,OUTFCB
  1042.     LD    HL,DDMA        ; point to DMA buffer
  1043.     CALL    SETSTP        ; set file stamp
  1044.     RET
  1045.  
  1046. ;------------------------------------------------------------------------
  1047. ; GETSTP and SETSTP are much modified from Carson Wilson's ZSLIB routines
  1048. ; of the same name.
  1049. ;------------------------------------------------------------------------
  1050.  
  1051. ;........................................................................
  1052. ;
  1053. ; GETSTP - Get file datestamp.  On entry DE points to file's FCB, which
  1054. ; must be initialized, and HL points to 128-byte datestamp buffer.
  1055. ; Returns zero flag set if okay, non-zero if error.
  1056.  
  1057. GETSTP:    PUSH    BC
  1058.     PUSH    DE        ; DE -> user's FCB
  1059.     PUSH    HL        ; HL -> user's buffer
  1060.     LD    A,GETFSTP    ; BDOS get stamp function
  1061.     JR    GETSET
  1062. ;........................................................................
  1063. ;
  1064. ; SETSTP - Set file datestamp.  On entry DE points to file's FCB, which
  1065. ; must be initialized, and HL points to 128-byte datestamp buffer.
  1066. ; Returns zero flag set if okay, non-zero if error.
  1067.  
  1068. SETSTP:    PUSH    BC
  1069.     PUSH    DE        ; DE -> user's FCB
  1070.     PUSH    HL        ; HL -> user's buffer
  1071.     LD    A,SETFSTP    ; BDOS set stamp function
  1072. GETSET:    POP    DE        ; DE -> user's buffer
  1073.     PUSH    DE
  1074.     LD    C,SETDMA
  1075.     PUSH    AF        ; save stamp function
  1076.     CALL    BDOSAV
  1077.     POP    AF        ; recover stamp function
  1078.     POP    HL
  1079.     POP    DE        ; DE -> user's FCB
  1080.     LD    C,A        ; get or set stamp function in C
  1081.     CALL    BDOSAV        ; ..to/from user's buffer
  1082.     DEC    A        ; 1 -> 0 means get/set okay
  1083.     POP    BC
  1084.     RET
  1085.  
  1086. ;.......................................................................
  1087. ;
  1088. ; Output char in 'A' to the output buffer.
  1089.  
  1090. OUTB:    EXX            ; Switch to i/o regs
  1091.     PUSH    AF        ; Save caller's char
  1092.     LD    (DE),A        ; Put byte into the next avail position
  1093.     INC    E        ; Increment pointer
  1094.     LD    A,E        ; See if on a 128 byte boundary
  1095.     SLA    A
  1096.     JR    NZ,RETOUT    ; Return if not
  1097.     CALL    PROGO        ; If so, update output record count
  1098.     JR    C,RETOUT    ; Return if it wasn't a full page boundary
  1099.     INC    D        ; Incr pointer high byte
  1100.     LD    A,(EOBHI)    ; Limit
  1101.     CP    D        ; Check
  1102.     JR    NZ,RETOUT    ; Ret if limit not reached
  1103.     PUSH    BC        ; If so, write the output buffer to disk
  1104.     LD    A,(OBSZ)    ; Get output buffer size
  1105.     SLA    A        ; Double pages for # of 128 byte records
  1106.     LD    B,A        ; Number of records to write goes into b
  1107.     CALL    WRTOUT        ; Writes out 'b' 128 byte records
  1108.     POP    BC
  1109.     LD    DE,OBUF        ; Reset pointer to beginning of bfr & rtn.
  1110.  
  1111. RETOUT:    POP    AF        ; Restore caller's char, flip regs & rtn
  1112.     EXX
  1113.     RET
  1114.  
  1115. ;.......................................................................
  1116. ;
  1117. ; Write partial or full output buffer to disk.    The # of records to be
  1118. ; written is specified in "B".
  1119.  
  1120. WRTOUT:    CALL    LOGOUT        ; Log to the output file user area
  1121.     LD    A,B        ; See if zero sectors spec'd
  1122.     OR    A
  1123.     RET    Z        ; Simply return if so
  1124.  
  1125.     LD    DE,OBUF        ; Init dma addr to beg of output bfr
  1126.     LD    A,(CPM3FL)
  1127.     OR    A
  1128.     JP    NZ,MSECO    ; Br for multi-sector output
  1129.  
  1130. WRTLP:    CALL    WRSEC        ; Write 128 bytes
  1131.     DEC    B
  1132.     RET    Z        ; Return if done
  1133.     LD    E,80H        ; Else incr by 1/2 page
  1134.     CALL    WRSEC
  1135.     INC    D        ; Inc hi-byte, 0 the lo to effect
  1136.     LD    E,0        ; Another 80h incr
  1137.     DJNZ    WRTLP        ; Loop till done
  1138.     RET
  1139.  
  1140. ;.......................................................................
  1141.  
  1142. MSECO:    LD    C,SETDMA    ; De already points to the output buffer
  1143.     CALL    BDOSAV
  1144.     LD    E,B        ; Put # of secs to write here, still in b
  1145.     LD    C,SETMS        ; Bdos func #
  1146.     CALL    BDOSAV
  1147.     LD    DE,OUTFCB    ; Output file fcb
  1148.     LD    C,WRITE        ; Bdos func #
  1149.     CALL    BDOSAV        ; Write out the whole buffer
  1150.     OR    A
  1151.     RET    Z        ; Ret if no error, else fall thru to
  1152.                 ; "wrterr" below & then thru to "fatal"
  1153.  
  1154. ;.......................................................................
  1155.  
  1156. WRTERR:    CP    2        ; Disk full?
  1157.     JR    NZ,NOTFUL
  1158.     LD    DE,ERR2B    ; "+++ Disk Full +++"
  1159.     CALL    MESAGE
  1160.     CALL    ERACE        ; Close / erase output file w/message.
  1161.                 ; (also closes input file)
  1162.     LD    A,(DIFD)
  1163.     OR    A
  1164.     JR    NZ,TRYCHG    ; The foll is only possible for 2 diff drvs
  1165.     CALL    CRLF
  1166.     JP    RETCCP        ; Forget it, the guy's out of luck
  1167.  
  1168. TRYCHG:    LD    DE,MSGCH    ; Does he want to change diskettes?
  1169.     CALL    MESAGE
  1170.     CALL    RSPNSE        ; Get any key press. ^C will cancel.
  1171.     CALL    CRLF
  1172.  
  1173. ;.......................................................................
  1174. ;
  1175. ; Now prepare to do a disk reset.  First perform a "select disk" func-
  1176. ; tion on the drive which is NOT being changed, namely the input drive.
  1177. ; Then perform a "reset drive" on the output drive (the user has already
  1178. ; changed diskettes).  Then set the default drive back the way it was.
  1179.  
  1180.     LD    A,(IDSPEC)    ; Input drive spec, a=1, etc.
  1181.     DEC    A        ; Convert to "A=0" format
  1182.     LD    E,A        ; Where bdos wants it
  1183.     LD    C,SELDSK    ; Bdos select disk function
  1184.     CALL    BDOSAV
  1185.     LD    C,RSTDRV    ; Perform a disk reset
  1186.     LD    DE,(ODRVEC)
  1187.     CALL    BDOSAV
  1188.     LD    A,(DEFDRV)    ; Now restore the default drive
  1189.     DEC    A
  1190.     LD    E,A
  1191.     LD    C,SELDSK
  1192.     CALL    BDOSAV
  1193.     LD    HL,(BUFPTR)    ; Set things up so last file gets re-processed
  1194.     LD    DE,-12
  1195.     ADD    HL,DE
  1196.     LD    (BUFPTR),HL
  1197.     JP    NXTFIL        ; Start all over (resets stack there)
  1198.  
  1199. NOTFUL:    LD    DE,ERR2C    ; "output error." (other than disk full)
  1200.     JP    FATAL        ; (this is fatal)
  1201.  
  1202. ;.......................................................................
  1203. ;
  1204. ; Auxiliary subr for above.  Writes 128 bytes from current val of DE.
  1205.  
  1206. WRSEC:    LD    C,SETDMA    ; Set dma as spec'd
  1207.     CALL    BDOSAV
  1208.     PUSH    DE        ; Save that val
  1209.     LD    DE,OUTFCB    ; Spec the output file
  1210.     LD    C,WRITE
  1211.     CALL    BDOSAV        ; Do it
  1212.     OR    A
  1213.     POP    DE        ; Restore to same value as before
  1214.     RET    Z        ; Rtn, assuming no error
  1215.     JR    WRTERR
  1216.  
  1217. ;.......................................................................
  1218. ;
  1219. ; Output the partial output buffer through the current pointer (DE'). If
  1220. ; not on a sector boundary, fill the remainder with "1A"'s.  Close files
  1221. ; and see if there are any more of them.
  1222.  
  1223. DONE:    EXX            ; Determine where nearest record boundary is
  1224.     LD    A,E        ; Get low byte of output pointer
  1225.     EXX
  1226.     CPL            ; Compute how far to next page boundary
  1227.     INC    A
  1228.     AND    7FH        ; Convert to distance to next half-page bndry
  1229.     JR    Z,ONBNDY    ; If there already (should be the case on uncr)
  1230.  
  1231.     LD    B,A        ; Else set up to fill rest of sector w/ eof's
  1232.     LD    A,1AH
  1233.  
  1234. FILLP:    CALL    OUTB        ; Do that
  1235.     DJNZ    FILLP
  1236.  
  1237. ONBNDY:    EXX            ; Compute # of sectors to write to disk
  1238.  
  1239.     EX    DE,HL        ; Put output pointer in HL
  1240.     LD    BC,OBUF        ; (ok to clobber BC' now, uncr is done w/ it)
  1241.     AND    A        ; (clr carry)
  1242.     SBC    HL,BC        ; How far into the buffer we are
  1243.     SLA    L        ; Effectively divide difference by 128
  1244.     RL    H
  1245.     LD    B,H        ; "b" now has # of recs to be written
  1246.  
  1247.     CALL    WRTOUT        ; Do that
  1248.     CALL    PROGI2        ; Output the final count
  1249.     CALL    PROGF        ; Last pass: print values in "k" also
  1250.  
  1251.     EXX
  1252.     RET
  1253.  
  1254. ;-----------------------------------------------------------------------
  1255. ;    File I/O subroutines:  Input and/or Output
  1256. ;-----------------------------------------------------------------------
  1257.  
  1258. ;.......................................................................
  1259. ;
  1260. ; "Log" to the input, output, or the default user area.
  1261.  
  1262. LOGDEF:    PUSH    BC
  1263.     PUSH    DE
  1264.     LD    A,(USERNO)    ; Log to the original user area, if necessary
  1265.     JR    LOGX
  1266.  
  1267. LOGOUT:    PUSH    BC
  1268.     PUSH    DE
  1269.     LD    A,(OUTUSR)    ; Log to the output user area, if necessary
  1270.     JR    LOGX
  1271.  
  1272. LOGIN:    PUSH    BC
  1273.     PUSH    DE
  1274.     LD    A,(INUSR)    ; Log to the input user area, if necessary
  1275.  
  1276. LOGX:    LD    E,A        ; Common code for either of above
  1277.     LD    A,(CURUSR)
  1278.     CP    E
  1279.     JR    Z,SKIPU        ; Filter out unnecessary user # changes
  1280.  
  1281.     LD    A,E        ; Back to "A" for updating "curusr"
  1282.     LD    (CURUSR),A    ; Do that
  1283.     LD    C,GSUSER    ; Now actually change user #'s
  1284.     CALL    BDOSAV
  1285.  
  1286. SKIPU:    POP    DE
  1287.     POP    BC
  1288.     RET
  1289.  
  1290. ;.......................................................................
  1291. ;
  1292. ; Get the current (called on program entry) user #. Put it in "USERNO".
  1293. ; Get the default drive and put its adjusted value in "DEFDRV"
  1294.  
  1295. GETUSR:    PUSH    BC
  1296.     PUSH    DE
  1297.     LD    C,GSUSER
  1298.     LD    E,0FFH        ; Spec "get" as opposed to "set"
  1299.     CALL    BDOSAV
  1300.     LD    (USERNO),A    ; Put that there
  1301.     LD    C,GETDSK    ; Get current disk function
  1302.     CALL    BDOSAV
  1303.     INC    A        ; Adjust so it is normal (ie a=1, not zero)
  1304.     LD    (DEFDRV),A    ; Put that there
  1305.     POP    DE
  1306.     POP    BC
  1307.     RET
  1308.  
  1309. ;.......................................................................
  1310. ;
  1311. ; Add the value in A to the current running checksum.  Regular registers
  1312. ; active.
  1313.  
  1314. CKSUM:    LD    HL,(CHKSUM)    ; Get current checksum
  1315.     LD    C,A
  1316.     LD    B,0        ; New val in BC
  1317.     ADD    HL,BC        ; Add to running checksum
  1318.     LD    (CHKSUM),HL    ; And save
  1319.     RET            ; Return with 'A'still intact
  1320.  
  1321. ;.......................................................................
  1322. ;
  1323. ; Initialize the FCB pointed to by DE.    Leave the drive spec alone.
  1324.  
  1325. CLRFCB:    PUSH    DE        ; Save caller's pointer to fcb
  1326.     INC    DE        ; Skip past drive spec
  1327.     LD    B,11        ; # of blanks for filename area
  1328.     LD    A,' '        ; A blank, obviously
  1329.  
  1330. ZLP1:    LD    (DE),A        ; Put in the blanks
  1331.     INC    DE
  1332.     DJNZ    ZLP1
  1333.  
  1334. CLREST:    LD    B,24        ; # of zeroes for the rest
  1335.     XOR    A        ; A zero, obviously
  1336.  
  1337. ZLP2:    LD    (DE),A        ; Put those in
  1338.     INC    DE
  1339.     DJNZ    ZLP2
  1340.  
  1341.     POP    DE        ; Restore pointer to FCB and return
  1342.     RET
  1343.  
  1344. ;...............................
  1345.  
  1346. CLRFC2:    PUSH    DE        ; Clear FCB starting after the filename field
  1347.     JR    CLREST        ; (DE supplied pointing to fcb+12)
  1348.  
  1349. ;.......................................................................
  1350. ;
  1351. ; Erase the output file, with message.
  1352.  
  1353. ERACE:    CALL    CLSOUT        ; (entry here if files are still open)
  1354.     CALL    CLSIN
  1355.  
  1356. ERAOUT:    LD    DE,MSGERA    ; "erasing..."
  1357.     CALL    MESAG2
  1358.     LD    HL,OUTFCB
  1359.     CALL    PRNFIL
  1360.     CALL    LOGOUT        ; Log to appropriate user # first !
  1361.     LD    DE,OUTFCB
  1362.     LD    C,ERASE
  1363.     CALL    BDOSAV
  1364.     RET
  1365.  
  1366. ;-----------------------------------------------------------------------
  1367. ;    Miscellaneous subroutines
  1368. ;-----------------------------------------------------------------------
  1369.  
  1370. ;.......................................................................
  1371. ;
  1372. ; Get a user Y/N response. Abort on ^C, return zero stat on "yes"
  1373.  
  1374. RSPNSE:    LD    C,CONIN        ; Console input
  1375.     CALL    BDOSAV        ; Wait for response
  1376.     CP    CTRLC        ; ^c ?
  1377.     JR    NZ,NCTRLC    ; Br if not
  1378.     LD    DE,ABORT    ; Abort w/ appropriate message
  1379.     JP    FATAL
  1380.  
  1381. NCTRLC:    CP    'Y'
  1382.     RET    Z
  1383.     CP    'y'
  1384.     RET            ; Rtns zero response if guy answered "Yes"
  1385.  
  1386. ;.......................................................................
  1387. ;
  1388. ; 4 x 2 divide- hlde / BC for result in DE (remainder in HL)
  1389.  
  1390. DIVIDE:    LD    A,B        ; }
  1391.     CPL            ; }
  1392.     LD    B,A        ; }
  1393.     LD    A,C        ; } negate divisor in BC
  1394.     CPL            ; }
  1395.     LD    C,A        ; }
  1396.     INC    BC        ; }
  1397.  
  1398. DV10:    LD    A,11H        ; Iterations, 17 req. to get all the DE bits
  1399.     JR    UM1
  1400. UM0:    ADC    HL,HL
  1401.  
  1402. UM1:    ADD    HL,BC        ; Divide hlde by -BC
  1403.     JR    C,UM2        ; If it fit
  1404.     SBC    HL,BC        ; Else restore it
  1405.     OR    A        ; Make sure carry is 0
  1406.  
  1407. UM2:    RL    E        ; Result bit to DE
  1408.     RL    D
  1409.     DEC    A
  1410.     JR    NZ,UM0        ; Continue
  1411.     RET
  1412.  
  1413. ;...............................
  1414.  
  1415. DIV10:    EX    DE,HL        ; Divide 16 bit value in HL by 10
  1416.     LD    HL,0        ; Zero the low byte
  1417.     LD    BC,-10        ; We can skip the negation code
  1418.     JR    DV10
  1419.  
  1420. ;.......................................................................
  1421. ;
  1422. ; BDOS call with all registers and alternates saved except "A"
  1423.  
  1424. BDOSAV:    EX    AF,AF'
  1425.     PUSH    AF
  1426.     EX    AF,AF'
  1427.     PUSH    BC
  1428.     PUSH    DE
  1429.     PUSH    HL
  1430.     EXX
  1431.     PUSH    BC
  1432.     PUSH    DE
  1433.     PUSH    HL
  1434.     PUSH    IX
  1435.     PUSH    IY
  1436.     EXX
  1437.     CALL    BDOS
  1438.     LD    (BDOSHL),HL    ; Some routines may want to analyze HL
  1439.     EXX
  1440.     POP    IY
  1441.     POP    IX
  1442.     POP    HL
  1443.     POP    DE
  1444.     POP    BC
  1445.     EXX
  1446.     POP    HL
  1447.     POP    DE
  1448.     POP    BC
  1449.     EX    AF,AF'
  1450.     POP    AF
  1451.     EX    AF,AF'
  1452.     RET
  1453.  
  1454. ;.......................................................................
  1455. ;
  1456. ; Type the string pointed to by DE to the console.
  1457.  
  1458. MESAGE:    CALL    CRLF        ; Precede all messages with cr, lf
  1459.  
  1460. MESAG2:    PUSH    BC        ; (entry here for no cr/lf)
  1461.     LD    C,PRTSTR    ; Print string
  1462.     CALL    BDOSAV
  1463.     POP    BC
  1464.     RET
  1465.  
  1466. ;.......................................................................
  1467. ;
  1468. ; Non-Z80 fatal error special "emergency exit".  This routine to be
  1469. ; JUMPED to.
  1470.  
  1471. MESS80:    LD    C,PRTSTR    ; Can't use "MESAGE" beause can't use "BDOSAV"
  1472.     CALL    BDOS
  1473.     RET            ; Rtn to ccp. (os's stack still intact)
  1474.  
  1475. ;.......................................................................
  1476. ;
  1477. ; Print a carriage return / linefeed sequence.
  1478.  
  1479. CRLF:    LD    A,CR
  1480.     CALL    TYPE
  1481.     LD    A,LF
  1482.     CALL    TYPE
  1483.     RET
  1484.  
  1485. ;.......................................................................
  1486. ;
  1487. ; Type the character in A to the console device.  Saves all registers.
  1488.  
  1489. TYPE:    PUSH    AF
  1490.     PUSH    BC
  1491.     PUSH    DE
  1492.     LD    E,A        ; Where bdos wants it
  1493.     LD    C,CONOUT    ; Bdos "console output" function
  1494.     CALL    BDOSAV        ; Do it
  1495.     POP    DE
  1496.     POP    BC
  1497.     POP    AF
  1498.     RET
  1499.  
  1500. ;.......................................................................
  1501. ;
  1502. ; Print fatal error messages.  Jump to this routine -- not a call!
  1503.  
  1504. FATALU:    CALL    MESAG2        ; Entry here if usage instructions desired.
  1505. GIVUSG:    LD    DE,CPYRT    ; version and copyright notice
  1506.     CALL    MESAG2
  1507.     LD    DE,USAGE
  1508.     CALL    MESAG2
  1509.     CALL    PRTNAM        ; program name
  1510.     LD    DE,SYNTX1    ; syntax line...
  1511.     CALL    MESAG2
  1512.     CALL    DUDIR        ; DU or DIR
  1513.     LD    DE,SYNTX2
  1514.     CALL    MESAG2
  1515.     CALL    DUDIR
  1516.     LD    DE,USAGE1    ; Q option
  1517.     CALL    MESAG2
  1518.     LD    A,(QUIFL)
  1519.     OR    A
  1520.     CALL    NZ,PRTOFF
  1521.     CALL    Z,PRTON
  1522.     LD    DE,USAGE2    ; C option
  1523.     CALL    MESAG2
  1524.     LD    A,(CNFRFL)
  1525.     OR    A
  1526.     CALL    NZ,PRTOFF
  1527.     CALL    Z,PRTON
  1528.     LD    DE,USAGE3    ; T and E options
  1529.     CALL    MESAG2
  1530.     LD    A,(NPROFL)
  1531.     OR    A
  1532.     CALL    NZ,PRDONT
  1533.     LD    DE,USAGE4    ; more E option, and A option if CRUNCH
  1534.     CALL    MESAG2
  1535.   IF CRUNCH
  1536.     LD    A,(ARCHIV)
  1537.     OR    A
  1538.     CALL    NZ,PRTOFF
  1539.     CALL    Z,PRTON    
  1540.   ENDIF    ; CRUNCH
  1541.     LD    DE,USAGE5    ; S option
  1542.     CALL    MESAG2
  1543.     LD    A,(SYSFL)
  1544.     OR    A
  1545.     CALL    Z,PRTINC
  1546.     CALL    NZ,PRTEXC
  1547.     LD    DE,USAGE6    ; more S option
  1548.     CALL    MESAG2
  1549.     JR    LOGOFF        ; Skip the "0 files processed" business
  1550.  
  1551. FATAL:    CALL    MESAG2        ; Print any final message.
  1552.  
  1553. RETCCP:    LD    A,(QUIFM)
  1554.     OR    A
  1555.     CALL    Z,CRLF
  1556.     LD    HL,(NFP)    ; get # of files processed
  1557.     CALL    DECOUT        ; Output that number
  1558.     LD    DE,FINMSG    ; "file(s) processed"
  1559.     CALL    MESAG2
  1560.     LD    HL,(NFP)
  1561.     DEC    HL
  1562.     LD    A,L
  1563.     OR    H
  1564.     LD    A,'s'
  1565.     CALL    NZ,TYPE
  1566.     LD    DE,FINMS2
  1567.     CALL    MESAG2
  1568.  
  1569. LOGOFF:    CALL    LOGDEF        ; Restore user number from original prog entry
  1570.  
  1571.     LD    SP,(OLDSTK)    ; Restore to system stack
  1572.     LD    A,(WRMFLG)    ; Warm boot flag set?
  1573.     OR    A
  1574.     JP    NZ,0000        ; If so, perf a warm boot
  1575.     RET            ; Else return to system ccp
  1576.  
  1577. ;.......................................................................
  1578. ;
  1579. ; Print "on", "off", "Don't", "Ex", "In", etc., and return to caller.
  1580.  
  1581. PRTON:    LD    A,'n'
  1582.     JP    TYPE
  1583.  
  1584. PRTOFF:    LD    A,'f'
  1585.     CALL    TYPE
  1586.     JP    TYPE
  1587.  
  1588. PRDONT:    LD    DE,MSGDNT
  1589.     JP    MESAG2
  1590.  
  1591. PRTINC:    LD    A,'I'
  1592.     CALL    TYPE
  1593.     LD    A,'n'
  1594.     JP    TYPE
  1595.  
  1596. PRTEXC:    LD    A,'E'
  1597.     CALL    TYPE
  1598.     LD    A,'x'
  1599.     JP    TYPE
  1600.  
  1601. DUDIR:    LD    HL,(Z3ED)    ; print DU
  1602.     LD    A,L
  1603.     OR    H
  1604.     LD    A,'u'
  1605.     JP    Z,TYPE
  1606.     LD    A,'i'        ; or if ZCPR, DIR
  1607.     CALL    TYPE
  1608.     LD    A,'r'
  1609.     JP    TYPE
  1610.  
  1611. PRTNAM:    LD    HL,COMNAM    ; use actual COM filename, if available
  1612.     LD    A,(HL)
  1613.     CP    ' '        ; anything there?
  1614.     JR    NZ,PRTNM2    ; (yes, use it)
  1615.     LD    HL,PRGNAM    ; no, use default program name
  1616. PRTNM2:    LD    B,8        ; print 8 characters
  1617. PRTNLP:    LD    A,(HL)
  1618.     CP    ' '        ; or until finding a space
  1619.     RET    Z
  1620.     CALL    TYPE
  1621.     INC    HL
  1622.     DJNZ    PRTNLP
  1623.     RET
  1624.  
  1625. ;.......................................................................
  1626. ;
  1627. ; Print the filename whose FCB is pointed to by HL.
  1628.  
  1629. PRNFIL:    DEC    HL        ; Slide back to user # at fcb-1
  1630.     LD    B,(HL)        ; Put that here for now
  1631.     INC    HL        ; Back to drive spec
  1632.     LD    A,(HL)        ; Get drive spec
  1633.     INC    HL        ; Move to 1st char of filename
  1634.     OR    A        ; Drive = default?
  1635.     JR    NZ,NOTDEF    ; Br if not
  1636.     LD    A,(DEFDRV)    ; If so, get the default drive
  1637.  
  1638. NOTDEF:    ADD    A,'A'-1        ; Convert to a letter
  1639.     CALL    TYPE
  1640.     LD    C,11+2        ; Total spaces to fill for fn and ft + 1
  1641.                 ; (will be used later)
  1642.     LD    A,B        ; Get user # we picked up above
  1643.     CP    10        ; 2 digits?
  1644.     JR    C,ONEDIG    ; Br if not
  1645.     DEC    C        ; adjust number of spaces by one
  1646.     LD    B,0        ; zero counter
  1647. TENSLP:    INC    B        ; increment 10's
  1648.     SUB    10        ; subtract 10
  1649.     CP    10
  1650.     JR    NC,TENSLP    ; ..until less than 10
  1651.     PUSH    AF
  1652.     LD    A,B        ; get 10's
  1653.     ADD    A,'0'        ; make printable
  1654.     CALL    TYPE        ; type 10's digit
  1655.     POP    AF        ; get back remainder
  1656. ONEDIG:    ADD    A,'0'        ; make printable
  1657.     CALL    TYPE        ; Type 1's digit
  1658.     LD    A,':'        ; Follow drive spec with a ":"
  1659.     CALL    TYPE
  1660.     LD    B,8+1        ; Max chars in file name plus 1
  1661.     CALL    PRNFNT        ; Print file name
  1662.     LD    A,'.'        ; Print dot
  1663.     CALL    TYPE
  1664.     LD    B,3+1        ; Max chars in file type plus 1
  1665.     CALL    PRNFNT        ; Print file type
  1666.  
  1667. PRNSP:    LD    A,' '        ; Fill out with spaces
  1668.     DEC    C
  1669.     RET    Z
  1670.     CALL    TYPE
  1671.     JR    PRNSP
  1672.  
  1673. ;...............................
  1674.  
  1675. PRNFNT:    DEC    B        ; Aux routine for abv; print file name or type
  1676.     RET    Z        ; Return if no more
  1677.     LD    A,(HL)        ; Else get character
  1678.     AND    7Fh        ; reset high bit
  1679.     INC    HL        ; Point to next character
  1680.     CP    ' '        ; Is it a space?
  1681.     JR    Z,PRNFNT    ; If so, loop back for more
  1682.     DEC    C        ; Else, decrement count of printed chars
  1683.     CALL    TYPE        ; Print the character
  1684.     JR    PRNFNT        ; Back for more
  1685.  
  1686. ;.......................................................................
  1687. ;
  1688. ; Wildcard expansion.  All filenames matching INFCB will be packed into
  1689. ; FNBUFF, twelve bytes per filename.  The first byte is used as a
  1690. ; "tag/flag", the following eleven bytes in each entry contain the file-
  1691. ; name.  The tag/flag is set to 00 if the file is NOT to be processed,
  1692. ; 01 indicates file IS to be processed.  The initial state of this byte
  1693. ; is defined here, but may be manually modified if "confirm mode" is
  1694. ; selected. The initial value is determined as follows:
  1695. ;
  1696. ; 1. If confirm and archive modes are OFF, files are flagged for proces-
  1697. ;    sing (01).
  1698. ;
  1699. ; 2. If "archive bit" mode is on, all "un-archived" files are tagged to
  1700. ;    processed (01), others are not (00). This can be overidden either
  1701. ;    way later "confirm" mode was selected as well.
  1702. ;
  1703. ; 3. If confirm mode only was selected, files are flagged as NOT to be
  1704. ;    processed (00).  They can be manually tagged by the user later.
  1705. ;
  1706. ;    (Note that certain circumstances may cause the files to be flagged
  1707. ;    later as (02) "perform a direct copy", but this is not our concern
  1708. ;    now.  Also note that a flag byte of "FF" means "no more files in
  1709. ;     list".)
  1710.  
  1711. WILDEX:    LD    HL,0        ; Init "# of files" to zero
  1712.     LD    (NFILES),HL
  1713.     LD    DE,DDMA        ; Explicitly set the dma to 80h
  1714.     LD    C,SETDMA
  1715.     CALL    BDOSAV
  1716.     LD    DE,INFCB    ; Fcb to be expanded
  1717.     LD    C,SFIRST    ; Look for 1st match
  1718.     CALL    BDOSAV        ; Bdos "Search for first" call
  1719.     CP    0FFH        ; Any match?
  1720.     RET    Z        ; Error- no matches- rtn w/ zero stat
  1721.     LD    DE,FNBUFF    ; From now on, DE is buffer dest pointer
  1722.     CALL    MOVNAM        ; Move first filename into buffer
  1723.  
  1724. EXPLP:    PUSH    DE        ; } (save bfr dest pntr)
  1725.     LD    DE,INFCB    ; }
  1726.     LD    C,SNEXT        ; }
  1727.     CALL    BDOSAV        ; }
  1728.     POP    DE        ; } process all additional matches
  1729.     CP    0FFH        ; }
  1730.     JR    Z,DONEX        ; }
  1731.     CALL    MOVNAM        ; }
  1732.     JR    EXPLP        ; }
  1733.  
  1734. DONEX:    LD    (DE),A        ; Flag the last [non-] entry with ff
  1735.     LD    HL,(NFILES)    ; Number of files found
  1736.     LD    A,H
  1737.     OR    L        ; Rtn with non-zero status if any files found
  1738.     RET
  1739.  
  1740. ;................................
  1741.                 ; Move filename to next position in FNBUFF
  1742. MOVNAM:    ADD    A,A        ; (pointed to by DE). Initialize the first
  1743.     ADD    A,A        ;  byte, the tag/flag byte, appropriately
  1744.     ADD    A,A        ;  depending on operating mode)
  1745.     ADD    A,A
  1746.     ADD    A,A        ; Bdos suplies directory entry at dma + 32*a
  1747.     ADD    A,DDMA        ; Namely 80h
  1748.     LD    L,A        ; Set up HL as source pointer
  1749.     LD    H,0        ; Hi-byte of ddma, namely zero
  1750.  
  1751.     LD    A,(SYSFM)    ; include system files?
  1752.     OR    A
  1753.     JR    NZ,MOVNM2    ; (yes)
  1754.     PUSH    HL
  1755.     LD    BC,10        ; no, so check for one
  1756.     ADD    HL,BC
  1757.     BIT    7,(HL)
  1758.     POP    HL
  1759.     RET    NZ        ; (don't find it or count it)
  1760.  
  1761. MOVNM2:    LD    A,(CNFRFM)    ; Default each file to "tagged" or "untagged"
  1762.     LD    B,A        ; If /C or /A options, default to untagged
  1763.  
  1764.   IF CRUNCH
  1765.     LD    A,(ARCHVM)    ; Archive bit mode only exists in CRUNCH
  1766.      ELSE
  1767.     XOR    A        ; (inherently "off")
  1768.   ENDIF    ; CRUNCH
  1769.  
  1770.     OR    B        ; See if either mode is active
  1771.     JR    Z,CF0        ; Br if not
  1772.     LD    A,01H
  1773. CF0:    XOR    01H        ; Now A=00 if either flag set, else A=01
  1774.     LD    B,12        ; Byte count +1 (11 filename characters)
  1775.  
  1776.     PUSH    DE        ; Save a copy of pntr to status byte
  1777.     JR    MIDLP        ; Transfer the tag/flag byte and 11 characters
  1778.  
  1779. ;...............................
  1780.  
  1781. LDIRLP:    LD    A,(HL)        ; Loop like ldir but "ands" with 7Fh
  1782.     LD    C,A        ; (to grab the val of A on last loop, used below)
  1783.     AND    7FH        ; Get rid of status bits
  1784.  
  1785. MIDLP:    LD    (DE),A        ; <== entry for first loop
  1786.     INC    HL
  1787.     INC    DE
  1788.     DJNZ    LDIRLP        ; Transfer 12 bytes
  1789.  
  1790. ;...............................
  1791.  
  1792.     POP    HL        ; (pushed as DE above)
  1793.  
  1794.   IF CRUNCH
  1795.     LD    A,(ARCHVM)    ; Archive mode?
  1796.     OR    A
  1797.     JR    Z,SKPSTF    ; Skip this code if not
  1798.  
  1799.     LD    A,C        ; Get the archive bit, from the last char
  1800.     AND    80H        ; Isolate it
  1801.     XOR    80H        ; Flip it
  1802.     RLCA            ; And convert it into a possible 01h
  1803.     OR    (HL)
  1804.     LD    (HL),A        ; "stuff" it into the tag/flag byte.
  1805.   ENDIF    ; CRUNCH
  1806.  
  1807. SKPSTF:    LD    HL,(NFILES)    ; Incr # of files counter
  1808.     INC    HL
  1809.     LD    (NFILES),HL
  1810.     OR    A        ; reset carry
  1811.     LD    BC,MAXFLS
  1812.     SBC    HL,BC
  1813.     RET    C        ; Normal return
  1814.  
  1815. ;...............................
  1816.  
  1817.     LD    DE,ERR3        ; Too many files, fatal error
  1818.     JP    FATAL
  1819.  
  1820. ;-----------------------------------------------------------------------
  1821. ;
  1822. ; Update the running count of # of records output (add one to it).
  1823.  
  1824. PROGO:    PUSH    AF        ; Save everything
  1825.     PUSH    BC
  1826.     PUSH    HL
  1827.     LD    HL,(OUTCTR)    ; Update binary count
  1828.     INC    HL
  1829.     LD    (OUTCTR),HL
  1830.     LD    HL,PROGBF+11    ; Point to ascii string version of count
  1831.     CALL    BCDINC        ; Incr that, too
  1832.     POP    HL        ; Restore regs & return
  1833.     POP    BC
  1834.     POP    AF
  1835.     RET
  1836.  
  1837. ;.......................................................................
  1838. ;
  1839. ; Update  # of records read on input.  Every 2 or 4 calls to this rou-
  1840. ; tine, actually update the display.  Monitor the console for ^C.
  1841.  
  1842. PROGI:    PUSH    AF        ; Save everything
  1843.     PUSH    BC
  1844.     PUSH    HL
  1845.  
  1846.     LD    C,CONST        ; Get console status
  1847.     CALL    BDOSAV
  1848.     OR    A
  1849.     JR    Z,CONTIN    ; Continue if no character
  1850.     LD    C,CONIN
  1851.     CALL    BDOSAV        ; Get the char for analysis
  1852.     CP    CTRLC        ; ^c?
  1853.     JR    NZ,CONTIN    ; Continue if not
  1854.     CALL    CRLF
  1855.     CALL    ERACE        ; erase output file
  1856.     LD    DE,ABORT    ; Else abort
  1857.     JP    FATAL
  1858.  
  1859. CONTIN:    LD    A,(QUIFM)
  1860.     OR    A
  1861.     JR    NZ,PERFIN    ; Skip the stuff below in quiet mode
  1862.     LD    A,(INCTR+0)    ; Mask ls bits to determine whether this call
  1863.     DEC    A        ; - is an 'active' one (updates the console)
  1864.     LD    B,A
  1865.     LD    A,(DIRFLG)    ; "direct copy flag" - different screen dsply
  1866.     OR    B
  1867.     AND    SCRUPT2        ; Screen update speed control #2
  1868.     JR    Z,FULUPD
  1869.     AND    SCRUPT1        ; Screen update speed control #1
  1870.     CALL    Z,PRTUPD    ; If zero, actually do a typeout
  1871.     JR    PERFIN
  1872.  
  1873. FULUPD:    CALL    PRNFIN        ; Perf "full" update.
  1874.  
  1875. PERFIN    EQU    $
  1876.  
  1877.   IF CRUNCH
  1878.     LD    A,(FULFLG)    ; If table not full, skip below check
  1879.     OR    A
  1880.     JR    Z,SKIPW4
  1881.  
  1882.     LD    A,(INCTR+0)    ; This controls checking for adaptive reset
  1883.     DEC    A
  1884.     AND    SCRUPT1        ; CHLRST may initiate an adaptive reset by
  1885.     CALL    Z,CHKRST    ; Setting a flag
  1886.  
  1887.   ENDIF    ; CRUNCH
  1888.  
  1889. SKIPW4:    LD    HL,(INCTR)    ; In any event, perform the increments
  1890.     INC    HL        ; First, incrment the binary version
  1891.     LD    (INCTR),HL
  1892.  
  1893.     LD    HL,PROGBF+5    ; Increment ascii string representing same
  1894.     CALL    BCDINC
  1895.     POP    HL        ; Restore regs & rtn
  1896.     POP    BC
  1897.     POP    AF
  1898.     RET
  1899.  
  1900. ;.......................................................................
  1901.  
  1902. PRTUPD:    PUSH    DE        ; Type a "short-form" update update
  1903.     LD    A,'$'        ; To the screen (ie "records in" only)
  1904.     LD    (PROGBF+6),A    ; Effectively truncate the update text
  1905.     LD    DE,PROGBF
  1906.     CALL    MESAG2        ; Type to screen until the "$" terminator
  1907.     LD    A,' '        ; Restore that byte to it's natural state
  1908.     LD    (PROGBF+6),A
  1909.     POP    DE
  1910.     RET            ; And return
  1911.  
  1912. ;.......................................................................
  1913. ;
  1914. ; Routine  like  "PROGI", but does NOT increment and  WILL  update  the
  1915. ; console on any call. Basically used as a final screen update.
  1916.  
  1917. PROGI2:    PUSH    AF
  1918.     LD    A,(QUIFM)    ; Still, don't type if in "quiet" mode
  1919.     OR    A
  1920.     JR    NZ,QUIET2
  1921.     PUSH    BC        ; Else print up the final tally
  1922.     PUSH    HL
  1923.     CALL    PRNFIN
  1924.     POP    HL
  1925.     POP    BC
  1926.  
  1927. QUIET2:    POP    AF
  1928.     RET
  1929.  
  1930. ;.......................................................................
  1931. ;
  1932. ; Perform a full screen update (recs in / out, compression ratio, etc.)
  1933.  
  1934. PRNFIN:    PUSH    DE
  1935.     PUSH    IX
  1936.     LD    DE,PROGBF    ; This buffer contains most of the stuff,
  1937.     CALL    MESAG2        ; - ready to be typed
  1938.  
  1939.     LD    A,(DIRFLG)
  1940.     OR    A
  1941.     JR    NZ,SKIPW2
  1942.  
  1943.     LD    DE,(OUTCTR)    ; Compression ratio must be computed, however
  1944.     PUSH    DE
  1945.     POP    IX        ; Get # of output recs into ix
  1946.  
  1947.     LD    HL,(INCTR)    ; Spec the divisor for the subroutine call
  1948.     LD    (DIVISR),HL
  1949.     CALL    COMRAT        ; Compute ratio. result, in %, returned in HL
  1950.     LD    A,' '        ; Need an extra space here to make it look good
  1951.     CALL    TYPE
  1952.     CALL    DECOUT        ; Type to screen in decimal
  1953.     LD    DE,PERCNT    ; A "%" char, basicly
  1954.     CALL    MESAG2        ; Type that
  1955.     LD    A,(OLDFLG)    ; Skip rest for old style (v1.x) files
  1956.     OR    A
  1957.     JR    NZ,SKIPW2
  1958.     LD    HL,4096        ; Display this value whenever table is full
  1959.     LD    A,(FULFLG)    ; Is it?
  1960.     OR    A
  1961.     JR    NZ,NOFUD    ; Br if so
  1962.     LD    HL,(ENTRY)    ; Type "Codes Assigned" to the screen
  1963.  
  1964.   IF CRUNCH
  1965.     DEC    HL        ; Adjust for a 2 count "skew" due to
  1966.     DEC    HL        ; - inherent nature of uncr to be "behind"
  1967.   ENDIF    ; CRUNCH
  1968.  
  1969. NOFUD:    CALL    DECOUT        ; The "ca" count
  1970.     LD    A,' '        ; Some more aesthetics
  1971.     CALL    TYPE
  1972.     CALL    TYPE
  1973.  
  1974.     LD    HL,(TTOTAL)    ; Get "Codes Reassigned"
  1975.     CALL    DECOUT        ; The "cr" count
  1976.  
  1977. SKIPW2:    POP    IX        ; Restore regs and return
  1978.     POP    DE
  1979.     RET
  1980.  
  1981. ;.......................................................................
  1982. ;
  1983. ; "Incremental compression ratio" computation.    For analysis of the
  1984. ; possibility of setting the adaptive reset flag, compute the compres-
  1985. ; sion ratio since the last reset (not necessarily the beginning of the
  1986. ; file).  This is significantly preferable to analyzing the ratio since
  1987. ; the beginning (the one displayed on the console) because that number
  1988. ; gets very "stable" as one gets further and further into a large file.
  1989. ; Sudden structural variations will not get picked up quickly that way.
  1990. ;
  1991. ; INCTR0 and OUTCT0 contain the # of records at the time of the last re-
  1992. ; set (or zero).  The offset from them (to the current values) are the
  1993. ; numbers divided to compute the ratio.
  1994.  
  1995.   IF CRUNCH
  1996. CHKRST:    PUSH    DE
  1997.     PUSH    IX
  1998.     LD    HL,(INCTR)    ; As described above
  1999.     LD    DE,(INCTR0)
  2000.     AND    A
  2001.     SBC    HL,DE
  2002.     LD    (DIVISR),HL    ; Adjusted input rec count will be the divisor
  2003.     LD    HL,(OUTCTR)
  2004.     LD    DE,(OUTCT0)
  2005.     AND    A
  2006.     SBC    HL,DE        ; Adjusted output record count is dividend
  2007.     EX    DE,HL
  2008.     PUSH    DE
  2009.     POP    IX        ; Put it in ix for the subr call
  2010.     CALL    COMRAT        ; Returns a compression ration in "HL"
  2011.  
  2012. ; The criteria for adaptive reset is when the current "incremental"
  2013. ; ratio goes "up".  "Up" is defined as higher the limit, which is equal
  2014. ; to the lowest incremental ratio achieved so far (not necessarily the
  2015. ; last computed ratio).  ["So far" means since the last adaptive reset,
  2016. ; if any.]
  2017. ;
  2018. ; Computationsbelow are single byte precision.    If the "compression"
  2019. ; ratio (during crunching) actually ever got higher than 256%, then this
  2020. ;  analysis is really quite irrelevant.. that would really be a lost
  2021. ; cause...
  2022.  
  2023.     LD    A,(LOWPER)    ; Get "target" value
  2024.     SUB    L        ; Compare to current
  2025.     JR    C,CHK4RS    ; If current is higher, reset may be indicated
  2026.     LD    A,L        ; If new ratio is lower, it is the new target
  2027.     LD    (LOWPER),A
  2028.     JR    SKIPW3        ; That's all
  2029.  
  2030. ; If new value is higher, a reset may be indicated.  The exact criteria
  2031. ; is that the value be one full percentage point, besides the +/-1 nor-
  2032. ; mal roundoff wavering, above the target value.
  2033.  
  2034. CHK4RS:    INC    A        ; Adjust the difference computed by one
  2035.     JP    P,SKIPW3    ; If that is not negative, no reset now
  2036.  
  2037.     LD    A,80H        ; Else set the adaptive reset flag. full
  2038.     LD    (RSTFLG),A    ; - processing occurs back at the main loop
  2039.  
  2040.     PUSH    HL        ; However, take care of updating these now
  2041.     LD    HL,(INCTR)    ; Inctr0 <-- inctr
  2042.     LD    (INCTR0),HL
  2043.     LD    HL,(OUTCTR)    ; Outct0 <-- outctr
  2044.     LD    (OUTCT0),HL
  2045.     POP    HL
  2046.  
  2047. SKIPW3:    POP    IX        ; Restore regs and return
  2048.     POP    DE
  2049.     RET
  2050.   ENDIF    ; CRUNCH
  2051.  
  2052. ;.......................................................................
  2053. ;
  2054. ; Compute a compression ratio, in percent.  Calculates IX/("divisr").
  2055. ; When called, DE must have a a copy of the dividend as well as IX.
  2056.  
  2057. COMRAT:    LD    HL,0        ; Prepare for 32 bit multiply by 100
  2058.     LD    B,H        ; [ ratio = (100 * out) / in ]
  2059.     LD    C,L
  2060.     ADD    IX,IX
  2061.     ADC    HL,HL        ; 2x
  2062.     ADD    IX,DE
  2063.     ADC    HL,BC        ; 3x
  2064.     ADD    IX,IX
  2065.     ADC    HL,HL        ; 6x
  2066.     ADD    IX,IX
  2067.     ADC    HL,HL        ; 12x
  2068.     ADD    IX,IX
  2069.     ADC    HL,HL        ; 24x
  2070.     ADD    IX,DE
  2071.     ADC    HL,BC        ; 25x
  2072.     ADD    IX,IX
  2073.     ADC    HL,HL        ; 50x
  2074.     ADD    IX,IX
  2075.     ADC    HL,HL        ; 100x
  2076.     ADD    IX,IX
  2077.     ADC    HL,HL        ; 200x
  2078.     PUSH    IX        ; Get result into HL DE for dividing
  2079.     POP    DE        ;
  2080.     LD    BC,(DIVISR)    ; Get divisor
  2081.     CALL    DIVIDE        ; Divides (HL DE) / BC
  2082.     EX    DE,HL        ; Put result into HL
  2083.     SRL    H        ; Divide it by 2
  2084.     RR    L        ;
  2085.     RET    NC        ; & return if no need to round up
  2086.     INC    HL        ; Else round up
  2087.     RET
  2088.  
  2089. ;.......................................................................
  2090. ;
  2091. ; Increment a 4 character ASCII unpacked BCD string, pointed to by HL.
  2092.  
  2093. BCDINC:    LD    B,4        ; Loop counter
  2094.  
  2095. DIGLP:    LD    A,(HL)        ; HL points to string
  2096.     OR    10H        ; Blank to zero conversion (init'd to blank)
  2097.     INC    A        ; Incr
  2098.     LD    (HL),A        ; Re-store
  2099.     CP    '9'+1        ; Carry?
  2100.     RET    NZ        ; Rtn if not
  2101.     LD    (HL),'0'    ; Else zero & loop to next char
  2102.     DEC    HL        ;
  2103.     DJNZ    DIGLP        ; (But not past limit)
  2104.     RET            ; And return
  2105.  
  2106. ;.......................................................................
  2107. ;
  2108. ; Convert records to "k" and print same.  Called at end of process.
  2109.  
  2110. PROGF:    PUSH    DE        ; Save regs
  2111.     PUSH    BC
  2112.     LD    DE,SPCPAR    ; Spaces, parenthesis
  2113.     CALL    MESAG2
  2114.     LD    HL,(INCTR)    ; Input recs
  2115.     CALL    AUXSUB        ; Div by 8 and type
  2116.     LD    DE,ARROW2    ; " --->"
  2117.     CALL    MESAG2
  2118.     LD    A,' '
  2119.     CALL    TYPE
  2120.     LD    HL,(OUTCTR)    ; Similarly for output recs
  2121.     CALL    AUXSUB
  2122.     LD    A,')'
  2123.     CALL    TYPE
  2124.     CALL    CRLF
  2125.     POP    BC        ; Restore & rtn
  2126.     POP    DE
  2127.     RET
  2128.  
  2129. ;...............................
  2130.                 ; Aux routine for above calculates (HL)/8
  2131. AUXSUB:    LD    DE,7        ; With upward rounding, & types it.
  2132.     ADD    HL,DE        ; [ie compute (# of recs+7) / 8 ]
  2133.     SRL    H        ; }
  2134.     RR    L        ; }
  2135.     SRL    H        ; } div by 8
  2136.     RR    L        ; }
  2137.     SRL    H        ; }
  2138.     RR    L        ; }
  2139.     CALL    DECOUT        ; Type HL in decimal
  2140.     LD    A,'k'
  2141.     CALL    TYPE
  2142.     RET
  2143.  
  2144. ;.......................................................................
  2145. ;
  2146. ; Convert a binary number to four chars ASCII & type them, right justified.
  2147.  
  2148. DECOUT:    CALL    DIV10        ; Divide orig # (in HL), by 10
  2149.     LD    A,L        ; Get remainder from l, (0-9)
  2150.     PUSH    AF        ; Save in reverse order retrieval later
  2151.     EX    DE,HL        ; Old dividend becomes new divisor
  2152.     CALL    DIV10        ; Repeat 3 more times
  2153.     LD    A,L
  2154.     PUSH    AF
  2155.     EX    DE,HL
  2156.     CALL    DIV10
  2157.     LD    A,L
  2158.     PUSH    AF
  2159.     EX    DE,HL
  2160.     CALL    DIV10
  2161.     LD    A,L
  2162.     PUSH    AF
  2163.     EX    DE,HL
  2164.     LD    B,3        ; Becomes loop counter
  2165.     LD    C,0EFH        ; Mask to convert zeroes to blanks
  2166.  
  2167. DECLP:    POP    AF        ; Type the 4 digits, with leading 0 suppression
  2168.     OR    A        ; Is it zero?
  2169.     JR    Z,LVMASK    ; Lv mask set if so
  2170.     LD    C,0FFH        ; Else cancel masking (of zeroes to blanks)
  2171. LVMASK:    ADD    A,'0'        ; Convert to ascii
  2172.     AND    C        ; Possibly blank a zero
  2173.     CALL    TYPE        ; Output the char
  2174.     DJNZ    DECLP        ; Do the first 3 digits
  2175.     POP    AF        ; Last digit is easy. never blank it.
  2176.     ADD    A,'0'        ; Convert to acsii
  2177.     CALL    TYPE        ; Type it & rtn
  2178.     RET
  2179.  
  2180. ;.......................................................................
  2181. ;
  2182. ; (Re-)initialize all necessary ram locs.  Called once for each file to
  2183. ; be processed.  This routine gets its info from an initialization block
  2184. ; called "SHADOW" which is copied into the working memory.  Routine also
  2185. ; performs alternate register initialization.
  2186.  
  2187. INTRAM:    LD    HL,SHADOW    ; Contains a copy of all relevant init values
  2188.     LD    DE,RAM        ; Target
  2189.     LD    BC,EOSHAD-SHADOW
  2190.     LDIR            ; Do it
  2191.     EXX            ; Routine performs register initialization too
  2192.     LD    HL,IBUF        ; Reset input buffer pointer
  2193.     LD    DE,OBUF        ; Reset output buffer pointer
  2194.     LD    BC,0        ; Zero this
  2195.     EXX            ; Back to primary registers
  2196.     RET
  2197.  
  2198. ;.......................................................................
  2199. ;
  2200. ; Exchange the 12 byte entries at (HL) and (DE). [ Used by SORT below ]
  2201.  
  2202. SWAP:    PUSH    DE
  2203.     PUSH    HL
  2204.     LD    B,12        ; Loop counter
  2205.  
  2206. SWAPLP:    LD    A,(DE)        ; Get a corresponding byte from each
  2207.     LD    C,(HL)
  2208.     EX    DE,HL        ; Exchange the pointers
  2209.     LD    (DE),A        ; And re-store the pair of bytes
  2210.     LD    (HL),C
  2211.     INC    HL
  2212.     INC    DE
  2213.     DJNZ    SWAPLP        ; Loop; (note- another ex DE,HL not needed)
  2214.     POP    HL
  2215.     POP    DE
  2216.     RET
  2217.  
  2218. ;.......................................................................
  2219. ;
  2220. ; Compare the 11 byte entries at (HL+1) and (DE+1) [ Used by SORT below]
  2221.  
  2222. COMP:    PUSH    DE
  2223.     PUSH    HL
  2224.     LD    B,11        ; Limit max # of comparisons
  2225.  
  2226. COMPLP:    INC    HL        ; Pre-incr pointers
  2227.     INC    DE
  2228.     LD    A,(DE)
  2229.     CP    (HL)
  2230.     JR    NZ,CMPRTN    ; If not equal, rtn with appropriate carry stat
  2231.     DJNZ    COMPLP        ; Loop up to eleven times
  2232.     SCF            ; Set for equal avoids unecessary equal swaps
  2233.  
  2234. CMPRTN:    POP    HL
  2235.     POP    DE
  2236.     RET
  2237.  
  2238. ;.......................................................................
  2239. ;
  2240. ; Sort all of the 12 byte filename entries in FNBUFF. Sleazy bubble sort.
  2241.  
  2242. SORT:
  2243.     LD    BC,(NFILES)    ; init inner (BC) loop counter
  2244.     LD    (SOCNT),BC    ; init outer (SOCNT) loop counter
  2245.     LD    DE,FNBUFF    ; Init "outer loop" pointer
  2246.  
  2247. ;...............................
  2248.  
  2249. OUTRLP:    LD    H,D        ; Reset inner loop pointer and counter
  2250.     LD    L,E        ; HL <-- DE
  2251.  
  2252. ;...............................
  2253.  
  2254. INRLP:    PUSH    BC        ; Save inner loop counter
  2255.     CALL    COMP        ; Compare two entries
  2256.     CALL    NC,SWAP        ; Swap if necessary
  2257.     LD    BC,12        ; Incr inner pointer by 12
  2258.     ADD    HL,BC
  2259.     POP    BC        ; Restore inner loop counter
  2260.     DEC    BC
  2261.     LD    A,B
  2262.     OR    C
  2263.     JP    NZ,INRLP
  2264.  
  2265. ;...............................
  2266.  
  2267.     LD    A,E        ; Incr DE by 12
  2268.     ADD    A,12
  2269.     LD    E,A
  2270.     LD    A,D
  2271.     ADC    A,0
  2272.     LD    D,A
  2273.     LD    BC,(SOCNT)
  2274.     DEC    BC
  2275.     LD    (SOCNT),BC
  2276.     LD    A,B
  2277.     OR    C
  2278.     JR    NZ,OUTRLP    ; Loop till done
  2279.     RET
  2280.  
  2281. ;-----------------------------------------------------------------------
  2282. ;    Text, data, etc.
  2283. ;-----------------------------------------------------------------------
  2284.  
  2285. PRSER5    EQU    $        ; (Destination filename supplied)
  2286. PRSER1    EQU    $        ; (Error from "parseu")
  2287.     DB    BELL,'++ Invalid argument ++',CR,LF,'$'  ; (generic for above)
  2288. PRSER2    EQU    $        ; (Invalid user #)
  2289. PRSER3    EQU    $        ; (Invalid drive)
  2290. PRSER9:    DB    BELL,'++ Invalid directory ++',CR,LF,'$' ; (for ZCPR3 only)
  2291. PRSER4:    DB    BELL,'++ Invalid option ++',CR,LF,'$'
  2292. PRSER8:    DB    BELL,'++ [text] to long ++',CR,LF,'$'
  2293.  
  2294. MSGERA:    DB    ' Erasing: $'
  2295. MSGCPY:    DB    '   Copying...',CR,LF,' $'
  2296. ERR0:    DB    ' [ File empty ]$'
  2297. ERR1:    DB    'File not found.$'
  2298. ERR2A:    DB    'File creation error.$'
  2299. ERR2B:    DB    CR,LF,'++ Disk Full ++   ',BELL,'$'
  2300. ERR2C:    DB    'Output error.$'
  2301. ERR3:    DB    'Too many files.$'
  2302. LAKMEM:    DB    'Not enough memory.  $'
  2303.   IF ZSYS
  2304. WRNGUP:    DB    'ZCPR3 required.$'
  2305.   ELSE    ; ZSYS
  2306. WRNGUP:    DB    'Z-80 CPU required.$'
  2307.   ENDIF    ; ZSYS
  2308. ARROW:    DB    ' --> $'
  2309. ARROW2:    DB    ' -->$'
  2310. ARROW3:    DB    ' ==> $'
  2311. PERCNT:    DB    '%  $'
  2312. SPCPAR:    DB    ' ($'
  2313. DASHES:    DB    '----',CR,LF,'$'
  2314. MSGDNT:    DB    'Don''t $'
  2315. MSGTAG:    DB    ' T to Tag files for processing, RETURN to skip.',CR,LF
  2316.     DB    ' B = Back one       U = Untag       ^C = Abort',CR,LF,'$'
  2317. MSGOK:    DB    'Selections OK (Y/N)? $'
  2318. MSGBEL:    DB    BELL        ; (cont. below)
  2319. MSGCLF:    DB    CR,LF,LF,'$'
  2320.  
  2321. MSGCH:    DB    'Change output disk and press RETURN to continue (^C aborts). $'
  2322. ABORT:    DB    CR,LF,'   ++ Aborted ++$'
  2323. PROMPT:    DB    ' Erase existing file (Y/[N])? ',BELL,'$'
  2324. HEADNG:    DB    '  in    out   rat   ca    cr',CR,LF ; (cont)
  2325.     DB    ' ====  ====  ====  ====  ====',CR,LF,'$'
  2326.  
  2327. FINMSG:    DB    ' file$'
  2328. FINMS2:    DB    ' processed.$'
  2329.  
  2330. ;-----------------------------------------------------------------------
  2331.  
  2332. SHADOW    EQU    $        ; (for description, see immediately below)
  2333.                 ;
  2334.     DB    00        ; "fulflg"
  2335.     DW    0000        ; "chksum"
  2336.     DB    01        ; "secnt"
  2337.     DW    0000        ; "inctr"
  2338.     DW    0000        ; "outctr"
  2339.     DW    0000        ; "inctr0"
  2340.     DW    0000        ; "outct0"
  2341.     DW    0000H        ; "entry"
  2342.     DB    09        ; "codlen"
  2343.     DB    02H        ; "trgmsk"
  2344.     DB    09H        ; "codle0"
  2345.     DB    00H        ; "rstflg"
  2346.     DW    0000H        ; "ttotal"
  2347.     DB    0FFH        ; "lowper"
  2348.     DW    NOPRED        ; "lastpr"
  2349.     DB    01H        ; "entflg"
  2350.     DB    00H        ; "oldflg"
  2351.     DB    00H        ; "dirflg"
  2352.     DB    00H        ; "sqzflg"
  2353.     DB    CR,'    0 /   0$' ; "progbf"
  2354.  
  2355. ;-----    PROGBF + 0  12345678901 ; (offsets into above)
  2356. ;             ^
  2357. EOSHAD    EQU    $
  2358. ;_______________________________________________________________________
  2359.  
  2360.     DSEG
  2361.  
  2362. ; The following RAM locations must be re-initialized each time the pro-
  2363. ; gram is executed (for each file when wildcards are used).  The area
  2364. ; called "SHADOW" (above) is used to accomplish this.
  2365.  
  2366. RAM    EQU    $
  2367.  
  2368. FULFLG:    DS    1        ; Becomes "FF" when table is full
  2369. CHKSUM:    DS    2        ; Checksum accumulated here
  2370. SECNT:    DS    1        ; Count of sectors read per "reload" call
  2371. INCTR:    DS    2        ; Count of total sectors read from input
  2372. OUTCTR:    DS    2        ; Likewise for output
  2373. INCTR0:    DS    2        ; Value of "inctr" at last reset
  2374. OUTCT0:    DS    2        ; Value of "outctr" at last reset
  2375. ENTRY:    DS    2        ; Current entry (code) number.
  2376. CODLEN:    DS    1        ; Current code length, in bits.
  2377. TRGMSK:    DS    1        ; Mask contains "1" bit in pos of next code len
  2378. CODLE0:    DS    1        ; "delayed" value of "codlen"
  2379. RSTFLG:    DS    1        ; Will cause an adaptive reset when set
  2380. TTOTAL:    DS    2        ; "codes reassigned" (for display purposes)
  2381. LOWPER:    DS    1        ; Lowest incremental compr. ratio achieved
  2382. LASTPR:    DS    2        ; "last pred"
  2383. ENTFLG:    DS    1        ; Flag prevents duplicating entries
  2384. OLDFLG:    DS    1        ;
  2385. DIRFLG:    DS    1        ; "direct flag", set when doing plain file copy
  2386. SQZFLG:    DS    1        ;
  2387. PROGBF:    DS    20        ; Alphanumeric ASCII to go to console
  2388.  
  2389. ;.......................................................................
  2390.  
  2391. INUSR:    DS    1        ; Must immediately precede the input fcb
  2392. INFCB:    DS    36        ; Input file fcb.
  2393.  
  2394. OUTUSR:    DS    1        ; Must immediately precede the output fcb
  2395. OUTFCB:    DS    36        ; Output fcb
  2396.  
  2397. DATFLG:    DS    1        ; file has embedded date if non-zero
  2398. DATBUF:    DS    15        ; date stamp storage
  2399.  
  2400. ;.......................................................................
  2401. ;
  2402. ; The flags below are analogous to some of patches at the beginning of
  2403. ; the program.    Those default values are copied into the data area here
  2404. ; each program execution, since some can be changed if an appropriate
  2405. ; command line option is processed.  This keeps the prgrm re-executable.
  2406.  
  2407. QUIFM:    DS    1        ; Verbose mode flag
  2408. NPROFM:    DS    1        ; No prompt before overwrite flag
  2409. NOMSFM:    DS    1        ; Defeat multi-sector i/o flag
  2410. CNFRFM:    DS    1        ; Confirm every file flag
  2411. ARCHVM:    DS    1        ; Archive bit mode flag (used by crunch only)
  2412. SYSFM:    DS    1        ; Include system files flag
  2413. BUFPTR:    DS    2        ; Used for indexing
  2414. OLDSTK:    DS    2        ; Operating system stack pointer saved here
  2415. DISP:    DS    2        ; A displacement
  2416. DIVISR:    DS    2        ; A divisor
  2417. BDOSHL:    DS    2        ; HL returned by BDOS calls saved here
  2418. CPM3FL:    DS    1        ; CP/M Plus flag
  2419. ZSDSFL:    DS    1        ; ZSDOS flag
  2420. CURUSR:    DS    1        ; The "current" user area
  2421. USERNO:    DS    1        ; The default user area
  2422. DEFDRV:    DS    1        ; The default drive
  2423. IDSPEC:    DS    1        ; Input drive spec (A=1, B=2,...)
  2424. ODSPEC:    DS    1        ; Output drive spec
  2425. OBSZ:    DS    1        ; Output buffer size, pages
  2426. EOBHI:    DS    1        ; End of output buffer, hi-byte
  2427. NFILES:    DS    2        ; # of files (from wildcard expander)
  2428. FILNUM:    DS    2        ; File counter for tag mode
  2429. DIFDU:    DS    1        ; Set if input DU: different than output DU:
  2430. DIFD:    DS    1        ; Set if input D: is different than output D:
  2431. WLDFLG:    DS    1        ; Set if program invoked with wildcard(s)
  2432. ODRVEC:    DS    2        ; "drive vector" corresponding to output drv
  2433. NFP:    DS    2        ; # of files processed
  2434. SOCNT:    DS    2        ; Sort outer loop counter
  2435.  
  2436. ;           (end of COMMON.LIB include)
  2437. ;=======================================================================
  2438.