home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / robot-pd / 22300.ZIP / 22300B.DSK / ucrlzh20.z80 < prev    next >
Text File  |  1998-05-08  |  42KB  |  1,283 lines

  1.     .SALL
  2.     TITLE 'UNCRrunch LZH v2.0  20 July 1991'
  3. ;************************************************************************
  4. ;*                                    *
  5. ;*               UNCRunch LZH v2.0                *
  6. ;*                  20 July 1991                *
  7. ;*                           - Roger Warren    *
  8. ;************************************************************************
  9. ;
  10. ;    With the kind permission of Mr. Steven Greenberg, author of 
  11. ;    UNCRunch, this program was generated from his UNCRunch v2.4 code
  12. ;    dated 15 Sept 1987.  Accordingly, the following notifications
  13. ;    are in order:
  14. ;
  15. ;     Portions Copyright (c)   S. Greenberg  09/15/87
  16. ;     Portions Copyright (c)   R. Warren     07/20/91
  17. ;    May be reproduced for non-profit use only
  18. ;
  19. ;    You can distribute it AS IS or modify it for your OWN use,
  20. ;    but public release of modified versions (source or object
  21. ;    files) without permission is prohibited, nor can it be sold.
  22.  
  23. ;UNCRLZH HISTORY:
  24. ; v2.0 Re-released because of new CRLZH algorithm changes.  Version 2.0
  25. ;    of CRLZH is 10% FASTER and compresses further than V1.1.  The output
  26. ;    files must be de-compressed with UNCRLZH version 2.0, which replaces
  27. ;    UNCRLZH 1.1.  UNCRLZH 2.0 handles LZH encoded files of both versions
  28. ;    as well as CRUCNCHED and SQUEEZED files.
  29. ;    With the kind permission of Gene Pizzetta, changes made to UNCR
  30. ;    thru version 2.8 have been incorporated into this program
  31. ;    taken from Steve Greenberg's version 2.4.  This program will
  32. ;    NOW handle date stamps ala ZSDOS.
  33. ;
  34. ; v1.1 Official first release.  No functional changes from Beta version.
  35. ;     Merely stepped version for differentiation.
  36. ;
  37. ; v1.0 Beta test version
  38.  
  39. VERS    EQU    20
  40. SUBVERS    EQU    ' '
  41.  
  42.     .Z80
  43.  
  44.     CSEG
  45.  
  46. NO    EQU    0
  47. YES    EQU    NOT NO
  48. N    EQU    NO
  49. Y    EQU    YES
  50. CRUNCH    EQU    NO        ; Yes for CRUNCH, no for UNCR (for common)
  51. ;ZSYS    EQU    YES        ; Yes if exclusively for Z-System
  52.     .ACCEPT    'ZCPR3-Only Version [Y/N] ? ',ZSYS
  53.  
  54. ;=======================================================================
  55.  
  56.   IF ZSYS
  57.  
  58. MEMPAG    EQU    2300H        ; <== set! [see comment near end of program]
  59.  
  60.   ELSE    ; ZSYS
  61.  
  62. MEMPAG    EQU    2500H        ; <== set! [see comment near end of program]
  63.  
  64.   ENDIF    ; ZSYS
  65.  
  66. ;=======================================================================
  67.  
  68. REV    EQU    (VERS/10*16)+(VERS MOD 10) ; Program revision level in BCD
  69. SIGREV    EQU    20H        ; "Significant" revision level (compatibility)
  70. SIGRVY    EQU    20H        ; "Significant" revision level for LZH
  71.  
  72. NOPRED    EQU    0FFFFH        ; "No predecessor"
  73. IMPRED    EQU    07FFFH        ; Pred that can't be matched or bumped
  74.  
  75. SCRUPT1    EQU    01H        ; Screen update speeds
  76. SCRUPT2    EQU    07H
  77.  
  78. ; --- Reserved codes ---
  79.  
  80. EOFCOD    EQU    100H        ; EOF code
  81. RSTCOD    EQU    101H        ; Adaptive reset code
  82. NULCOD    EQU    102H        ; Null code
  83. SPRCOD    EQU    103H        ; Spare code
  84.  
  85. ; --- ASCII equates ---
  86.  
  87. CTRLC    EQU    03H        ; ^c
  88. BELL    EQU    07H        ; Beep
  89. BS    EQU    08H        ; Backspace
  90. LF    EQU    0AH        ; Linefeed
  91. CR    EQU    0DH        ; Carriage return
  92.  
  93. ; --- CP/M address equates ---
  94.  
  95. DFCB    EQU    5CH        ; Default FCB #1
  96. DFCB2    EQU    6CH        ; Default FCB #2
  97. DDMA    EQU    80H        ; Default DMA address
  98. BDOS    EQU    0005H        ; BDOS entry point
  99.  
  100. ; --- BDOS function equates ---
  101.  
  102. CONIN    EQU    1        ; Input a character from the console
  103. CONOUT    EQU    2        ; Output single char to console
  104. PRTSTR    EQU    9        ; Print string to console
  105. CONST    EQU    11        ; Get console status
  106. GETVER    EQU    12        ; Get CP/M version #
  107. SELDSK    EQU    14        ; Select disk
  108. OPEN    EQU    15        ; Open file
  109. CLOSE    EQU    16        ; Close file
  110. SFIRST    EQU    17        ; Search for first file
  111. SNEXT    EQU    18        ; Search for next file
  112. ERASE    EQU    19        ; Erase file
  113. READ    EQU    20        ; Read file (sequential)
  114. WRITE    EQU    21        ; Write file (sequential)
  115. MAKE    EQU    22        ; Make file
  116. GETDSK    EQU    25        ; Get currently logged drive
  117. SETDMA    EQU    26        ; Set DMA address
  118. GSUSER    EQU    32        ; Get/set user code
  119. RSTDRV    EQU    37        ; Reset drive
  120. SETMS    EQU    44        ; Set multi-sector count (cp/m+ only)
  121. GETDMA    equ    47        ; ZSDOS get current DMA address
  122. EXDOSV    equ    48        ; ZSDOS extended BDOS version
  123. GETFSTP    equ    102        ; ZSDOS get file stamp
  124. SETFSTP    equ    103        ; ZSDOS set file stamp
  125.  
  126. ;-----------------------------------------------------------------------
  127.  
  128.     EXTRN    USQREL,UNCR1
  129.  
  130.   IF NOT ZSYS
  131.     EXTRN    PARSEU
  132.   ENDIF    ; NOT ZSYS
  133.  
  134.     EXTRN    UNLZH
  135.  
  136.     ENTRY    GETBYT,OUT
  137.     ENTRY    GLZHUN,PLZHUN    ; for UNLZH
  138.  
  139. ;_______________________________________________________________________
  140. ;
  141. ; Macros to facilitate "horizontal" movement through the table.
  142. ; See "Table structure" comment near "initbl" for more information.
  143.  
  144. RIGHT1     MACRO
  145.     LD    A,H        ; }
  146.     ADD    A,10H        ; } move "right" one column (same row)
  147.     LD    H,A        ; }
  148.      ENDM
  149.  
  150. ;.......................................................................
  151.  
  152. START:    JP    STRT        ; <--- entry
  153.     DB    'Z3ENV',01H    ; ZCPR3 environment descriptor
  154. Z3ED:    DW    00h
  155.  
  156. ;-----------------------------------------------------------------------
  157.  
  158.     DW    0        ; filler
  159.     DB    'CRLZH'        ; for ZCNFG
  160.     DB    VERS/10+'0',VERS MOD 10+'0'
  161.     DB    ' '        ; Filler
  162. ARCHIV:    DB    0        ; Archive mode (not used, for CRUNCH)
  163. QUIFL:    DB    0        ; Quiet mode flag
  164. NPROFL:    DB    0        ; No prompt before overwrite flag
  165. TRBOFL:    DB    0        ; Defeat multi-sector i/o flag
  166. CNFRFL:    DB    0        ; Confirm every file flag
  167. WRMFLG:    DB    0        ; Warm boot flag
  168. BIGFLG:    DB    0        ; Bigger file prompt flag
  169. MAXUSR:    DB    31        ; Maximum user allowed by program
  170. MAXDRV:    DB    16        ; Maximum drive allowed by program
  171. SYSFL:    DB    0        ; System file inclusion flag
  172. TYPFL:    DB    'Y'        ; Default filetype (UNCRLZH only)
  173.  
  174. ;......................................................................
  175. ;
  176. ; File type exclusion list.  (for CRUNCH, not used by UNCR)
  177.  
  178. EXTBL:    DB    '               '    ; filled with spaces
  179.     DB    '               '
  180.  
  181. ;=*=-=*=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=
  182.  
  183. CPYRT:    DB    'UNCRLZH '
  184.   IF ZSYS
  185.     DB    'Z-'
  186.   ENDIF    ; ZSYS
  187.     DB    'Version ',VERS/10+'0','.',VERS MOD 10+'0',SUBVERS
  188.     DB    ' Copyright (c) 1987 by S. Greenberg',CR,LF
  189.         DB    '        Portions  Copyright (c) 1991 by R. Warren',CR,LF
  190.     DB    ' May be used/reproduced for non-profit use only',CR,LF,LF,'$'
  191.  
  192. ;=*=-=*=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=
  193.  
  194. STRT:
  195.   IF ZSYS
  196.     LD    HL,(Z3ED)    ; check for ZCPR3
  197.     LD    A,H
  198.     OR    L
  199.     JP    NZ,Z80
  200.   ELSE    ; ZSYS
  201.     SUB    A        ; Z-80 test [RAF]
  202.     JP    PO,Z80
  203.   ENDIF    ; ZSYS
  204.     LD    DE,WRNGUP    ; "Program requires Z-80 processor"
  205.     JP    MESS80        ; No frills exit w/ message
  206.  
  207. Z80:    LD    (OLDSTK),SP    ; Save os's stack
  208.     LD    SP,TOPSTK    ; Set local stack
  209.     CALL    STRTUP        ; Does a lot of stuff
  210.  
  211. ;=======================================================================
  212. ;
  213. ;    *****    Re-enter here for each matching file *****
  214. ;
  215. ; General wildcard operation:  When the program is first invoked, a ll
  216. ; matching filenames are put end to end in FNBUFF, 12 bytes each, in
  217. ; alalphabetical order.  Since a filename is only 11 characters long,
  218. ; the spare byte, which precedes each filename, is used as a "tag/flag".
  219. ; By the time file processing starts (now), a number of routines have
  220. ; already run (parts  of the STRTUP routine).  These routines set the
  221. ; tag-flag which indicates to us now in what manner the file should be
  222. ; processed:  "00" = "skip it", "01" = process it", "02" = "perform a
  223. ; direct copy (if possible)", "FF" = "no more files".
  224.  
  225. NXTFIL:    LD    SP,TOPSTK    ; 'just in case'
  226.     LD    A,CR
  227.     CALL    TYPE
  228.     XOR    A        ; clear embedded date flag
  229.     LD    (DATFLG),A
  230.     LD    (YFLAG),A    ; ..and lzh flag
  231.     LD    DE,INFCB    ; Input file fcb
  232.     CALL    CLRFCB        ; Init it to blanks and zeroes
  233.     INC    DE        ; Leave "DE" pointing at infcb+1 for below
  234.     LD    HL,(BUFPTR)    ; Pntr to name of next file from expansion bfr
  235. NXTSEL:    LD    A,(HL)
  236.     OR    A        ; If zero, the file is "unselected"
  237.     JR    NZ,ISSEL    ; Br if it is selected
  238.     LD    BC,12        ; Else just quietly skip to the next file
  239.     ADD    HL,BC
  240.     LD    (BUFPTR),HL
  241.     JR    NXTSEL
  242.  
  243. ;...............................
  244. ;
  245. ; The file is "selected"; prepare to process it
  246.  
  247. ISSEL:    CP    0FFH        ; An "FF" means done
  248.     JP    Z,RETCCP    ; Br if that is the case
  249.     PUSH    AF        ; Save stat (to see if file is "excluded" blw)
  250.  
  251.     LD    A,(QUIFM)
  252.     OR    A
  253.     PUSH    DE
  254.     LD    DE,DASHES    ; "-----" for visual separation
  255.     CALL    Z,MESAG2
  256.     POP    DE
  257.  
  258.     INC    HL        ; Skip to 1st filename char
  259.     LD    BC,11        ; Filename character count
  260.     LDIR            ; Put next file name into input fcb
  261.     LD    (BUFPTR),HL    ; Save new pointer for next file
  262.     CALL    INTRAM        ; Initialize all ram
  263.     LD    A,80H        ; (init'd by "INTRAM", but must be init'd
  264.     LD    (CSAVE),A    ; - differently for CRUNCH & UNCRunch)
  265.     POP    AF        ; Get file's status byte back again
  266.     CP    02H        ; 02 if file matched the "exclusion" list
  267.     JR    NZ,COPNIN    ; If not, definitly attempt to uncompress it
  268.     LD    A,(WLDFLG)    ; If so, see if prgm was invoked w/ wildcards
  269.     OR    A        ;
  270.     JP    NZ,COPY9    ; If so, do not uncompress; do a straight copy
  271.  
  272. ;.......................................................................
  273. ;
  274. ; Now open the input file.  A failure here is unusual, since the file
  275. ; existed at the time the filename expansion took place.  There are
  276. ; "normal" series of events which could lead up to this, however.
  277.  
  278. COPNIN:    CALL    OPNIN        ; Attempt to open the next input file "INFCB"
  279.     JR    NC,OPOK        ; Br if ok
  280.     LD    DE,ERR1        ; "input file not found"
  281.     JP    SKIP1        ; Skip to next file
  282.  
  283. ;.......................................................................
  284. ;
  285. ; If we got here, the input file is open.  The output file is not
  286.  
  287. OPOK:    LD    DE,OUTFCB    ; Now for the output fcb
  288.     CALL    CLRFCB        ; Clear it
  289.     INC    DE        ; Leave "DE" pointing at filename area
  290.     LD    A,' '        ; For proper alignment
  291.     CALL    TYPE
  292.     LD    HL,INFCB    ; Print input filename to console
  293.     CALL    PRNFIL
  294.     XOR    A        ; Init 1st char of date stamp bfr to zero
  295.     LD    (STAMP),A    ; (nulls the buffer; zero is the eof char)
  296.     CALL    GETCHR        ; Get a char from the input stream
  297.     JR    NC,NTMT        ; If carry set on first byte, file is empty
  298.     LD    DE,ERR0        ; "[ file empty ]"
  299.     JR    NCR2        ; Treat same as "Not compressed"
  300.  
  301. NTMT:    CP    76H        ; Check for crunched file header "76FE"
  302.     JR    NZ,NCRNCH    ; Br if not
  303.     CALL    GETCHR
  304.     CP    0FEH
  305.     JR    Z,YCRNCH
  306.     CP    0FDH        ; lzh?
  307.     JR    Z,YLZH        ; br if so
  308.     CP    0FFH        ; Squeezed?
  309.     JR    Z,YESQZ        ; Br if so
  310.  
  311. NCRNCH:    CALL    CLSIN        ; Not squeezed or crunched; close input file
  312.     LD    DE,MSG43    ; "[not compressed]"
  313.  
  314. NCR2:    CALL    MESAG2
  315.     LD    A,(WLDFLG)    ; Invoked w/ wildcards?
  316.     OR    A
  317.     JP    NZ,COPY9    ; Do straight copy ("copy" chks for diff du)
  318.     JP    NXTFIL        ; Else go on to next file
  319.  
  320. ;...............................
  321.  
  322. YESQZ:    LD    (SQZFLG),A    ; Flag file as squeezed using ff already in a
  323.     CALL    GETCHR        ; Get checksum byte #1
  324.     LD    L,A        ; Hold that
  325.     CALL    GETCHR        ; Checksum byte #2
  326.     LD    H,A
  327.     LD    (SQCKSM),HL    ; Save for later reference
  328.     JR    YCRNCH
  329.  
  330. YLZH:    LD    (YFLAG),A    ; flag file as lzh crunched
  331.  
  332. YCRNCH:    LD    DE,OUTFCB+1    ; Where output filename will be copied to
  333.     LD    B,12        ; Loop limiter (11 char filename + ".")
  334.  
  335. EATLP:    CALL    GETCHR        ; Get next char
  336.     OR    A        ; A zero byte indicates end of filename
  337.     JR    Z,ATEIT        ; Br when that is encountered
  338.     AND    7FH        ; Force valid ascii (should be already)
  339.     CALL    UCASE        ; Upcase the char- (may be lc if squeezed)
  340.     CP    '.'        ; Check for name / ext division char
  341.     JR    Z,ISDOT        ; Br when encountered
  342.     LD    (DE),A        ; Else copy char to output fcb
  343.     INC    DE        ; And incr that pointer
  344.     DJNZ    EATLP        ; Continue, but not past end of filename
  345.     JR    IGNORE        ; If no 0 detected, ignore following info
  346.  
  347. ;.......................................................................
  348. ;
  349. ; When "." is encountered, skip to the file extension bytes of the out-
  350. ; put FCB.  Any remaining non-extension bytes were init'd to blank).  Do
  351. ; not copy the "." to the output FCB.
  352.  
  353. ISDOT:    LD    DE,OUTFCB+9    ; Skip...
  354.     LD    B,3        ; Update loop limiter counter
  355.     JR    EATLP        ; And continue
  356.  
  357. ;...............................
  358.  
  359. IGNORE:    LD    A,(SQZFLG)    ; For squeezed files, nothing else to do
  360.     OR    A
  361.     JP    NZ,USQZIT    ; Go to it
  362.  
  363. IGNRLP:    CALL    GETCHR        ; Loop absorbs extraneous header info
  364.     JR    C,NCRNCH    ; Circumvent possible hangup (eof before 0)
  365.     OR    A        ; Wait for the terminating zero
  366.     JR    Z,ATEIT        ; If terminating zero is reached
  367.     CP    1        ; do we have a date stamp?
  368.     JR    NZ,IGNOR2    ; (no)
  369.  
  370.     LD    B,15        ; 15 bytes in date string
  371.     LD    DE,DATBUF    ; DE -> date buffer
  372. DATLP:    CALL    GETCHR
  373.     JR    C,NCRNCH
  374.     OR    A
  375.     JR    Z,ATEIT
  376.     CP    0FFh        ; if it's FFh, make it 0
  377.     JR    NZ,NOTFFH
  378.     CPL
  379. NOTFFH:    LD    (DE),A
  380.     INC    DE
  381.     DJNZ    DATLP
  382.     LD    A,0FFh
  383.     LD    (DATFLG),A
  384.     JR    IGNRLP
  385.  
  386. IGNOR2:    CP    '['        ; Else check for date stamp bof char
  387.     JR    NZ,IGNRLP    ; Other chars are extraneous at this point
  388.  
  389. ;...............................
  390.  
  391.     LD    DE,STAMP    ; Start copying file stamp info to this buffer
  392.     JR    ENTSLP
  393.  
  394. STMPLP:    CALL    GETCHR        ; Get a char
  395.     JP    C,NCRNCH    ; Circumvent hangup
  396. ENTSLP:    LD    (DE),A        ; Put char in dest
  397.     INC    DE        ; Incr dest pntr
  398.     OR    A
  399.     JR    NZ,STMPLP    ; Loop till zero is reached
  400.  
  401. ;...............................
  402.  
  403. ATEIT:    CALL    GETCHR        ; Get revision level, do nothing with it
  404.     LD    A,(YFLAG)    ; is it lzh?
  405.     OR    A
  406.     JR    NZ,YATEIT    ; (yes, check significant revision below)
  407.     CALL    GETCHR        ; Get significant revision level
  408.     CP    SIGREV        ; Compare to this prog
  409.     JP    C,OLDTYP    ; Br if old type1x crunched file
  410.     JR    Z,SIGOK        ; If equal, ok, else...
  411. YATERR:    LD    DE,ERR5        ; "can't uncrunch that file. newer revision of
  412.     JP    SKIP2        ; - this program needed" or some such remark
  413.  
  414. YATEIT:    CALL    GETCHR
  415.     CP    SIGRVY+1    ; compare to significant revision
  416.     JR    NC,YATERR    ; doesn't match
  417.     JP    OLDTYP        ; continue
  418.  
  419. SIGOK:    CALL    GETCHR        ; Get checksum flag
  420.     LD    (CKSMFL),A    ; Put it there
  421.     CALL    GETCHR        ; Get spare byte, do nothing with it
  422.     CALL    OPNOUT        ; Open output file & type "--->  <filename>"
  423.     PUSH    AF        ; Save stat from above
  424.     CALL    PRNID        ; Type any embedded date stamp info also
  425.     POP    AF
  426.     JP    C,SKIP2A    ; If user wants to skip it
  427.  
  428. ;.......................................................................
  429. ;
  430. ; Now both files are open.  Eventually either both will be closed, or
  431. ; the input file will be closed and the output deleted.
  432.  
  433.     LD    A,(QUIFM)    ; Skip column headings if in quiet mode
  434.     OR    A
  435.     JR    NZ,QUIET1
  436.     LD    DE,HEADNG    ; Type all the "in / out  ca  cr" stuff
  437.     CALL    MESAGE
  438.  
  439. QUIET1:    CALL    INITB2        ; Initialize the lzw table
  440.     LD    DE,NOPRED    ; Init to "NOPRED" (null value)
  441.  
  442. ;=======================================================================
  443. ;
  444. ;         *** Main Decoding loop(s). ***
  445. ;
  446. ;=======================================================================
  447.  
  448. MAINLP:    LD    (LASTPR),DE    ; Always keep a copy of the last "pred" here
  449.     CALL    GETCOD        ; Get bits to form a a new code in "DE"
  450.     JP    C,DUN        ; Br if eof node or physical end-of-file
  451.     PUSH    DE        ; Push a copy of the new pred
  452.     CALL    DECODE        ; Decode new pred
  453.     LD    HL,ENTFLG    ; Flag is "01" if "decode" made the entry
  454.     SRL    (HL)        ; Check (and zero) the flag
  455.     JR    C,NOENTR    ; Don't make the same entry twice!
  456.     LD    HL,(LASTPR)    ; Get old pred
  457.     LD    A,(CHAR)    ; And suffix char generated from the new pred
  458.     CALL    ENTERX        ; Make new table entry from those two
  459.  
  460. NOENTR:    POP    DE        ; Get newest pred again (not that new anymore)
  461.     LD    A,(FULFLG)    ; Monitor the table full flag
  462.     OR    A
  463.     JR    Z,MAINLP    ; Continue decoding & entering 'till full
  464.  
  465. ;...............................
  466.  
  467.     CP    0FEH        ; When this becomes "FF", we are done
  468.     JR    NZ,FASTLP    ; First it will become "FE", though. in that
  469.     INC    A        ; - case perf 1 more loop & change it to "FF"
  470.     LD    (FULFLG),A    ;
  471.     JR    MAINLP        ; One more!
  472.  
  473. ;.......................................................................
  474.  
  475. FASTLP:    LD    (LASTPR),DE    ; Table full loop similar to above ,except
  476.     CALL    GETCOD        ; - don't bother checking table full flag
  477.     JP    C,DUN        ; - call "ENTFIL", not "ENTERX" (for possible
  478.     PUSH    DE        ; - code reassignment
  479.     CALL    DECODE        ; Call to actually decode chars
  480.     LD    HL,(LASTPR)    ; Get old pred
  481.     LD    A,(CHAR)    ; And suffix char generated from the new pred
  482.     CALL    ENTFIL        ; Possibly make new table entry from those two
  483.     POP    DE
  484.     JR    FASTLP        ; Continue in code reassignment mode
  485.  
  486. ;        *** End of Main Processing Loop(s)
  487. ;_______________________________________________________________________
  488. ;
  489. ; Come here when one of the special codes is encountered (we may not
  490. ; really be "dun").  Actually, a null code should have been intercepted
  491. ; by the GET12 routine, leaving only EOF (actually done) or adaptive
  492. ; reset.
  493.  
  494. DUN:    LD    A,E        ; Some kind of special code encountered
  495.     CP    LOW(EOFCOD)    ; Actually done?
  496.     JR    Z,DUNDUN    ; Br if do
  497.     CP    LOW(RSTCOD)    ; Else better be reset (null was intercepted)
  498.     JP    NZ,FATBAD    ; File is invalid
  499.  
  500. ;.......................................................................
  501. ;
  502. ; --- Perform an adaptive reset ---
  503.  
  504.     LD    HL,0000        ; Reset entry # prior to table re-initialization
  505.     LD    (ENTRY),HL
  506.     LD    (TTOTAL),HL    ; Reset "codes reassigned"
  507.     XOR    A
  508.     LD    (FULFLG),A    ; Reset  "table full" flag
  509.     CALL    INITB2        ; Reset the entire table
  510.     LD    A,9        ; Reset the code length to "9"
  511.     LD    (CODLEN),A
  512.     LD    A,02H        ; Reset the target mask value accordingly
  513.     LD    (TRGMSK),A
  514.  
  515.     LD    DE,NOPRED    ; Set pred to "nopred"
  516.     LD    A,1        ; 1st entry is always a special case
  517.     LD    (ENTFLG),A    ; (trick it to make no table entry)
  518.     JP    MAINLP        ; And continue where we left off
  519.  
  520. ;_______________________________________________________________________
  521. ;
  522. ; --- Actually done, close things up ---
  523.  
  524. DUNDUN:    CALL    GETCHR        ; Get the checksum, always next
  525.     LD    E,A
  526.     CALL    GETCHR        ; Get checksum (hi-byte)
  527.     LD    D,A        ; Checksum (from input file) now in "DE"
  528.     LD    A,(CKSMFL)    ; Checksum override flag (not currently used)
  529.     AND    A        ; Check flag, also clear carry for below
  530.     JR    NZ,CHKSOK    ; If flag > 0, don't check checksum
  531.  
  532. DUNDUQ:    LD    HL,(CHKSUM)    ; Checksum (as computed)
  533.     SBC    HL,DE        ; Else check by subtraction
  534.     JR    Z,CHKSOK    ; Br if match
  535.     LD    DE,BADCHK    ; Bad checksum, issue warning
  536.     CALL    MESAGE
  537.  
  538. ;...............................
  539.  
  540. CHKSOK:    CALL    DONE        ; Write out remaining output buffer
  541.  
  542. CLOSE2:    CALL    CLSOUT        ; Close output file
  543.     CALL    CLSIN        ; Close input file
  544.     JR    NEXT
  545.  
  546. ;.......................................................................
  547.  
  548. COPY9:    CALL    COPY        ; Perform a straight copy
  549.     JP    C,NXTFIL    ; If copy didn't take place, don't count it
  550.  
  551. NEXT:    CALL    DATSTP        ; Move date stamp
  552.     LD    HL,(NFP)    ; If we got here, the file has been "processed"
  553.     INC    HL        ; So incr the "files processed" counter
  554.     LD    (NFP),HL
  555.     JP    NXTFIL        ; Go start next file
  556.  
  557. ;.......................................................................
  558.  
  559. SKIP1:    CALL    MESAGE        ; Entry if neither in nor output files open yet
  560.  
  561. SKIP1A:    JP    NXTFIL        ; (Entry here if no error text desired)
  562.  
  563. ;...............................
  564.  
  565. SKIP2:    CALL    MESAGE        ; Entry here if input file open only
  566.  
  567. SKIP2A:    CALL    CLSIN        ; (Entry here for no message)
  568.     JP    NXTFIL
  569.  
  570. ;.......................................................................
  571. ;
  572. ; The following routine actually performs the decoding.  The top section
  573. ; "DECODE" flags the entry as "referenced".  It then calls the recursive
  574. ; section below it, "DECODR", to do the actual work.
  575.  
  576. DECODE:    PUSH    DE        ; Save code. the code provides us an immediate
  577.     EX    DE,HL        ;   index into the main logical table
  578.  
  579.     LD    A,H        ; (Add offset to beg of table, of course)
  580.     ADD    A,TABLHI
  581.     LD    H,A
  582.     SET    5,(HL)        ; Set bit 5 of pred (hi) to flag entry as
  583.     POP    DE        ; - "referenced" (ie not bumpable)
  584.  
  585. ;.......................................................................
  586.  
  587. DECODR    EQU    $        ; Decode and output the index supplied in "DE"
  588.  
  589.     LD    IY,STKLIM    ; Stack overflow check as a safety precaution
  590.     ADD    IY,SP        ; (limit allows extra for this invocation lvl)
  591.     JP    NC,STKOVF    ; Br on overflow (shouldn't happen)
  592.  
  593.     PUSH    HL        ; Only "HL" need be saved
  594.  
  595.     LD    A,D        ; Convert index in "DE" to address in "HL"
  596.     ADD    A,TABLHI
  597.     LD    H,A
  598.     LD    L,E        ; Address now in "HL"
  599.  
  600.     LD    A,(HL)        ; Make sure the entry exists
  601.     AND    0DFH
  602.     CP    80H        ; (Value for a vacant entry)
  603.     JR    NZ,OK1        ; Br if so (normal case)
  604.  
  605. ;...............................
  606.  
  607.     LD    A,01H        ; The "ugly" exception, wswsw
  608.     LD    (ENTFLG),A    ; Set flag so entry isn't made twice
  609.     PUSH    HL        ; Save current stuff.
  610.     LD    HL,(LASTPR)    ; Get the last pred..
  611.     LD    A,20H        ; (setting this flag will flag the entry as
  612.     LD    (FFFLAG),A    ; - referenced,)
  613.     LD    A,(CHAR)    ; Get the last char
  614.     CALL    ENTERX        ; Make an on the fly entry...
  615.     XOR    A
  616.     LD    (FFFLAG),A    ; Put this back to normal
  617.     POP    HL        ; And presto...
  618.     LD    A,(HL)        ; It had better exist now!
  619.     CP    80H
  620.     JR    Z,FATBAD    ; *** else file is fatally invalid ***
  621.  
  622. ;...............................
  623.  
  624. OK1:    LD    D,(HL)        ; Normal code- get "pred" (hi)
  625.     RIGHT1            ; Move to "pred" (lo)
  626.     LD    E,(HL)        ; Get that. if MSB of hi byte is set, val must
  627.     BIT    7,D        ; - be "FF" (nopred) because it isn't "80H"
  628.     JR    NZ,TERM        ; If so, branch. this terminates recursion.
  629.     RES    5,D        ; Else clear flag bit & decode pred we found
  630.     CALL    DECODR        ; Decode and output the "pred" (recursive call)
  631.     RIGHT1            ; Move pointer ahead to the "suffix" byte
  632.     LD    A,(HL)        ; Get it
  633.  
  634. SAMABV:    CALL    SEND        ; Output the "suffix" byte
  635.     POP    HL        ; Restore reg and return
  636.     RET
  637.  
  638. TERM:    RIGHT1            ; Move pointer ahead to the suffix byte
  639.     LD    A,(HL)        ; Get it & save it. it is the 1st char of the
  640.     LD    (CHAR),A    ; - decoded string, and will be used later to
  641.     JR    SAMABV        ; - attempt to make a new table entry.
  642.                 ; (rest is same as above)
  643.  
  644. ;_______________________________________________________________________
  645.  
  646. FATBAD:    LD    DE,ERR4        ; "invalid crunched file"
  647.     CALL    MESAGE        ; ..print it
  648.     JP    CHKSOK        ; Write out whatever we have, then next file
  649.                 ; (Stack gets reloaded before next file)
  650.  
  651. ;_______________________________________________________________________
  652. ;
  653. ; Enter { <pred>, <suffix> } into the table, as defined in { HL, A }
  654.  
  655. ENTERX:    PUSH    AF        ; Save the suffix till we're ready to enter it
  656.     PUSH    HL        ; Save pred, xferred to "DE" just below
  657.     CALL    FIGURE        ; Puts result in "phyloc" only, affects nothing
  658.     POP    DE        ; Put pred in "DE" (pushed as "HL" above)
  659.     LD    HL,(ENTRY)    ; Get next avail entry #
  660.     LD    A,H        ; Convert that to an address
  661.     ADD    A,TABLHI
  662.     LD    H,A
  663.  
  664. ; Entries are made here, but not normally flagged as "referenced" until
  665. ; the are received by "DECODE".  Until they are flagged as referenced,
  666. ; theyare "bumpable" i.e., available for code reassignment.  If "FFFLAG"
  667. ; is set to 20H, however, they will be flagged now.  This only occurs
  668. ; during initialization (bumping an atomic entry would be most unfortu-
  669. ; nate) and when a WsWsW string encounter initiates an emergency entry,
  670. ; despite the code never having been received by "DECODE".
  671.  
  672.     LD    A,(FFFLAG)    ; Normally zero, as described above
  673.     OR    D
  674.     LD    (HL),A        ; Make the entry- pred (hi) first
  675.     RIGHT1            ; Move to pred (lo) position
  676.     LD    (HL),E        ; Put that in
  677.     RIGHT1            ; Move to suffix position
  678.     POP    AF        ; Retrieve the suffix, saved on entry
  679.     LD    (HL),A        ; Stick it in
  680.     LD    HL,(ENTRY)    ; Increment the entry # counter
  681.     INC    HL
  682.     LD    (ENTRY),HL
  683.     INC    HL        ; See if a new code length is indicated. the
  684.     LD    A,(TRGMSK)    ; - extra inc "HL" above is to account for
  685.     CP    H        ; - skew delays of uncruncher vs. cruncher
  686.     RET    NZ        ; Normally just return
  687.  
  688.     SLA    A        ; Change to a new code length
  689.     LD    (TRGMSK),A    ; This will be the next target mask
  690.     LD    A,(CODLEN)    ; Get the old code length, as a # of bits
  691.     INC    A        ; Increment it, too
  692.     CP    13        ; Check for overflow (12 bits is the max)
  693.     JR    Z,FLGFUL    ; If so, flag table as full
  694.     LD    (CODLEN),A    ; Else this is the new code length
  695.     RET
  696.  
  697. ;...............................
  698.  
  699. FLGFUL:    LD    A,0FEH        ; Flag table as full
  700.     LD    (FULFLG),A
  701.     RET
  702.  
  703. ;.......................................................................
  704. ;
  705. ; Get the next code by stripping the appropriate # of bits off the input
  706. ; stream, based on the current code length "CODLEN".  If the code is
  707. ; "NULL", don't even return; just get another one.  If the code is one
  708. ; of the other special codes, return with the carry flag set. "Spare" is
  709. ; actually treated like a "null" for the time being, since it's use has
  710. ; yet to be defined.
  711.  
  712. GETCOD:    LD    DE,0000        ; Init "shift register" to zero
  713.     LD    A,(CODLEN)    ; Get current code length
  714.     LD    B,A        ; Will be used as a loop counter
  715.     LD    A,(CSAVE)    ; "leftover" bits
  716.  
  717. GETLP:    SLA    A        ; Shift out a bit
  718.     CALL    Z,REF        ; Refill when necessary
  719.     RL    E        ; Shift in the bit shifted out
  720.     RL    D        ; Likewise
  721.     DJNZ    GETLP        ; Loop for # of bits needed
  722.  
  723.     LD    (CSAVE),A    ; Save "leftover" bits for next time
  724.     LD    A,D        ; If hi-byte = "01", we may have a special code
  725.     DEC    A        ; Set z if it was "1"
  726.     AND    A        ; Clr carry
  727.     RET    NZ        ; Rtn w/ clr carry if byte wasn't "01"
  728.  
  729. ;...............................
  730.  
  731.     LD    A,E        ; Else further analysis necessary
  732.     CP    4        ; Set carry on 100, 101, 102, 103
  733.     RET    NC        ; Else code is normal, rtn with clr carry
  734.     CP    LOW(NULCOD)    ; Is it the "NULL" code?
  735.     JR    Z,GETCOD    ; If so, just go get another code
  736.     CP    LOW(SPRCOD)    ; (treat the unimplemented "spare" like a null)
  737.     JR    Z,GETCOD    ; As above
  738.  
  739.     SCF            ; < rtn with carry set indicating special code
  740.     RET            ; (presumably "EOF" or "reset")
  741.  
  742. ;_______________________________________________________________________
  743. ;
  744. ; Routine to reload "A" with more bits from the input stream.  Note we
  745. ; pre-shift out the next bit, shifting in a "1" from the left.    Since
  746. ; the leftmost bit in the reg is a guaranteed "1", testing the zero
  747. ; stat of the  accumulator later is a necessary and sufficient condition
  748. ; for determining that all the bits in the accumulator have been used.
  749. ;
  750. ; The only things to be careful of is that the last bit is NOT used la-
  751. ; ter, and that the bit now in the carry flag IS used upon return from
  752. ; this    subroutine.  (This is the identical scheme used in USQFST.  An
  753. ; exact complement to it is incorporated for shifting bits out in the
  754. ; CRUNCH program).
  755.  
  756. REF:    CALL    GETCHR        ; Get the char
  757.     JR    C,PHYEOF    ; Br if unexpected physical eof encountered
  758.     SCF            ; To shift in the "1" from the right
  759.     RLA            ; Do that, shifting out a "real" bit
  760.     RET            ; Rtn (with that real bit in the carry flag)
  761.  
  762. ;_______________________________________________________________________
  763.  
  764. PHYEOF:    LD    SP,TOPSTK    ; "Emergency exit"- reset stack
  765.     LD    DE,UNXEOF    ; "Unexpected eof."
  766.     CALL    MESAGE
  767.     JP    CHKSOK        ; Write out what we have, then continue
  768.  
  769. ;_______________________________________________________________________
  770. ;
  771. ; Send character to the output buffer, plus related processing
  772.  
  773. SEND:    EXX            ; Alt regs used for output processing
  774.     SRL    B        ; If reg is "1", repeat flag is set
  775.                 ; (note, clears itself automatically)
  776.     JR    C,REPEAT    ; Go perf the repeat
  777.     CP    90H        ; Else see if char is the repeat spec
  778.     JR    Z,SETRPT    ; Br if so
  779.     LD    C,A        ; Else nothing special- but always keep
  780.     EXX            ; Back to normal regs
  781.     CALL    OUTC        ; Else just output the char;
  782.     RET
  783.  
  784. ;.......................................................................
  785. ;
  786. ; Set repeat flag; count value will come as the next byte. (Note: don't
  787. ; clobber C with the "90H"- it still has the prev character, the one to
  788. ; be repeated)
  789.  
  790. SETRPT:    INC    B        ; Set flag
  791.     EXX            ; Switch to primary regs & return.
  792.     RET
  793.  
  794. ;.......................................................................
  795. ;
  796. ; Repeat flag was previously set; current byte in a is a count value.
  797. ; A zero count is a special case which means send 90H itself.  Otherwise
  798. ; use B (was the flag) as a counter. The byte itself goes in A.
  799.  
  800. REPEAT:    OR    A        ; Check for special case
  801.     JR    Z,SND90H    ; Jump if so
  802.     DEC    A        ; Compute "count-1"
  803.     LD    B,A        ; Juggle registers
  804.     PUSH    BC        ; The count and the char
  805.     LD    B,0        ; Zero the count in advance
  806.     EXX
  807.     POP    BC
  808.  
  809. AGAIN:    LD    A,C
  810.     PUSH    BC
  811.     CALL    OUTC        ; Repeat b occurrences of byte in 'c'
  812.     POP    BC
  813.     DJNZ    AGAIN        ; Leaves b, the rpt flag, 0 as desired
  814.     RET
  815.  
  816. ;...............................
  817.  
  818. SND90H:    LD    A,90H        ; Special case code to send the byte 90h
  819.     EXX
  820.     CALL    OUTC
  821.     RET
  822.  
  823. ;.......................................................................
  824. ;
  825. ; Send the char in "A" to the output buffer and add it to the running
  826. ; checksum.
  827.  
  828. OUT    EQU    $
  829. OUTC:    CALL    OUTB        ; Output it
  830.     CALL    CKSUM        ; Add to the checksum
  831.     RET
  832.  
  833. ;_______________________________________________________________________
  834. ;
  835. ; Convert the middle letter of the filename extension to a "Z" if it is
  836. ; "?", AND "difdu" = 0.  If we are uncrunching to a different DU:, get
  837. ; all files.
  838.  
  839. FIXFCB:    LD    A,(DIFDU)
  840.     OR    A
  841.     RET    NZ        ; If this flag is set, leave ext char untouched
  842.     LD    HL,INFCB+10    ; Point to middle letter of extension
  843.     LD    A,'?'
  844.     CP    (HL)        ; See if it is ambiguous
  845.     RET    NZ        ; If not, we'll allow any letter (rev v1.2)
  846.     LD    A,(TYPFL)    ; Else force it to configuration choice
  847.     LD    (HL),A        ; "Z", "Y", or "Q".  This is mainly so
  848.     RET            ; the command line "UNCR *.*" will work well
  849.  
  850. ;_______________________________________________________________________
  851. ;
  852. ; Flag files to be copied, not uncompressed
  853.  
  854. EXCLUD:    LD    BC,12        ; Leave 12 in bc for incrementing ix
  855.     LD    IX,FNBUFF    ; Points to beg of filenames
  856.  
  857. OUTLP:    LD    A,(IX+0)    ; Get flag byte for this entry
  858.     CP    0FFH        ; Final [non-] entry?
  859.     RET    Z        ; (return if so)
  860.  
  861.     OR    A        ; Is it an untagged filename?
  862.     JR    Z,NXTFN        ; If so, leave it that way & move to next
  863.     LD    A,(IX+10)    ; Otherwise check middle letter of fn ext
  864.     CP    'Z'
  865.     JR    Z,NXTFN        ; If 'z', do not exclude it
  866.     CP    'Y'
  867.     JR    Z,NXTFN        ; nor if it's 'y'
  868.     CP    'Q'
  869.     JR    Z,NXTFN        ; Likewise 'q', else "exclude" it
  870.  
  871. ;-----------------------------------------------------------------------
  872.  
  873. AUTOM3:    LD    A,02H        ; Flag file as "excluded"
  874.     LD    (IX+0),A
  875.  
  876. NXTFN:    ADD    IX,BC        ; Move to next filename in "fnbuff"
  877.     JR    OUTLP
  878.  
  879. ;_______________________________________________________________________
  880. ;
  881. ; Type the stuff in the "stamp" buffer to the console.
  882.  
  883. PRNID:    LD    HL,STAMP    ; Point to that buffer
  884.     LD    B,40        ; Practical limit of 40 char "stamp"
  885.     LD    A,(HL)        ; is there a text string?
  886.     OR    A
  887.     RET    Z        ; (nope)
  888.     LD    A,' '        ; for aesthetics
  889.     CALL    TYPE
  890. PRFILP:    LD    A,(HL)        ; Get a character
  891.     OR    A        ; Zero terminates the field
  892.     RET    Z        ; Return when encountered
  893.     CALL    TYPE        ; Else type the char
  894.     CP    ']'        ; This terminates stamp also (after typing it)
  895.     RET    Z        ; Return if that happened
  896.     INC    HL        ; Else incr pointer
  897.     DJNZ    PRFILP        ; And loop
  898.     RET
  899.  
  900. ;_______________________________________________________________________
  901.  
  902. STKOVF:    LD    DE,ERR6        ; "*** stack overflow ***"
  903.     LD    SP,TOPSTK    ; Shouldn't happen, but we're still in control
  904.     JP    FATBAD        ; Reset and continue with next file, if any
  905.  
  906. ;_______________________________________________________________________
  907. ;
  908. ; Initialize the table to contain the 256 "atomic" entries - { "NOPRED",
  909. ; <char> },  for all values of <char> from 0 thru 255
  910.  
  911. INITB2:    CALL    PRESE2        ; "pre-initializes" the table (mostly zeroes)
  912.     LD    A,20H
  913.     LD    (FFFLAG),A
  914.     XOR    A        ; Start with a suffix of zero
  915.     LD    HL,NOPRED    ; Pred for all 256 atomic entries
  916.  
  917. INILP:    PUSH    HL
  918.     PUSH    AF
  919.     CALL    ENTERX
  920.     POP    AF
  921.     POP    HL
  922.     INC    A        ; Next suffix
  923.     JR    NZ,INILP    ; Loop 256 times
  924.  
  925. ;.......................................................................
  926. ;
  927. ; Now reserve the four reserved codes 100H - 103H (EOF, RESET, NULL, and
  928. ; SPARE.  This is easily achieved by inserting values in the table which
  929. ; cannot possibly be matched, and insuring that they cannot be reas-
  930. ; signed.  An occurrence of any of these codes is possible only when the
  931. ; cruncher explicitely outputs them for the special cases for which they
  932. ; are designated.
  933.  
  934.     LD    B,4        ; Loop counter for the 4 reserved entries
  935.  
  936. RSRVLP:    PUSH    BC
  937.     LD    HL,IMPRED    ; An "impossible" pred
  938.     XOR    A        ; Any old suffix will do
  939.     CALL    ENTERX        ; Make the entry
  940.     POP    BC
  941.     DJNZ    RSRVLP        ; Loop 4 times
  942.  
  943.     XOR    A        ; Now restore this flag to its normal value
  944.     LD    (FFFLAG),A
  945.     RET
  946.  
  947. ;.......................................................................
  948. ;
  949. ; Low-level table preset called before initialization above. This rou-
  950. ; tine presets the main table as follows: (see description of table
  951. ; elsewhere):  Column 1: 4096 x 80H, Columns 2 and 3: 4096 x 00H
  952.  
  953. PRESE2:    LD    HL,TABLE    ; Beginning of main table, 4096 rows x 3 columns
  954.     LD    DE,TABLE+1
  955.     LD    BC,1000H
  956.     LD    (HL),80H
  957.     LDIR            ; Put in 1000h "80H"'s
  958.     LD    (HL),0        ;
  959.     LD    BC,2*1000H-1    ; Note "-1"
  960.     LDIR            ; And 2000h more "00H"'s
  961.  
  962. ;.......................................................................
  963. ;
  964. ; The auxiliary physical translation table is 5003 rows 2 columns
  965. ; (logically speaking).  Actually 5120 rows, 2 columns are allocated.
  966. ; All entries are initialized to 80H.
  967.  
  968.     LD    HL,XLATBL    ; Physical <--> logical xlation table
  969.     LD    DE,XLATBL+1
  970.     LD    BC,2800H    ; Total entries = 1400h x 2
  971.     LD    (HL),80H
  972.     LDIR
  973.     LD    A,7FH
  974.     LD    (XLATBL+0),A
  975.     RET
  976.  
  977. ;_______________________________________________________________________
  978. ;
  979. ; Figure out what physical location the cruncher put its entry by repro-
  980. ; ducing the hashing process.  Insert the entry # into the corresponding
  981. ; physical location in XLATBL.
  982.  
  983. FIGURE:    LD    B,A        ; < suffix supplied goes into B
  984.     CALL    HASH        ; Get initial hash value into  "HL"
  985.  
  986. PHYLP:    LD    C,H        ; C  <-- extra copy of h
  987.     LD    A,(HL)        ; Check if any entry exists at that location
  988.     CP    80H        ; Value for a vacant spot
  989.     JR    Z,ISMT        ; Br if vacant
  990.     CALL    NM        ; Else find next in chain
  991.     JR    PHYLP        ; And continue
  992.  
  993. ;...............................
  994.  
  995. ISMT:    LD    DE,(ENTRY)    ; Get the logical entry #
  996.     LD    (HL),D        ; Stick in hi-byte
  997.     LD    A,H        ; Move "right1" for this table
  998.     ADD    A,14H
  999.     LD    H,A
  1000.     LD    (HL),E        ; Low-byte goes there
  1001.     RET
  1002.  
  1003. ;...............................
  1004.  
  1005. NM    EQU    $        ; No match yet... find next "link" in chain
  1006.  
  1007.     LD    DE,(DISP)    ; Secondary probe- add disp computed by "HASH"
  1008.     ADD    HL,DE
  1009.     LD    A,H
  1010.     CP    XLATBH        ; Check for loop around
  1011.     JR    NC,NC9        ; Br if not
  1012.     LD    DE,5003        ; Else loop
  1013.     ADD    HL,DE
  1014.  
  1015. NC9:    RET
  1016.  
  1017. ;.......................................................................
  1018.  
  1019. ENTFIL    EQU    $        ; Try to enter the pred/suffix in HL|A
  1020.  
  1021.     CALL    HASH        ; Get initial hash value into  "HL"
  1022.  
  1023. ;.......................................................................
  1024.  
  1025. PHYLP2:    LD    A,(HL)        ; Check if any entry exists at that location
  1026.     CP    80H        ;
  1027.     RET    Z        ; End of chain, return w/o reassignment
  1028.  
  1029. ;...............................
  1030.  
  1031.     PUSH    HL        ; Save physical table pointer
  1032.     LD    D,(HL)        ; Get entry #, hi
  1033.     LD    A,H        ; }
  1034.     ADD    A,14H        ; } right 1 for this table
  1035.     LD    H,A        ; }
  1036.     LD    L,(HL)        ; Entry #, lo byte
  1037.     LD    A,D
  1038.     ADD    A,TABLHI    ; Convert to an addr in "HL"
  1039.     LD    H,A
  1040.     BIT    5,(HL)        ; See if entry is bumpable
  1041.     JR    Z,MAKIT        ; If so bumpable, go do it
  1042.     POP    HL        ; Else restore physical tbl pointer
  1043.     CALL    NM        ; Find next "link" in chain
  1044.     JR    PHYLP2        ; And continue
  1045.  
  1046. ;.......................................................................
  1047. ;
  1048. ; Reassign the entry pointed to by "avail", if any. Re-define the "last
  1049. ; pred entered" and "last suffix" variables.
  1050.  
  1051. MAKIT:    POP    DE        ; Get rid of extraneous physical pointer
  1052.     LD    DE,(TTOTAL)    ; Increase user's display count
  1053.     INC    DE
  1054.     LD    (TTOTAL),DE
  1055.     LD    DE,(LASTPR)    ; Get the pred
  1056.     LD    A,(CHAR)    ; And suffix
  1057.     LD    B,A        ; Put suffix here, ("right1" kills a)
  1058.     LD    (HL),D        ; Actually make the entry
  1059.     RIGHT1
  1060.     LD    (HL),E        ; [pred(lo)]
  1061.     RIGHT1
  1062.     LD    (HL),B        ; [suffix]
  1063.     RET            ; Done
  1064.  
  1065. ;.......................................................................
  1066. ;
  1067. ; For additional details about the hashing algorithm, see CRUNCH.
  1068.  
  1069. HASH    EQU    $
  1070.  
  1071.     LD    E,L        ; Save so low-nybble of pred can be used below
  1072.     ADD    HL,HL
  1073.     ADD    HL,HL
  1074.     ADD    HL,HL
  1075.     ADD    HL,HL        ; Shift whole pred value left 4 bits
  1076.     XOR    H        ; Xor hi-byte of that with suffix
  1077.     LD    L,A        ; Goes there as lo-byte of result
  1078.     LD    A,E        ; Get pred(lo) saved above
  1079.     AND    0FH        ; Want only low nybble of that
  1080.     ADD    A,XLATBH    ; Convenient time to add in table offset
  1081.     LD    H,A        ; Goes here as hi-byte of result
  1082.     INC    HL        ; Except add one. this eliminates poss. of 0.
  1083.     PUSH    HL        ; Save hash val for return
  1084.     LD    DE,-5003-XLATBL    ; Compute displacement value, - (5003-hash)
  1085.     ADD    HL,DE        ; (displacement has table offset removed again)
  1086.     LD    (DISP),HL    ; Secondary hashing value, a negative number.
  1087.     POP    HL        ; Get back orig hash address
  1088.     RET            ; And return it
  1089.  
  1090. ;=======================================================================
  1091. ;
  1092. ; For old style (v1.x) type crunched files, simply call the "UNCR1"
  1093. ; module.  LZH-encoded and squeezed files are handled identically,
  1094. ; except call "UNLZH" and "USQREL" modules, respectively.  All I/O
  1095. ; will be done by this program -- UNCR1 will get and feed data through
  1096. ; calls to entry points "GETBYT" and "OUT".  UNLZH will use "GLZHUN"
  1097. ; and "PLZHUN".
  1098.  
  1099. OLDTYP:    CALL    GETCHR        ; Get checksum flag
  1100.     LD    (CKSMFL),A    ; Put it there
  1101.     CALL    GETCHR        ; Get spare byte, do nothing with it *** nec??
  1102.  
  1103. USQZIT:    LD    A,0FFH        ; Flag this as an old style uncrunch
  1104.     LD    (OLDFLG),A    ; (controls type of screen updating)
  1105.     CALL    OPNOUT        ; Open output file & type "--> <filename>"
  1106.     PUSH    AF        ; Save stat from abv call
  1107.     LD    A,(SQZFLG)    ; *** necessary?
  1108.     OR    A
  1109.     CALL    Z,PRNID        ; Type any embedded id text also
  1110.     POP    AF        ; Get back carry stat
  1111.     JP    C,SKIP2A    ; If user wants to skip it
  1112.  
  1113.     LD    A,(QUIFM)
  1114.     OR    A
  1115.     LD    DE,HEADNY    ; Type all the "in / out" stuff
  1116.     CALL    Z,MESAGE
  1117.  
  1118.  
  1119.     EXX            ; Go back to start of file (already read some)
  1120.     LD    HL,IBUF
  1121.     EXX
  1122.  
  1123. FIX21:    LD    HL,SECNT    ; Bugger up the sector count since we just
  1124.     INC    (HL)        ; - reset the input pointer
  1125.     LD    HL,(INCTR)    ; [rev 2.1 fix]
  1126.     DEC    HL        ; Decr "inctr" for same reason
  1127.     LD    (INCTR),HL
  1128.     LD    A,'0'        ; [Rev 2.1 fix]
  1129.     LD    (PROGBF+5),A    ; Reset ascii display to zero
  1130.     LD    HL,TABLE    ; Point to large data area for uncr1 & lzh
  1131.     LD    A,(YFLAG)
  1132.     OR    A
  1133.     JR    NZ,USELZH    ; if lzh-encoded, call unlzh
  1134.     LD    A,(SQZFLG)
  1135.     OR    A
  1136.     JR    NZ,USESQZ    ; If squeezed, call usqrel
  1137.     CALL    UNCR1        ; Uncrunch the whole thing
  1138.  
  1139. ABVQ:    JP    NC,DUNDUN    ; A "normal" return
  1140.     JP    FATBAD        ; Any other error falls under "invalid.."
  1141.  
  1142. USESQZ:    CALL    USQREL        ; unsqueeze it
  1143.     LD    DE,(SQCKSM)    ; Get checksum read at beginning of file
  1144.     JP    NC,DUNDUQ    ; Terminate similarly (w/o reading cksm bytes)
  1145.     JP    FATBAD
  1146.  
  1147. USELZH:    CALL    UNLZH        ; uncrunch it a la lzh
  1148.     JR    ABVQ        ; check return
  1149.  
  1150. ;_______________________________________________________________________
  1151.  
  1152. PRCSTM:    LD    DE,PRSER1    ; "invalid argument" (no stamps allowed)
  1153.     JP    FATALU
  1154.  
  1155. ;_______________________________________________________________________
  1156.  
  1157. UCASE:    CP    'a'        ; Upper-case character in A
  1158.     RET    C
  1159.     SUB    20H        ; (Note "{","|","}",and "~" cannot occur)
  1160.     RET
  1161.  
  1162. ;_______________________________________________________________________
  1163. ;
  1164. ; All ASCII centralized here as a service to disassembly hobbyists.
  1165.  
  1166. INTRO:    DB    'LZH Uncruncher  Version ',VERS/10+'0','.',VERS MOD 10+'0'
  1167.     DB    SUBVERS,CR,LF,'$'
  1168. BADCHK:    DB    'Checksum error.',CR,LF,'$'
  1169. MSG43:    DB    '    [ Not compressed ]',CR,LF,'$'
  1170. ERR4:    DB    'Invalid Crunched File.',CR,LF,'$'
  1171. ERR5:    DB    'Requires newer version.',CR,LF,'$'
  1172. ERR6:    DB    'Stack Overflow.',CR,LF,'$'
  1173. UNXEOF:    DB    'Unexpected EOF.',CR,LF,'$'
  1174. USAGE:    DB    'Usage:',CR,LF
  1175.     DB    '   $'
  1176. PRGNAM:    DB    'UNCRLZH '        ; must end with space if < 8 characters
  1177. COMNAM:    DB    '        '
  1178. SYNTX1:    DB    ' {d$'
  1179. SYNTX2:    DB    ':}afn {d$'
  1180. USAGE1:    DB    ':} {/options}',CR,LF
  1181.     DB    'Second parameter is destination.',CR,LF
  1182.     DB    'Options following slash:',CR,LF
  1183.     DB    '   Q   Quiet mode o$'
  1184. USAGE2:    DB    CR,LF
  1185.     DB    '   I   Inspect (Tag) mode o$'
  1186. USAGE3:    DB    CR,LF
  1187.     DB    '   T   Same as I',CR,LF
  1188.     DB    '   E   $'
  1189. USAGE4:    DB    'Erase existing files$'
  1190. USAGE5:    DB    CR,LF
  1191.     DB    '   S   $'
  1192. USAGE6:    DB    'clude System files$'
  1193.  
  1194. ;=======================================================================
  1195.  
  1196. ; ** Include file begins here **
  1197.  
  1198.     INCLUDE    COMMONLZ.LIB
  1199.  
  1200. ; ** Include file ends here **
  1201. ;=======================================================================
  1202. ; - File I/O
  1203.  
  1204. PLZHUN    EQU    OUTC        ; for UNLZH module 'puts' thru this label
  1205. GLZHUN    EQU    GETBYT        ; for UNLZH module 'gets' thru this lable
  1206.  
  1207. ;=======================================================================
  1208.  
  1209. ; Additional miscellaneous ram locations which need not be initialized
  1210. ; or are initialized by the routines which use them.
  1211.  
  1212. CKSMFL:    DS    1        ; Skip checksum if flag non-zero
  1213. CHAR:    DS    1        ; Last char of the previously decoded string
  1214. FFFLAG:    DS    1
  1215. CSAVE:    DS    1
  1216. SQCKSM:    DS    2        ; squeezed file checksum
  1217. YFLAG:    DS    1        ; non-zero = LZH crunched file
  1218.  
  1219. ;...............................
  1220.  
  1221. STKSZ    EQU    8        ; Minimum stack size (pages)
  1222. IBUFSZ    EQU    8        ; Input buffer size (pages)
  1223.  
  1224. ;=======================================================================
  1225. ;
  1226. ; ===>    All tables will begin at "MEMPAG", defined at the top of the
  1227. ;    program.  This should be set to a page aligned value i.e., ad-
  1228. ;    dress that ends  in "00", which is ABOVE the end all program
  1229. ;    and data segments.  You may have to do one test link to deter-
  1230. ;    mine the proper value (changing "MEMPAG" will not change the
  1231. ;    length of the segments on the subsequent link).
  1232. ;
  1233. ; "MEMPAG" is defined at the beginning of this program to remind you to
  1234. ; set it properly.  If you set it higher than necessary, there will be
  1235. ; no negative effect other than an increase in the TPA required to run
  1236. ; the program.    If you set it too low, you will be in big trouble.  The
  1237. ; value must be set manually because most linkers cannot resolve an
  1238. ; "and", "shift", or "hi" byte extraction at link time to determine the
  1239. ; page boundary.
  1240. ;
  1241. ;=======================================================================
  1242.  
  1243. ; "MAXFLS" is  buffer size (in files) for wildcard expansions.    Room for
  1244. ; this many files will be allocated.
  1245.  
  1246. MAXFLS    EQU    256
  1247.  
  1248. FNBUFF    EQU    MEMPAG           ; (= beg of wildcard expansion buffer)
  1249. ENDFNB    EQU    FNBUFF+(12*MAXFLS) ; End of expansion buffer
  1250.  
  1251. IBUF    EQU    ENDFNB           ; (= beg of input buffer)
  1252. EIBUF    EQU    IBUF+(IBUFSZ*256)  ; End of input buffer
  1253.  
  1254. TABLE    EQU    EIBUF           ; (= beg of table)
  1255. EOTBL    EQU    TABLE+(3*1000H)       ; End of table
  1256. XLATBL    EQU    EOTBL
  1257. EXLATB    EQU    XLATBL+(2*1400H)
  1258. STAMP    EQU    EXLATB           ; 80h bytes for "stamp" buffer
  1259. ESTAMP    EQU    STAMP+80H
  1260.  
  1261. SAFETY    EQU    ESTAMP           ; Safety region- beyond legal bottom of stack
  1262. BOTSTK    EQU    SAFETY+80H       ; "Legal" stack limit
  1263. TOPSTK    EQU    EXLATB+(STKSZ*256) ; Top of stack
  1264.  
  1265. ENDALL    EQU    TOPSTK           ; End of everything, except output buffer
  1266. OBUF    EQU    ENDALL           ; Beginning of dynamically sized output buffer
  1267.  
  1268. ;.......................................................................
  1269.  
  1270. STKLIM    EQU    0-BOTSTK    ; Negation of "botstk", used as safety check
  1271.  
  1272. IBUFHI    EQU    HIGH IBUF    ; Input bfr addr, hi byte (lo byte = 0)
  1273. EIBFHI    EQU    HIGH EIBUF    ; End of input bfr addr, hi byte, likewise
  1274. TABLHI    EQU    HIGH TABLE    ; Beg of table, hi byte, likewise
  1275. ETBLHI    EQU    HIGH EOTBL    ; End of table, hi byte, likewise
  1276. XLATBH    EQU    HIGH XLATBL
  1277. EFNBHI    EQU    HIGH ENDFNB    ; End of expansion buffer, likewise
  1278. ENDHI    EQU    HIGH ENDALL    ; End of everything, likewise
  1279. OBUFHI    EQU    HIGH OBUF    ; Output buffer address, hi byte likewise
  1280.  
  1281.     END
  1282.