home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / beehive / compress / usqfst20.arc / UF20.MAC < prev   
Text File  |  1990-07-21  |  38KB  |  1,090 lines

  1. ; ***********************************************************************
  2. ; *                                    *
  3. ; *            Fast Unsqueezer, v2.0                *
  4. ; *                 28 June 1986                *
  5. ; *                        Steven Greenberg    *
  6. ; ***********************************************************************
  7.  
  8.  
  9.     .Z80
  10.     TITLE 'Fast Unsqueezer, v2.0'
  11.  
  12.     ASEG        ; (see note concerning aseg / cseg controversy
  13.     ORG    100H    ; at end of program where "codtbl" is defined.)
  14.  
  15. ; ***    CSEG        [out for now]
  16.  
  17. ; v2.0 - 06/28/86
  18. ;
  19. ;      Supports optional destination as well as source drive  spec-
  20. ; ifications.   At Bob Freed's hint, the maximum size  of  "codtbl"
  21. ; has  been  reduced to 256 (see clarification  at  "SQUEEZED  FILE
  22. ; FORMAT"; Bytes 5+n, 6+n).   This reduces the required TPA size by
  23. ; 4k.   Version  also gracefully terminates  (with  an  "Unexpected
  24. ; EOF"  message)  should the squeezed input file  be  truncated  or
  25. ; otherwise  badly damaged.   Previous versions would  continuously
  26. ; decode the final record if faced with this condition.  All output
  27. ; filenames  are automatically converted from lower to  upper  case
  28. ; (Where do these squeezed files with embedded lower-case filenames
  29. ; come from, anyway?).  Includes additional filename processing  to
  30. ; limit filename to a maximum of 8 characters plus three  extension
  31. ; characters  (ie,   in no case will bytes be  written  beyond  the
  32. ; filename area of the output FCB.  v2.0 also gives usage  (command
  33. ; line format) if called with no arguments.  Thanks to H. Goldstein
  34. ; for some of these suggestions.
  35. ;                      - SGG
  36. ;
  37. ; v1.9 - 04/02/86
  38. ;
  39. ;   Program  now  zeroes the MS bits of the filename  chars  before
  40. ; putting them into the output FCB (as it turns out, these bits may
  41. ; or  may not be guaranteed clear, depending on the  program  which
  42. ; performed the squeeze). This eliminates a possible problem if the
  43. ; squeezed  file  was Read-Only. Fixed a glitch which  would  cause
  44. ; unnecessary additional sectors to be appended to the output  file
  45. ; in  the  unlikely event its length was an exact multiple  of    the
  46. ; output  buffer. No longer prints the program name to the  console
  47. ; so you can name your .COM file as you please. Restored some  doc-
  48. ; umentation  that inadvertently got removed in v1.8. Put  35/36ths
  49. ; of  the output FCB after the end of the program since it  is  now
  50. ; fully  initialized by "ZERFCB". Added code to type  source  file-
  51. ; name(s)  as well as output filename(s) to  console  (particularly
  52. ; useful in wildcard mode).
  53. ;                      - SGG
  54. ;
  55. ; v1.8 - 03/04/86
  56. ;
  57. ;   The  search-and-optional-erase of the destination file was  re-
  58. ; moved in favor of a "blind" delete file call. The open-file  call
  59. ; immediately after the make-file has been eliminated. The TPA size
  60. ; check  has been changed to take into account that  versions  1.1+
  61. ; require the CCP to remain resident. Slightly increased the  input
  62. ; buffer  size for this assembly prog now req's memory up to to  an
  63. ; even 9000H. If anyone has memory problems, change the buffer size
  64. ; equ's  at the end ("IBUFSZ","OBUFSZ",or "MAXFLS"). I made  Sigi's
  65. ; wildcard  expansion  buffer size settable at assembly time  &  is
  66. ; checked for overflow at run time.
  67. ;                     - SGG
  68. ;
  69. ; v1.7 - 03/01/86
  70. ;   Found a pre-stack-save Z80 test that I THINK everyone can agree
  71. ; on (it also works for HD64180s & NSC800s), went back to Z80  code
  72. ; for all stack pointer moves, converted Sigi's wildcard sorter  to
  73. ; Zilog  mnemonics  so non-M80 folks can assemble it and  threw  in
  74. ; some  JRs here and there. Restored the disk write  error  message
  75. ; routine  from another(!) version 1.3 (not documented  here)  done
  76. ; done by Bill Duerr.
  77. ;                     - Bruce Morgen [bm]
  78. ;
  79. ; v1.6 - 02/18/86
  80. ;   Added wildcard support and suppress non-*?Q?-files  completely.
  81. ; Moved code where it belongs (CSEG)!
  82. ;                     - Sigi Kluger
  83. ;
  84. ; v1.5 - 02/18/86
  85. ;   One  of the changes made in v1.1 has been reversed-  Apparently
  86. ; the BIOS for some machines (Kaypro & Osborne?) clobber the alter-
  87. ; nate registers. Thanks to Keith Peterson for info on this.
  88. ;
  89. ;   No  more tricks at "FATAL" or OS stack size  assumptions  Built
  90. ; CR/LF  into the message routine; removed extraneous OR A's  after
  91. ; INC A's from the modified file open success tests.
  92. ;
  93. ;   Most of the changes are in the form of improved  documentation,
  94. ; & some code segments have been shifted in position.
  95. ;
  96. ;                     - Steven Greenberg
  97. ;
  98. ; v1.4 - 02/17/86 [intermediate unreleased version]
  99. ;
  100. ; v1.3 - 02/17/86
  101. ;   Changed  stack  save and load routines to the old  8080  method
  102. ; since they must run even if you try to use an 8080 processor  and
  103. ; get the error message.
  104. ;                     - D. Jewett, III [dj]
  105. ;
  106. ; v1.2 - 02/15/86
  107. ;   Fixed source code so it could used with the M80 assembler which
  108. ; is  owned by more CP/M users than all other Z80  assemblers  com-
  109. ; bined  (and by a wide margin at that). It can still be  assembled
  110. ; with the SLR Z80ASM for which it was originally written.
  111. ;                     - Irv Hoff
  112. ;
  113. ; v1.1 - 02/09/86
  114. ;   Various small changes to the CP/M interface aspect of the code.
  115. ; Fixed the test for file-open success (BDOS won't always return  a
  116. ; zero). Moved local stack to Copyright message and saved OS  stack
  117. ; to  beginning of same, eliminating warm boot-on-exit (the  algor-
  118. ; ithm  is so fast that the CCP reload often took as much  time  as
  119. ; the unsqueezing itself). Took out now unnecessary stack trick  at
  120. ; FATAL:  and slimmed down on PUSH/POPs at BDOSAV: (BDOS  does  not
  121. ; use Z80 specific registers).
  122. ;                     - Bruce Morgen
  123. ; _________________________________________________________________
  124. ; (FOR CP/M 2.0+, Z-80 only)
  125. ;
  126. ; v1.0 - 01/10/86
  127. ;
  128. ;   This  program  unsqueezes standard  (Greenlaw  style)  squeezed
  129. ; programs.  Simply  specify the filename to be unsqueezed  on  the
  130. ; command line; the result filename will be generated  automatically
  131. ; and written to the default drive. The difference between this un-
  132. ; squeezer and others lies in its unique architecture. This results
  133. ; in speed increases ranging from a factor of about 2 (compared  to
  134. ; fastest  assembly coded programs previously available) on  up  to
  135. ; factors greater than 5 (compared to standard C coded versions).
  136. ;
  137. ;   The architecture, very briefly, is as follows. First the  "dic-
  138. ; tionary" info contained in the squeezed file is "compiled" into a
  139. ; decoding program, which sits in memory just above the .COM  file.
  140. ; Since  each squeezed file generates its own unique  program,  the
  141. ; program  is a highly efficient subroutine for performing the  ac-
  142. ; tual unsqueeze operation.
  143. ;
  144. ;   Thanks to Jeff D. Wilson for many worthwhile suggestions.
  145. ;
  146. ;                     - Steven Greenberg
  147. ; ________________________________________________________________________
  148. ; SQUEEZED  FILE  FORMAT:  Here is the  format  of  the  mysterious
  149. ; squeezed file, originally defined by Richard Greenlaw around '81.
  150. ;
  151. ;   BYTES 0,1: 76,FF always.  Identifies the file as "squeezed".
  152. ;
  153. ;   BYTES  2,3:  16-bit checksum, lo-byte first.  It is the sum  of
  154. ; all  bytes as they appear in the GENERATED file, modulo 2^16.
  155. ;
  156. ;   BYTES 4,... 4+n: Variable length filename field, containing the
  157. ; name  of the original file before it was  squeezed.  The end   of
  158. ; this  field is defined by a zero byte. The "."  char   separating
  159. ; the  filename  from its .EXT is included as  as a char,  and  its
  160. ; position may float.
  161. ;
  162. ;   BYTE 5+n:  Zero, as mentioned above
  163. ;
  164. ;   BYTE  6+n,7+n:  The length of the "dictionary", which  follows.
  165. ; The value is the number "word pairs" (described below), and has a
  166. ; maximum value of 0100H.  The length of the dictionary in bytes is
  167. ; four times this value  (2 bytes/word  x  2 words/pair).
  168. ;
  169. ;      The  dictionary is a binary tree based structure.   It  con-
  170. ; tains "internal" and "terminal" (or leaf) nodes.  The maximum #of
  171. ; codes to be represented is 257 (256 possible bytes plus a special
  172. ; EOF  code).  This may require as many as 257 leaf nodes plus  256
  173. ; "internal"  nodes (513 total).  The standard squeezed  file  dic-
  174. ; tionary format represents the tree by using up to 256 pairs of 2-
  175. ; byte  words; each word within the pair could be a pointer to  an-
  176. ; other  node  or a could be a "leaf" word which  is  terminal  and
  177. ; posseses a value.  In most of the following discussion, the whole
  178. ; pair  is called a "node".  A worst case situation takes 256  word
  179. ; pair nodes, corresponding to 256 "table entries".  These will  be
  180. ; described  in  more detail later.   Pre- v2.0  versions  of  this
  181. ; program  allocated twice this amount, with the extra  serving  no
  182. ; particular purpose.
  183. ;
  184. ;   BYTES 8+n,... (8+n)+(4*l)-1: Dictionary, as described above.
  185. ;
  186. ;   REMAINING  BYTES:  Squeezed code  to be thought of as  a  cont-
  187. ; inuous bit  stream where byte boundaries are insignificant. Chars
  188. ; are defined by codes of varying lengths of bits  (The  more freq-
  189. ; uent  the character the shorter the code).  The bit stream is  LS
  190. ; bit thru MS bit, then move on to  next byte.  The end of the file
  191. ; cannot be detected  until the special end-of-file code "SPEOF" is
  192. ; decoded.
  193. ;
  194. ;   ADDITIONAL NOTE:  Multiple contiguous occurrences of the  iden-
  195. ; tical  character are encoded by the 3-byte sequence:
  196. ;
  197. ;              <char> 90H <count>
  198. ;
  199. ;   When  "CHAR" is first decoded, it is outputted normally.   When
  200. ; the 90H is decoded, a flag is set, the next char  is decoded    for
  201. ; a count val, and the first char is repeated an additional "count-
  202. ; 1"  times. Encoding the byte  90H itself is achieved by the  seq-
  203. ; uence  90H  00H i.e.,  when the count is 0 send a 90H,  the  byte
  204. ; before the  90H was irrelevant.
  205. ;______________________________________________________________________________
  206.  
  207. ; Opcode equates
  208.  
  209. JPOP    EQU    0C3H        ; Opcode for "JP" instruction
  210.  
  211. ; ASCII equates
  212.  
  213. CR    EQU    0DH
  214. LF    EQU    0AH
  215.  
  216. ; CP/M address equates
  217.  
  218. DFCB    EQU    5CH        ; Default file control block
  219. DFCB2    EQU    6CH        ; Default file control block #2
  220. DDMA    EQU    80H        ; Default dma address
  221. BDOS    EQU    0005H        ; Bdos entrypoint
  222.  
  223. ; BDOS function equates
  224.  
  225. CONOUT    EQU    2        ; Print char to console
  226. PRTSTR    EQU    9        ; Print string to console
  227. OPEN    EQU    15        ; Open file
  228. CLOSE    EQU    16        ; Close file
  229. SFIRST    EQU    17        ; Search for first
  230. SNEXT    EQU    18        ; Search for next
  231. ERASE    EQU    19        ; Erase file
  232. READ    EQU    20        ; Read file (sequential)
  233. WRITE    EQU    21        ; Write file (sequential)
  234. MAKE    EQU    22        ; Make file
  235. SETDMA    EQU    26        ; Set dma address
  236. ;______________________________________________________________________________
  237.  
  238. ENTRY:    JP    START
  239.  
  240. ;..............................................................................
  241. ;
  242. OLDSTK:    DEFB    'Copyright (c) Steven Greenberg 6/28/86  201-670-8724; '
  243.     DEFB    'may be copied for non-profit use only'
  244. ;..............................................................................
  245.  
  246. START:
  247.     LD    A,7FH        ; Find out if z80 with flag test
  248.     ADD    A,A        ; Add 7fh to 7fh
  249.     JP    PE,Z80        ; Parity (overflow)=z80
  250.     LD    DE,WRNGUP    ; "program requires z-80 processor"
  251.     JP    MESS80        ; Non-z80s: print up and go home
  252.  
  253. Z80:    LD    (OLDSTK),SP    ; Save os's stack
  254.     LD    SP,START    ; Set local stack
  255.     LD    A,(BDOS+2)    ; Size up the tpa
  256.     SUB    EOBFHI+10    ; (includes 2k for the ccp)
  257.     JR    NC,ENOUGH    ;
  258.     LD    DE,LAKMEM    ; "not enough memory..."
  259.     JP    FATAL        ; (fatal error)
  260.  
  261. ENOUGH:    LD    DE,LOGO        ; Version#, etc
  262.     CALL    MESAGE        ;
  263.     LD    A,(DFCB+1)    ; See if any input file specified
  264.     CP    ' '        ;
  265.     JR    NZ,NOHELP    ;
  266.     LD    DE,USAGE    ; User needs help (so to speak)
  267.     JP    FATAL        ;
  268.  
  269. NOHELP:    LD    A,'Q'        ; Force .?q? !!!
  270.     LD    (DFCB+10),A    ; (middle char of filename extension)
  271.     LD    DE,DFCB        ; Point to specified file
  272.     LD    HL,FNBUFF    ; And to filename buffer
  273.     CALL    WILDEX        ; Do wildcard expansion
  274.     JR    Z,WERR        ; (if no matching file found)
  275.  
  276.     LD    DE,MAXFLS    ; Check if too many matching files
  277.     AND    A        ; Clear carry
  278.     SBC    HL,DE        ;
  279.     JR    NC,TOOMNY    ;
  280.  
  281.     LD    HL,FNBUFF    ; Get name buffer
  282.     LD    (BUFPTR),HL    ; Set up buffer pointer
  283.  
  284.     LD    A,(DFCB2+0)    ; Get destination drive spec for all output
  285.     LD    (OFCB+0),A    ; Put it in the drive byte of the output FCB
  286. ;______________________________________________________________________________
  287. ;
  288. ;    *** Come here for each new file ***
  289.  
  290. NXTFIL:
  291.     XOR    A        ; Zero the "EOF flag"
  292.     LD    (EOFLAG),A    ;
  293.     LD    DE,DFCB+1    ; Clear input fcb
  294.     PUSH    DE
  295.     CALL    ZERFCB
  296.     LD    HL,(BUFPTR)
  297.     POP    DE
  298.     PUSH    HL        ; Save filepointer
  299.     LD    BC,11        ; 11 characters
  300.     INC    HL
  301.     LDIR            ; Move next filename in place
  302.     LD    DE,OFCB+1
  303.     CALL    ZERFCB        ; Clean output fcb
  304.     POP    HL
  305.     LD    DE,16        ; Offset to next filename
  306.     ADD    HL,DE
  307.     LD    (BUFPTR),HL
  308.     LD    DE,DFCB
  309.     LD    C,OPEN
  310.     CALL    BDOSAV
  311.     INC    A
  312.     JR    NZ,PRIN        ; Br if successful
  313.  
  314. WERR:    LD    DE,ERR1        ; Else, "Input file not found"
  315.     JP    FATAL
  316.  
  317. TOOMNY:    LD    DE,ERR3        ; "too many matching files"
  318.     JP    FATAL
  319.  
  320. PRIN:    LD    DE,CRLF        ; Print a CR/LF
  321.     CALL    PRINT        ;
  322.     LD    HL,DFCB        ; Print name of input file
  323.     CALL    PRNFIL        ;
  324. ;______________________________________________________________________________
  325. ;
  326. ; Before going too much further, take this opportunity to "clone" a
  327. ; 16 byte template of code into memory 256 times.  This forms the
  328. ; skeleton for the compiled block of code "CODTBL".  Various specific
  329. ; instructions and data will overwrite sections of this template after
  330. ; the dictionary info is read.
  331.  
  332. CLONE:    LD    HL,TMPLAT    ; Xfer one copy to the beg of "CODTBL"
  333.     LD    DE,CODTBL
  334.     LD    BC,16
  335.     LDIR
  336.     LD    HL,CODTBL    ; Now copy it 255 more times.
  337.     LD    BC,255*16    ; De already points to "CODTBL+16"
  338.     LDIR            ; That does it
  339.  
  340. ; Now load up the input buffer.  The input buffer, the output buffer,
  341. ; and "CODTBL" are all page aligned and of page multiple lengths.  There
  342. ; are no other criteria for the lengths of the buffers, except that the
  343. ; input buffer should have a minimum length of 1K plus 1 more page. This
  344. ; guarantees that the entire dictionary (plus miscellaneous header info)
  345. ; will be read in on the 1st pass, simplifying the program.
  346.  
  347.     CALL    RELOAD        ; (leaves HL pointing to beg of "ibuf")
  348.     XOR    A        ; Init the "EOF flag" to zero (again)
  349.     LD    (EOFLAG),A    ; (detects multiple reads of last sector)
  350.     LD    A,(HL)        ; Get first byte of squeezed file
  351.     CP    76H        ; Check for "Squeezed File Header" 76H,FFH
  352.     JR    NZ,NTSQZD    ; Br if not a squeezed file
  353.     INC    L        ; Note buffer starts on a page boundary
  354.     INC    (HL)        ; Chk for ff (clobber it along the way)
  355.  
  356. NTSQZD:    LD    DE,NSQMSG    ; Meanwhile , prep for poss err msg
  357.     JP    NZ,FATAL    ; Fatal "not squeezed" condition
  358.     LD    DE,ARROW    ; " --->"
  359.     CALL    PRINT        ; Ok, print an arrow
  360.     LD    HL,(IBUF+2)    ; Get the 16 bit checksum and save
  361.     LD    (CHKSUM),HL    ; Goes there
  362.     LD    HL,IBUF+3    ; Init past "76FF" and 2 byte checksum (-1)
  363.     LD    DE,OFCB+1    ; Init to point to filename of output fcb
  364.     LD    B,11        ; Set loop cntr for max #of chars in filename
  365.  
  366. EATLP:    INC    L        ;
  367.     LD    A,(HL)        ; Eat up the file name
  368.     OR    A        ; A zero byte indicates end of filename
  369.     JR    Z,ATEIT        ; Br when that is encountered
  370.     AND    7FH        ; Strip off any "attribits"
  371.     CALL    UCASE        ; Upcase char if necessary
  372.     CP    '.'        ; Check for name / ext division char
  373.     JR    Z,ISDOT        ; Br when encountered
  374.     LD    (DE),A        ; Else copy filename char to output fcb
  375.     INC    DE        ; And incr that pointer
  376.     DJNZ    EATLP        ; Continue, but not past filename area of FCB
  377.  
  378.     INC    HL        ; Once more (position should contain "0")
  379.     JR    ATEIT        ; We are done, by definition.
  380.  
  381. ; When "." is encountered, skip to the file extension bytes of the output
  382. ; FCB.  (Any remaining non-extension bytes were init'd to blank).  Do not
  383. ; copy the "." to the output FCB.
  384.  
  385. ISDOT:    LD    DE,OFCB+9    ; Skip to filename .EXT area
  386.     LD    B,3        ; Adjust counter appropriately
  387.     JR    EATLP        ; And continue
  388.  
  389. ATEIT:    PUSH    HL        ; Save current pointer value
  390.     LD    HL,OFCB        ; Print the output filename
  391.     CALL    PRNFIL        ; Print the filename to the console
  392.     POP    HL        ; Restore value
  393.  
  394.     LD    DE,OFCB        ; Output fcb
  395.     LD    C,ERASE        ; "blind erase" the dest file if it exists
  396.     CALL    BDOSAV        ; (*** implement a prompt here? ***)
  397.     LD    C,MAKE        ; In any case, make the new file
  398.     CALL    BDOSAV
  399.     INC    A
  400.     JR    NZ,MAKTBL    ; Err cond check
  401.     LD    DE,ERR2        ; "file open error"
  402.     JP    FATAL        ; Exit
  403. ;______________________________________________________________________________
  404. ;
  405. ;     Now create "CODTBL"  by overwriting certain sections  of  the
  406. ; template  created above.  The dictionary contains 4  byte  nodes-
  407. ; these  are  converted into 16  byte code segments.   The  maximum
  408. ; length  of the original dictionary is  (256*4) bytes (2K) corres-
  409. ; ponding to a maximum "CODTBL" length of 8K.
  410. ;
  411. ;    NODE DEFINITION:  As mentioned above, a "node" consists of two
  412. ; pairs  of bytes.  The first pair corresponds to a zero  bit,  the
  413. ; latter to a "1".  To decode a character, we start at node #0. A
  414. ; bit is pulled off the bit stream. We then use the 1st or 2nd byte
  415. ; pair  depending on the bit value.  The byte pair takes on 1 of  2
  416. ; forms  "nn FF" or "xx 0x".  The "nn FF" type is a terminal  node,
  417. ; it means we have our next output value - that value  specifically
  418. ; being  the 1's complement (makes it more mysterious) of "nn".  If
  419. ; the  node is of the second type, it is a pointer to another  node
  420. ; (an  absolute offset from the beg of the dictionary in  terms  of
  421. ; node#, must be multiplied by 4 for a byte offset.  It has a  max-
  422. ; imum  value  of  256, and is  expressed as  a  16-bit #,  lo-byte
  423. ; first).   In this case we go to that node, pull another  bit  off
  424. ; the input stream, and continue the process.
  425. ;
  426. ;    There  is actually a 3rd node type, which just comes up  once.
  427. ; Its  form is "FF FE".  It's a special end-of-file  marker  called
  428. ; "SPEOF".
  429. ;
  430. ;    HOW THE PROGRAM WORKS:  Each node is converted into a  16-byte
  431. ; (actually  13  plus 3 nop's) series of instructions.   These  in-
  432. ; structions  later perform the unsqueezing operation.   The  whole
  433. ; block of code starts at "CODTBL" (which is also the  entrypoint).
  434. ; Each 13 byte "node code" consists of a 7 byte header.  The header
  435. ; shifts out the next bit from reg "b", then conditionally branches
  436. ; to  the first or second half of the remaining code (3  bytes  per
  437. ; half;  7+3+3  = 13).  The 3 bytes in each half are either  the  2
  438. ; instruc-tions "LD A,<byte>" followed by "RET" (terminal node)  or
  439. ; the  single  instruction "JP <nxtnode>".  All calls  to  "CODTBL"
  440. ; even-tually hit a terminal node and perform a normal return.  The
  441. ; only exception is the special end-of-file node which compiles  to
  442. ; "JP  SPEOF"; on this particular return the stack is manually  ad-
  443. ; justed to compensate for the lack of a "RET" instruction.
  444. ;
  445. ; THE TEMPLATE: This is the "template" which was "cloned" earlier
  446. ;
  447. ;    The  following 3 instructions form the header code  for  every
  448. ; node.  They are identical for every node (since the jump is  rel-
  449. ; ative).
  450. ;..............................................................................
  451.  
  452. TMPLAT:    SRL    B        ; Shift out next bit
  453.     CALL    Z,REFILL    ; Refill reg when empty
  454.     JR    C,BITIS1    ; If bit is "1"
  455. ;..............................................................................
  456. ;
  457. ;    After  the header code gets executed, one of 2 halves  of  the
  458. ; remainder  of the node gets executed.  Which half depends on  the
  459. ; bit shifted out above ("0" for the first half, "1" for the  2nd).
  460. ; Each  half-node has two possible forms.  The terminal form  loads
  461. ; an appropriate value and returns.  The non-terminal form jumps to
  462. ; the  header  of another node. This 16-byte  "node-code  template"
  463. ; assumes  the former case by default, since 2 of 3 bytes  in  that
  464. ; case  are fixed (only the value need be in-serted).  If it  turns
  465. ; out to be the latter case, all 3 bytes will be overwritten with a
  466. ; "jmp" opcode plus an appropriate address.
  467. ;..............................................................................
  468.  
  469. BITIS0:    LD    A,00H        ; (00h gets replaced with actual value
  470.     RET            ; To be returned.)
  471.  
  472. BITIS1:    LD    A,00H        ; 2nd half of the node, likewise
  473.     RET            ;
  474.  
  475.     NOP            ; }
  476.     NOP            ; } so the template is exactly 16 bytes
  477.     NOP            ; }
  478. ;______________________________________________________________________________
  479. ;
  480. ;    --- Create the "node code" table ---
  481.  
  482. MAKTBL:    INC    L        ; Now points one past the filename eof
  483.     LD    E,(HL)        ; Get #of nodes (lo byte)
  484.     INC    L
  485.     LD    D,(HL)        ; Hi byte of same
  486.     INC    L
  487.     LD    A,D
  488.  
  489. ; An additional file validity check: though the #of nodes could in theory
  490. ; theory as high as 0100H, the high byte shoul never be 2 or more
  491.  
  492.     SUB    2        ; If this happens, assume it is not a
  493.     JP    NC,NTSQZD    ; Squeezed file.
  494.  
  495. ; HL indexes through source dictionary (already initialized), & HL' is
  496. ; current dest pointer (indexes thru "codtbl").  DE is initialized to the
  497. ; # of nodes and is decreased to 0.
  498.  
  499.     EXX            ; Init some constants
  500.     LD    DE,10        ; Used for incrementing HL'
  501.     LD    HL,CODTBL+7    ; Init HL' itself
  502.     EXX            ;
  503.  
  504. ; Remember, the whole "header" code and some other instructions are already
  505. ; there (from when "template" was duplicated).  Only specific details need
  506. ; now be filled in.
  507.  
  508. NODELP:    CALL    MAKHAF        ; Make the first ("0") half-node
  509.     CALL    MAKHAF        ; 2nd ("1") half-node
  510.  
  511. ; Source pointer has already been incremented 4 times, as desired. Dest
  512. ; pointer has only been incremented 6 times, however.
  513.  
  514.     EXX            ; }
  515.     ADD    HL,DE        ; } so take care of that
  516.     EXX            ; }
  517.  
  518.     DEC    DE        ; Loop counter
  519.     LD    A,D
  520.     OR    E
  521.     JR    NZ,NODELP    ; Continue till done
  522.     JR    RUN        ; Go run, hl is is ready, pointing to
  523.                 ;  the first byte of squeezed code
  524. ;______________________________________________________________________________
  525. ;
  526. ; Create a "half-node"
  527.  
  528. MAKHAF:    LD    C,(HL)
  529.     INC    HL
  530.     LD    A,(HL)        ; Get a byte pair from the dictionary
  531.     INC    HL
  532.     OR    A        ; If it is negative, it is "terminal"
  533.     JP    M,TERMOD    ; Branch if that is the case.
  534. ;..............................................................................
  535. ;
  536. ; Create code for one half-node of the non-terminal variety.
  537. ; Byte pair is in A,C.  Multiply it by 16 (bytes/node in "codtbl")
  538.  
  539.     SLA    C
  540.     RLA
  541.     SLA    C
  542.     RLA
  543.     SLA    C
  544.     RLA
  545.     SLA    C
  546.     RLA
  547.     ADD    A,CDTBLH    ; Add offset to beginning of "CODTBL",
  548.     LD    B,A        ; Now bc has the jump address
  549.  
  550. ALTENT:    PUSH    BC        ; Save it
  551.     EXX            ; Switch to dest pointers
  552.     LD    (HL),JPOP    ; Insert the "jp" opcode
  553.     INC    L        ; Remember "codtbl" is page aligned
  554.     POP    BC        ; Get addr back
  555.     LD    (HL),C        ; Jump addr, lo
  556.     INC    L        ;
  557.     LD    (HL),B        ; Jump addr, hi
  558.     INC    L        ;
  559.     EXX            ; Back to source pointers
  560.     RET            ; Thats all
  561. ;..............................................................................
  562. ;
  563. ; Create a half-node of the terminal variety
  564.  
  565. TERMOD:    CP    0FEH        ; Check for special eof terminal node
  566.     JR    Z,SPEOF        ; Br for that unique case
  567.     LD    A,C        ; Else this byte is the complement of
  568.                 ; The returned value
  569.     CPL
  570.     EXX            ; Switch to dest pointers
  571.     INC    L        ; Just 2nd of 3 bytes need be inserted
  572.     LD    (HL),A        ; Put it in
  573.     INC    L        ;
  574.     INC    L        ; But make sure hl gets incr'd 3 times
  575.     EXX            ;
  576.     RET            ; That's all
  577. ;..............................................................................
  578. ;
  579. ; Special EOF returns to a special address in mainline code, rather
  580. ; than using "RET".  Stack is adjusted accordingly there.
  581.  
  582. SPEOF:    LD    BC,DONE        ; The special address
  583.     JR    ALTENT        ; Use convenient code subsection above
  584. ;______________________________________________________________________________
  585. ;
  586. ; Code to refill register 'B' with the next byte
  587.  
  588. REFILL:    INC    L
  589.     JR    Z,POSRLD    ; If l is zero, may be at end of buffer
  590.  
  591. CONT:    LD    B,(HL)        ; Else get next byte
  592.  
  593. ; Now we pre-shift out the next bit, shifting in a "1" from the left.
  594. ; Since the leftmost bit in the reg is a  guaranteed "1", testing the
  595. ; zero stat of the reg is a necesssary and sufficient condition for
  596. ; determining that all the bits in the reg have   been used up (see
  597. ; header code for "TMPLATE").  The only things to be careful of is that
  598. ; the the last bit is NOT used, and that the bit now in the carry flag
  599. ; IS used upon return from this subroutine.
  600.  
  601.     SCF            ; To shift in the flag bit
  602.     RR    B        ; Shift out real bit as described
  603.     RET            ; That's it
  604.  
  605. POSRLD:    INC    H        ; Check if time to reload the input
  606.     LD    A,EIBFHI    ; Buffer with additional data.
  607.     CP    H        ;
  608.     CALL    Z,RELOAD    ; Reload if necessary (resets hl)
  609.     JR    CONT
  610. ;______________________________________________________________________________
  611. ;
  612. ; Main code to perform the unsqueeze. In general, the alternate regs
  613. ; are used as output pointers, flags, etc. while the primary registers
  614. ; are used for input pointing and general purpose use.
  615.  
  616. RUN:    EXX            ; First initialize the alternate regs
  617.     LD    HL,OBUF        ; HL', output pntr, to beg of output bfr
  618.     LD    BC,0        ; C' always has a copy of the previous
  619.     EXX            ;  char output;    B' is a "repeat flag".
  620.  
  621. ; Primary register initialization: initialize HL, the input pntr, to point to
  622. ; the first byte of squeezed code -1. Initialize DE, the checksum accumulator,
  623. ; to zero.  Initialize 'B', which contains bits currently being decoded, to
  624. ; to 0 so first "decode" call will immediately load it with the first byte.
  625.  
  626.     DEC    HL        ; First byte of squeeze code -1
  627.     LD    DE,0        ; Checksum accumulator
  628.     LD    B,D        ; (zero)
  629. ;..............................................................................
  630. ;
  631. ;    *** Main operational loop ***
  632.  
  633. MAINLP:    CALL    CODTBL        ; Unsqueeze a character
  634.     CALL    SEND        ; Output it to the output buffer
  635.     JR    MAINLP        ; And repeat "forever" (see "SPEOF"
  636. ;______________________________________________________________________________
  637. ;
  638. ; Reload the input buffer, & reset HL to point to the beginning of it.
  639. ; Assumes input bfr starts page boundry and is of page multiple length.
  640.  
  641. RELOAD:    PUSH    AF
  642.     PUSH    BC
  643.     PUSH    DE
  644.     LD    B,IBUFSZ    ; Loop counter, buffer length in pages
  645.     LD    D,IBUFHI    ; Beg of buffer (hi)
  646.  
  647. RLDLP:    LD    E,0        ; Lo byte of current dma
  648.     CALL    RDSEC        ; Read in 128 bytes (1/2 page)
  649.     JR    NZ,RLDRTN    ; (return if eof enecountered)
  650.     LD    E,80H        ; To read in the next half page
  651.     CALL    RDSEC        ; Do that
  652.     JR    NZ,RLDRTN    ; As above
  653.     INC    D        ; Next page
  654.     DJNZ    RLDLP        ; Loop till done
  655.  
  656. RLDRTN:    POP    DE        ; Restore regs
  657.     POP    BC
  658.     POP    AF
  659.     LD    HL,IBUF        ; Reset input pointer
  660.     RET            ; And return
  661. ;..............................................................................
  662. ;
  663. ; Subr for abover, reads 128 bytes to memory starting at HL
  664.  
  665. RDSEC:    PUSH    DE        ; Save dma before clobbering it with fcb
  666.     LD    C,SETDMA    ; Set dma function
  667.     CALL    BDOSAV        ;
  668.     LD    DE,DFCB        ; Input fcb
  669.     LD    C,READ        ;
  670.     CALL    BDOSAV        ; Read a record
  671.     POP    DE        ; Restore dma to original dma address
  672.     OR    A        ; Set non-zero status
  673.     RET    Z        ; Normal return, barring EOF condition
  674.  
  675.     LD    A,(EOFLAG)    ; Check if EOF is hit twice
  676.     OR    A        ;
  677.     JR    NZ,HTCHED    ; This is an abnormal condition
  678.     CPL            ; Else (first EOF) put "FF" in "eoflag"
  679.     LD    (EOFLAG),A    ;
  680.     OR    A        ; Set non-zero status and return
  681.     RET            ;
  682.  
  683. HTCHED:    LD    DE,CHOPPD    ; "Unexpected EOF enountered"
  684.     JP    FATAL        ; (file is truncated or damaged)
  685. ;______________________________________________________________________________
  686. ;
  687. ; When "SPEOF" is encountered, a jump to here is made to exit "CODTBL"
  688. ; rather than the normal RET instruction.
  689.  
  690. DONE:    INC    SP        ; So adjust the stack immediately!
  691.     INC    SP        ;
  692.     LD    A,(CHKSUM+0)    ; Make sure the checksum checks out
  693.     CP    E        ; Lo-byte
  694.     JR    NZ,NFG        ; Br if nfg
  695.     LD    A,(CHKSUM+1)    ; Likewise
  696.     CP    D        ;
  697.     JR    Z,CKSMOK    ; Ok
  698.  
  699. ; If a checksum error is detected, report the warning. Let the guy
  700. ; have his file anyway, for whats its worth.
  701.  
  702. NFG:    LD    DE,CHKERR    ; "checksum error detected"
  703.     CALL    MESAGE        ;
  704.  
  705. ; Switch to alternate regs for output. The total #of bytes generated
  706. ; should always be a multiple of 128.  This assumption is not made,
  707. ; however, as it may not be true if the file was squeezed on non-CP/M
  708. ; systems.  Compute # of sectors to write- specifically subtract the
  709. ; buffer start addr from the current pointer value, add 7FH and divide
  710. ; by 128. If the byte count  was in fact a multiple of 128, this has
  711. ; no effect; otherwise it makes sure the final sector gets written.
  712.  
  713. CKSMOK:    EXX            ; Switch to alt regs
  714.     AND    A        ; Clear carry
  715.     LD    DE,OBUF-7FH    ; Take care of adding 7fh in advance
  716.     SBC    HL,DE        ; Subtract
  717.     SLA    L        ; Divide by 128
  718.     RL    H        ; Result now in h
  719.     LD    B,H        ; Use 'b' as the counter
  720.     CALL    WRTOUT        ; Writes 'b' sectors to the output file
  721.     EXX            ; Back to primary regs
  722.  
  723.     LD    DE,OFCB        ; Close the output file
  724.     LD    C,CLOSE
  725.     CALL    BDOSAV
  726.  
  727.     LD    DE,DFCB        ; Likewise the input file
  728.     LD    C,CLOSE
  729.     CALL    BDOSAV
  730.  
  731. ; Fall through
  732.  
  733. EXIT:    LD    HL,(NMBFLS)
  734.     DEC    HL
  735.     LD    (NMBFLS),HL
  736.     LD    A,H
  737.     OR    L
  738.     JP    NZ,NXTFIL    ; Next file
  739.     LD    SP,(OLDSTK)    ; Restore os stack
  740.     RET            ; To ccp
  741.  
  742. ;______________________________________________________________________________
  743. ;
  744. ; Write 'B' 128 byte sectors to the output file
  745. ;
  746. WRTOUT:
  747.     LD    A,B        ; If b=0, don't write any sectors
  748.     OR    A        ;
  749.     RET    Z        ;
  750.  
  751.     LD    DE,OBUF        ; Init dma addr to beg of output bfr
  752.  
  753. WRTLP:    LD    C,SETDMA    ; Set dma to there
  754.     CALL    BDOSAV
  755.     PUSH    DE        ; Save that address
  756.     LD    DE,OFCB        ; Specify the output file
  757.     LD    C,WRITE        ; Write a record
  758.     CALL    BDOSAV        ;
  759.     OR    A
  760.     JR    NZ,WRTERR    ; Br on error
  761.     POP    DE        ; Address as saved above
  762.     DJNZ    NEXSEC        ; Decrement counter & continue if not done
  763.     RET            ;
  764.  
  765. NEXSEC:    LD    E,80H        ; Else incr by 1/2 page
  766.     LD    C,SETDMA    ;
  767.     CALL    BDOSAV        ;
  768.     PUSH    DE        ; Save dma pntr
  769.     LD    DE,OFCB        ; Output fcb
  770.     LD    C,WRITE        ; Write another sec
  771.     CALL    BDOSAV        ;
  772.     OR    A        ;
  773.     JR    NZ,WRTERR    ; Br if error
  774.     POP    DE        ; Get back orig pointer
  775.     INC    D        ; Inc hi-byte, 0 the lo to effect
  776.     LD    E,0        ; Another 80h incr
  777.     DJNZ    WRTLP        ; Loop till done
  778.  
  779.     RET
  780. ;______________________________________________________________________________
  781. ;
  782. BDOSAV:                ; Bdos call w/ all regs and alts saved
  783.     EXX            ;  except for AF, AF', IX, & IY
  784.     PUSH    BC
  785.     PUSH    DE
  786.     PUSH    HL
  787.     EXX
  788.     PUSH    BC
  789.     PUSH    DE
  790.     PUSH    HL
  791.     CALL    BDOS
  792.     POP    HL
  793.     POP    DE
  794.     POP    BC
  795.     EXX
  796.     POP    HL
  797.     POP    DE
  798.     POP    BC
  799.     EXX
  800.     RET
  801.  
  802. WRTERR:    LD    DE,WRTMSG    ; Write error, falls through to "fatal"
  803. ;______________________________________________________________________________
  804. ;
  805. ; For fatal errors- print the message, restore the os stack & return
  806. ; This rountine is "jumped to", not called
  807. ;
  808. FATAL:    CALL    MESAGE        ;
  809.     LD    DE,CRLF        ;
  810.     CALL    PRINT        ;
  811.     LD    SP,(OLDSTK)    ; Restore stack pointer Z80-style
  812.     RET            ;
  813.  
  814. MESAGE:    EX    DE,HL        ; Save pntr to message (supplied in de)
  815.     LD    DE,CRLF        ; First print a cr/lf sequence
  816.     LD    C,PRTSTR
  817.     CALL    BDOSAV
  818.     EX    DE,HL        ; Then the message in question
  819.  
  820. PRINT:    LD    C,PRTSTR    ; Entry here if no cr/lf desired
  821.     JP    BDOSAV
  822.  
  823. MESS80:    LD    C,PRTSTR    ; For non-Z80 mesage, don't use "BDOSAV"
  824.     JP    BDOS        ;
  825. ;______________________________________________________________________________
  826. ;
  827. ; Send character to the output buffer, plus related processing
  828. ;
  829. SEND:    EXX            ; Alt regs used for output processing
  830.     SRL    B        ; If reg is "1", repeat flag is set
  831.                 ; (note, clears itself automatically)
  832.     JR    C,REPEAT    ; Go perf the repeat
  833.     CP    90H        ; Else see if char is the repeat spec
  834.     JR    Z,SETRPT    ; Br if so
  835.     LD    C,A        ; Else nothing special- but always keep
  836.     CALL    OUT        ; Else just output the char;
  837.     EXX            ; Back to normal regs
  838.     RET            ;
  839.  
  840. ; Set repeat flag; count value will come as the next byte. (Note: don't
  841. ; clobber C with the "90H"- it still has the prev character, the one to
  842. ; be repeated)
  843.  
  844. SETRPT:    INC    B        ; Set flag
  845.     EXX            ; Switch to primary regs & return.
  846.     RET
  847.  
  848. ; Repeat flag was previously set; current byte in a is a count value.
  849. ; A zero count is a special case which means send 90H itself.  Otherwise
  850. ; use B (was the flag) as a counter. The byte itself goes in A.
  851.  
  852. REPEAT:    OR    A        ; Check for special case
  853.     JR    Z,SND90H    ; Jump if so
  854.     DEC    A        ; Compute "count-1"
  855.     LD    B,A        ; Juggle registers
  856.     LD    A,C        ;
  857.  
  858. AGAIN:    CALL    OUT        ; Repeat b occurrences of byte in 'a'
  859.     DJNZ    AGAIN        ; Leaves b, the rpt flag, 0 as desired
  860.     EXX            ; Restore regs & rtn
  861.     RET
  862.  
  863. SND90H:    LD    A,90H        ; Special case code to send the byte 90h
  864.     CALL    OUT        ; Itself
  865.     EXX            ;
  866.     RET            ; (90h "squeezes" into 2 bytes!)
  867. ;..............................................................................
  868. ;
  869. ; Output character in 'A' directly to the output buffer
  870. ;
  871. OUT:    EXX            ; Back to primary regs briefly
  872.     LD    C,A        ; Save a in c
  873.     ADD    A,E        ; De is the running checksum
  874.     LD    E,A
  875.     JR    NC,NOCARY
  876.     INC    D
  877.  
  878. NOCARY:    LD    A,C        ; Put the char back into a
  879.     EXX            ; Back to output (alternate) regs
  880.  
  881.     LD    (HL),A        ; Put byte into the next avail position
  882.     INC    L        ; Increment pointer
  883.     RET    NZ        ; Return if not passing a page boundry
  884.     INC    H        ; Incr pointer high byte, check limit
  885.     LD    L,A        ; Use l, which is 0, for temp storage
  886.     LD    A,EOBFHI    ; Limit
  887.     CP    H        ; Check
  888.     LD    A,L        ; But first restore regs
  889.     LD    L,0        ;
  890.     RET    NZ        ; Ret if limit not reached
  891.     PUSH    AF
  892.     PUSH    BC
  893.     LD    B,OBUFSZ*2    ; Number of 128 byte records to write
  894.     CALL    WRTOUT
  895.     POP    BC
  896.     POP    AF
  897.     LD    HL,OBUF
  898.     RET
  899.  
  900. ;______________________________________________________________________________
  901. ;
  902. ; Initialize an FCB.  DE points to the FCB +1.
  903. ;
  904. ZERFCB:    LD    B,11        ; Fill filename with blanks
  905.     LD    A,' '
  906.     CALL    ZL
  907.     LD    B,24        ; Then zero remainder
  908.     XOR    A
  909. ZL:    LD    (DE),A
  910.     INC    DE
  911.     DJNZ    ZL
  912.     RET
  913. ;______________________________________________________________________________
  914. ;
  915. ; Print name of output file. HL should point to the FCB.
  916. ;
  917. PRNFIL:    LD    A,(HL)        ; Get drive spec
  918.     INC    HL        ; Move to 1st char of filename
  919.     OR    A        ; Drive = default?
  920.     JR    Z,DEFDRV    ; Br if so
  921.     ADD    A,'A'-1        ; Else convert to a letter
  922.     CALL    TYPE        ;
  923.     LD    A,':'        ; Follow drive spec with a ":"
  924.     CALL    TYPE        ;
  925.  
  926. DEFDRV:    LD    B,12        ; Loop cntr (max #of chars plus ".")
  927.  
  928. CHARLP:    LD    A,(HL)        ; Get a char
  929.     CP    " "        ; Blank?
  930.     JR    Z,SKPTYP    ; Supress them
  931.  
  932. TYPEIT:    CALL    TYPE        ; Type the char
  933.  
  934. SKPTYP:    DEC    B        ; Loop counter
  935.     RET    Z        ; Rtn when done
  936.  
  937.     LD    A,B        ; Check loop counter
  938.     CP    4        ; At this point, type a "."
  939.     JR    NZ,NOT4        ;
  940.     LD    A,"."        ;
  941.     JR    TYPEIT        ; Type it. do not incr hl or reload a.
  942.  
  943. NOT4:    INC    HL        ; Advance pointer
  944.     JR    CHARLP        ; Repeat till done
  945. ;______________________________________________________________________________
  946. ;
  947. TYPE:    LD    C,CONOUT    ; Type the char in "a" to the console
  948.     LD    E,A        ; (clobbers c & e)
  949.     CALL    BDOSAV        ;
  950.     RET            ;
  951. ;______________________________________________________________________________
  952. ;
  953. ;WILDEX - wildcard expansion module
  954. ; S. Kluger  04/15/84
  955. ;
  956. ; This module, for use with SYSLIB, can be used to expand a wildcard
  957. ; filename into a table of file names as found in current DU:
  958.  
  959. ; ENTRY:
  960. ; HL = .buffer
  961. ; DE = .afn fcb
  962.  
  963. ; EXIT:
  964. ; HL = number of files
  965. ; ACC= zero flag set if error
  966. ; the buffer contains HL file names of 16 char each
  967. ; Char 0 contains the user number!
  968.  
  969. WILDEX:    LD    (BUFPTR),HL
  970.     LD    HL,0
  971.     LD    (NMBFLS),HL
  972.     LD    C,SFIRST
  973.     CALL    BDOSAV
  974.     CP    0FFH
  975.     RET    Z        ; Nothing found -- error
  976.     CALL    MOVEN        ; Move name
  977. WLOOP:    LD    C,SNEXT        ; Search for next
  978.     CALL    BDOSAV
  979.     CP    0FFH
  980.     JR    Z,DONEW        ; Finished
  981.     CALL    MOVEN
  982.     JR    WLOOP
  983.  
  984. DONEW:    OR    A
  985.     LD    HL,(NMBFLS)
  986.     RET
  987.  
  988. MOVEN:    PUSH    DE
  989.     LD    HL,(BUFPTR)
  990.     ADD    A,A
  991.     ADD    A,A
  992.     ADD    A,A
  993.     ADD    A,A
  994.     ADD    A,A
  995.     ADD    A,80H
  996.     LD    C,A
  997.     LD    B,0
  998.     LD    D,16        ; Move 16 chars
  999. MOVLP:    LD    A,(BC)
  1000.     LD    (HL),A
  1001.     INC    HL
  1002.     INC    BC
  1003.     DEC    D
  1004.     JR    NZ,MOVLP
  1005.     LD    (BUFPTR),HL
  1006.     POP    DE
  1007.     LD    HL,(NMBFLS)
  1008.     INC    HL
  1009.     LD    (NMBFLS),HL
  1010.     RET
  1011. ;______________________________________________________________________________
  1012. ;
  1013. UCASE:                ; "Upcase" the letter in "A", if necessary
  1014.     CP    'a'        ;
  1015.     RET    C        ; If < "a", forget it
  1016.     CP    'z'+1        ;
  1017.     RET    NC        ; Likewise if > "z"
  1018.     SUB    20H        ; Else convert
  1019.     RET            ;
  1020. ;______________________________________________________________________________
  1021.  
  1022. LOGO:    DEFB    'Fast Unsqueezer v2.0',CR,LF,'$'
  1023. ERR1:    DEFB    'Input file not found.$'
  1024. ERR2:    DEFB    'File open error.$'
  1025. ERR3:    DEFB    'Too many matching files.$'
  1026. ARROW:    DEFB    ' ---> $'
  1027. LAKMEM:    DEFB    'Out of memory.$'
  1028. NSQMSG:    DEFB    'Not a squeezed file.$'
  1029. CHKERR:    DEFB    'Checksum error detected.$'
  1030. WRNGUP:    DEFB    'Program needs Z-80.$'
  1031. WRTMSG:    DEFB    'Output error.$'
  1032. CHOPPD:    DEFB    'Unexpected EOF encountered.$'
  1033. USAGE:    DEFB    'Usage: UF  [d:] <afn> [d:]',CR,LF
  1034.     DEFB    ' optional drive specs are source & dest. respectively.$'
  1035. CRLF:    DEFB    CR,LF,'$'
  1036. ;______________________________________________________________________________
  1037. ;
  1038. BUFPTR:    DEFW    0        ; Used for indexing thru "fnbuff"
  1039. NMBFLS: DEFW    0        ; #of wild card matches found
  1040. ;..............................................................................
  1041.  
  1042. CHKSUM:    DS 2            ; Checksum kept here
  1043. EOFLAG:    DS 1            ; "EOF Flag"; set from 0 to FF when EOF is hit
  1044. OFCB:    DS 36            ; Output fcb; gets initialized by "zerfcb"
  1045.  
  1046. MAXFLS    EQU    400        ; Max #of filenames in a wild card expansion
  1047.                 ;  (should be sufficient!)
  1048. FNBUFF:    DS (16*MAXFLS)        ; Wildcard expansion buffer
  1049. ENDFNB    EQU $            ; End of above buffer
  1050. ;______________________________________________________________________________
  1051. ;
  1052. ; Compute next page boundary following the end of the above buffer. Do
  1053. ; this by adding 0FFH and "anding" with 0FF00H. This will become the
  1054. ; beginning of "CODTBL".
  1055.  
  1056. ; *** NOTE ***  [sgg]
  1057. ;      If this code is CSEG'd, M80 will reject this. You can fake
  1058. ;    out the assembler using a "HIGH" , then multiplying by 256,
  1059. ;    but then it will link incorrectly. If you just EQU "codtbl",
  1060. ;    the resulting code isn't really relocatable anyway...
  1061. ;
  1062. ;      I think there are ways around this, but they involve the
  1063. ;    assumption that this whole file is "page relocatable" only.
  1064.  
  1065. PGBND    EQU    (ENDFNB+0FFH) AND 0FF00H ; (works with aseg only)
  1066.     ORG    PGBND
  1067. ;..............................................................................
  1068. ;
  1069. ; Minimum input buffer size is 5 pages to guarantee that the max possible
  1070. ; dictionary size (256 x 4) bytes plus overhead) loads the first pass.
  1071. ;
  1072. ; Output buffer can be any page multiple length (note it too is also page
  1073. ; aligned).  Increases beyond 64 pages (16k) may do little to improve perf.
  1074.  
  1075. IBUFSZ    EQU    16        ; Input buffer size (pages)
  1076. OBUFSZ    EQU    64        ; Output buffer size (pages)
  1077. PAGE    EQU    256        ; (for clarity)
  1078.  
  1079. CODTBL:    DS    256*16        ; "codtbl"; 256 entries x 16 bytes/entry
  1080. IBUF:    DS    IBUFSZ*PAGE    ; Input buffer
  1081. OBUF:    DS    OBUFSZ*PAGE    ; Output buffer
  1082. EOBUF    EQU    $        ; End of output buffer
  1083.  
  1084. CDTBLH    EQU    HIGH CODTBL    ; }
  1085. IBUFHI    EQU    HIGH IBUF    ; } high bytes of the beginning addresses
  1086. EIBFHI    EQU    HIGH OBUF    ; }  of the buffers just defined
  1087. EOBFHI    EQU    HIGH EOBUF    ; }
  1088.  
  1089.     END
  1090. et i    CP    'z'+1            RET    NC        ; Likewise if > "z    SUB    20H        ; Else conver    RET            ;___________