home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / DEMON / ZIPDIR12.ARC / ZD.Z80 < prev    next >
Text File  |  1994-02-20  |  35KB  |  1,221 lines

  1. ;******************************************************************************
  2. ;*                                          *
  3. ;*                ZIPDIR v1.0                      *
  4. ;*             ZIPfile Directory Lister                  *
  5. ;*                                          *
  6. ;******************************************************************************
  7. ; v1.0 15 March 1989  Initial release.
  8. ;
  9. ; Note: This code is hereby placed into the public domain HOWEVER a great
  10. ;    deal of the code is taken directly from the listing routines of
  11. ;    Robert A. Freed's UNARC program and used with permission. These
  12. ;    routines may be subject to to the same restrictions stated in the
  13. ;    current version of that program.     - S. Greenberg  03/15/89
  14. ;
  15.     .Z80
  16.     ASEG
  17.     ORG    100H
  18. ;
  19. ;
  20. NO    EQU    0
  21. YES    EQU    NOT NO
  22. WBFLAG    EQU    NO        ; Yes if program is to warm boot on exit
  23. WHLADR    EQU    003EH        ; Wheel byte address if used on an RCP/M
  24. ;                ; - (only used to prevent listing SYS files)
  25. LPSCRN    EQU    31        ; Lines per screen before [more] pause.
  26. ;
  27. ;--- ASCII equates ---
  28. ;
  29. CTLC    EQU    'C'-'@'        ; Control-C (console abort)
  30. CTLK    EQU    'K'-'@'        ; Control-K (alternate abort)
  31. BEL    EQU    'G'-'@'        ; Bell
  32. HT    EQU    'I'-'@'        ; Horizontal tab
  33. LF    EQU    'J'-'@'        ; Line feed
  34. CR    EQU    'M'-'@'        ; Carriage return
  35. CTLS    EQU    'S'-'@'        ; Control-S (suspend output)
  36. CTLZ    EQU    'Z'-'@'        ; Control-Z (CP/M end-of-file)
  37. DEL    EQU    7FH        ; Delete/rubout
  38. REP    EQU    'P'-'@'+80H    ; Repeated byte flag (DLE with MSB set)
  39. ;
  40. ;--- CP/M address equates ---
  41. ;
  42. BOOT    EQU    0000H        ; Warm boot address
  43. BDOS    EQU    0005H        ; Bdos entrypoint
  44. FCB    EQU    5CH        ; Default file control block #1
  45. ;
  46. ;--- BDOS function equates ---
  47. ;
  48. CONIN    EQU    1        ; Console input (single char)
  49. CONOUT    EQU    2        ; Output single char to console
  50. CONST    EQU    11        ; Get console status
  51. OPEN    EQU    15        ; Open file
  52. CLOSE    EQU    16        ; Close file
  53. READ    EQU    20        ; Read file (sequential)
  54. SETDMA    EQU    26        ; Set dma address
  55. RDRND    EQU    33        ; Read random
  56. GTSIZE    EQU    35        ; Compute file size
  57. ;
  58. ;--- FCB offsets ---
  59. @DR    EQU    0        ; Drive code
  60. @FN    EQU    1        ; File name
  61. @FT    EQU    9        ; File type
  62. @CR    EQU    32        ; Current record
  63. @R0    EQU    33        ; Random record field R0 (LS byte)
  64. @R1    EQU    34        ; Random record field R1
  65. @R2    EQU    35        ; Random record field R2 (MS byte)
  66. @FCBSX    EQU    35        ; Extended FCB size for random I/O
  67. ;
  68. ;--- ZIP file equates ---
  69. ;
  70. SIG0    EQU    50H        ; End of central directory signature (LS byte)
  71. SIG1    EQU    4BH        ; (next byte)
  72. SIG2    EQU    05H        ; (next byte)
  73. SIG3    EQU    06H        ; End of central directory signature (MS byte)
  74. ; End of Central Directory Record offsets (only fields used are included here)
  75. ;
  76. @SIG    EQU    0        ; (4) End of central directory record signature
  77. @NFILS    EQU    10        ; (2) #of entries in the central directory
  78. @CDOFF    EQU    16        ; (4) offset- beg of file to start of cent. dir
  79. ; Note: Structure of the individual central directory entries is indicated
  80. ; by the data structure HDRBUF at the end of the program.
  81. ;
  82. ;..............................................................................
  83. ;
  84. ; Open the file and find the end of it.
  85. ;
  86. ENTRY:    LD    (OLDSTK),SP    ; Save system stack pointer
  87.     LD    SP,STACK    ; Set to local area
  88.     LD    A,(FCB+@FN)    ; Any filename supplied?
  89.     CP    ' '
  90.     JP    Z,GIVUSG    ; If not, give usage
  91.     LD    A,LPSCRN    ; Init lines per screen counter
  92.     LD    (LPSCT),A
  93.     LD    A,(FCB+@FT)    ; See if any filetype was specified
  94.     CP    ' '
  95.     JR    NZ,SKPZIP    ; If so, leave it as is
  96.     LD    HL,'PI'        ; Else inject a ".ZIP" extension
  97.     LD    (FCB+@FT+1),HL
  98.     LD    A,'Z'
  99.     LD    (FCB+@FT+0),A
  100. ;
  101. SKPZIP:    LD    HL,FCB+12    ; Init FCB to all 0's except drive & filename
  102.     LD    B,@FCBSX-12
  103. ;
  104. ZLP2:    LD    (HL),0
  105.     INC    HL
  106.     DJNZ    ZLP2
  107.     LD    C,OPEN        ; Attempt to open the file
  108.     CALL    FCBDOS        ; (calls BDOS with DE = FCB)
  109.     INC    A
  110.     JP    Z,NOSUCH    ; If no such file..
  111.     LD    A,(FCB+10)    ; Check if file has SYS attribute
  112.     AND    80H        ; (for security when program is used online)
  113.     JR    Z,NONSYS    ; If not, it's OK
  114.     LD    A,(WHLADR)    ; If so, check if wheel byte is set
  115.     OR    A
  116.     JP    Z,NOSUCH    ; SYS file w/o wheel byte: pretend no such file
  117. ;
  118. NONSYS:    LD    C,SETDMA    ; Set DMA addr to memory area following prgm
  119.     LD    DE,PAGE
  120.     CALL    BDOSAV
  121.     LD    C,READ        ; Initially perform a seq. read to guarantee
  122.     CALL    FCBDOS        ; - proper FCB initialization (data not used)
  123.     LD    C,GTSIZE    ; Get file size so we can access the last rec
  124.     CALL    FCBDOS        ; Returns value in FCB+@R2,R1,R0
  125.     LD    A,(FCB+@R2)    ; Disallow the 8 meg case
  126.     OR    A
  127.     JP    NZ,TOOBIG
  128. ;
  129. ;..............................................................................
  130. ;
  131. ; Search for the 4 byte sequence which comprises the End of Central Directory
  132. ; Record signature. The signature and the rest of the End Record which follows
  133. ; it should be completely contained within the last two records of the file,
  134. ; but it may not if the file was padded during transmission or if the ZIP file
  135. ; contains a long ZIP file comment. For file size of L records, this code will
  136. ; read the last two records, L-2 and L-1, into a page of memory at PAGE. If the
  137. ; signature is not found, the code will try again, this time reading records
  138. ; L-3 and L-2 into memory at PAGE.  This is not optimally effecient, but the
  139. ; number of re-reads is very small in practice so the time penalty is slight.
  140. ;................................
  141. ;                ;
  142. AGAIN:    LD    DE,-2        ; Come back here if a re-read is necessary
  143.     LD    HL,(FCB+@R0)    ; Last record# plus one (on 1st pass, anyway)
  144.     ADD    HL,DE        ; Subtract two
  145.     JP    NC,BADZIP    ; Don't go below zero
  146.     CALL    CABORT        ; This process is abortable
  147.     CALL    READ2        ; Read 2 recs (HL, HL+1) into page+0, page+80H
  148. ;                ;
  149. ;................................
  150. ;                ;
  151.     LD    IX,PAGE        ;
  152.     LD    B,255-3        ;
  153. ;                ;
  154. MTCHLP:    LD    A,(IX+@SIG+0)    ; Search for end of central directory
  155.     CP    SIG0        ; Signature - (50H,4BH,05H,06H)
  156.     JR    NZ,NOMTCH    ;
  157.     LD    A,(IX+@SIG+1)    ;
  158.     CP    SIG1        ;
  159.     JR    NZ,NOMTCH    ;
  160.     LD    A,(IX+@SIG+2)    ;
  161.     CP    SIG2        ;
  162.     JR    NZ,NOMTCH    ;
  163.     LD    A,(IX+@SIG+3)    ;
  164.     CP    SIG3        ;
  165.     JR    Z,MATCH        ; Match; IX now points to start of central dir
  166. ;                ;
  167. NOMTCH:    INC    IX        ;
  168.     DJNZ    MTCHLP        ;
  169. ;...............................;
  170. ;
  171.     JP    AGAIN        ; No match, try again
  172. ;
  173. ;..............................................................................
  174. ;
  175. ; The End Record signature has been located. Use the values contained in the
  176. ; End Record to locate the start of the central directory itself.
  177. ;
  178. MATCH:    LD    H,(IX+@NFILS+1)    ; Get #of files, save it in NFILES
  179.     LD    L,(IX+@NFILS+0)
  180.     LD    (NFILES),HL
  181.     LD    A,(IX+@CDOFF+3)    ; Get offset to start of central directory
  182.     OR    A        ; Way too big if MS byte is non-zero
  183.     JP    NZ,TOOBIG
  184.     LD    H,(IX+@CDOFF+2)    ; Will divide the val by 128 to get #of records
  185.     LD    L,(IX+@CDOFF+1)
  186.     LD    A,(IX+@CDOFF+0)
  187.     PUSH    AF
  188.     AND    7FH        ; First get the remainder from the div by 128
  189.     LD    C,A        ; (that will be the offset within the record)
  190.     LD    B,0        ; That value now in BC
  191.     PUSH    BC
  192.     POP    IY        ; Now in IY
  193.     POP    AF        ; Get back orig LS byte
  194.     RLA            ; Divide HL,A by a left shift
  195.     RL    L
  196.     RL    H
  197.     JP    C,TOOBIG    ; Too big if HL was originally > 8000H
  198.     LD    (FCB+@R0),HL    ; Else put the value in the random rec# field
  199. ;
  200. ;.............................................................................
  201. ;
  202. ; Now we are ready to read central directory data into memory. A single
  203. ; random read will position the file properly (R0, R1 are already set).
  204. ; The offset to the beginning of the data in the first record is in IY.
  205. ;
  206.     LD    DE,PAGE+80H    ; A record at a time goes into this half page
  207.     LD    C,SETDMA
  208.     CALL    BDOSAV
  209.     LD    C,RDRND        ; Perform a random read to position the file
  210.     CALL    FCBDOS
  211.     LD    C,READ        ; Read the 1st record. After this, use GETDTA.
  212.     CALL    FCBDOS
  213.     PUSH    IY        ; Relative offset to start of real data
  214.     POP    HL
  215.     LD    DE,PAGE+80H-1    ; Convert it from a relative to absolute value
  216.     ADD    HL,DE
  217.     LD    (DTAPTR),HL    ; Inititialize "READTA"'s internal pointer
  218.     LD    HL,TOTS        ; Initialize all the "totals" data to zero
  219.     LD    B,TOTC
  220. ;
  221. CLRTOT:    LD    (HL),0
  222.     INC    HL
  223.     DJNZ    CLRTOT
  224.     LD    DE,IDSTR    ; Type "ZIPFILE = <filename>"
  225.     CALL    PRINTS
  226.     LD    HL,FCB+@FN
  227.     CALL    PFN        ; (types filename, compressing blanks)
  228.     CALL    CRLF
  229. ;
  230. ;..............................................................................
  231. ;
  232. ; Main loop, 1 iteration/filename. Read one file header's worth of information
  233. ; into the structure named HDRBUF. Then process the information, using the
  234. ; named offsets of HDRBUF to refer to it. Repeat for each file.
  235. ;
  236. MEMLP:    LD    DE,HDRBUF    ; Destination spec for GETDTA
  237.     LD    BC,HDRLEN    ; Byte count for same
  238.     CALL    GETDTA        ; Do it
  239.     LD    BC,(NAMLEN)    ; Read the filename field into NAMBUF
  240.     PUSH    BC        ; BC is size of field
  241.     LD    DE,NAMBUF    ; Destination spec
  242.     CALL    GETDTA        ; Do it
  243.     LD    HL,NAMBUF    ; Spec source of data for DONAME
  244.     POP    BC        ; Field length spec for DONAME
  245.     CALL    DONAME        ; Process NAMBUF into NAME (see routine)
  246.     LD    BC,(XLEN)    ; Extra field length
  247.     LD    DE,NAMBUF    ; Spec target area, but data gets thrown out
  248.     CALL    GETDTA        ; Read the extra field, and ignore it
  249.     CALL    CABORT        ; Check for ^C, ^S, etc.
  250.     CALL    LIST        ; Process and list the whole entry
  251.     LD    HL,(NFILES)    ; Decr #of files counter
  252.     DEC    HL        ;
  253.     LD    (NFILES),HL    ;
  254.     LD    A,H        ;
  255.     OR    L        ;
  256.     JR    NZ,MEMLP    ; And loop until done
  257. ;...............................;
  258. ;                ;
  259.     CALL    LISTT        ; Done with all files; list totals
  260.     JP    RETCCP        ; And exit the program
  261. ;
  262. ;..............................................................................
  263. ;
  264. ; Routine to read spec'd #of bytes from the file to spec'd destination area
  265. ;
  266. ; Entry: BC has #of bytes we want to read from file
  267. ;     DE is destination pointer
  268. ;     "DTAPTR" keeps track of internal position within buffer "PAGE"
  269. ;
  270. GETDTA:    LD    A,B        ; Check if zero bytes needed
  271.     CP    16        ; This is a practical consideration - if this
  272.     JP    NC,BADZIP    ; - routine is called to read 4k+, there is
  273.     OR    C        ; - a serious problem. Prevent overwriting BDOS
  274.     RET    Z        ; Return when zero bytes needed.
  275.     DEC    BC        ; Else decr byte counter in advance
  276.     LD    HL,(DTAPTR)    ; Internal [source] pointer
  277.     INC    L        ; We are using 2nd half of page aligned bfr,
  278.     CALL    Z,RELOD        ; - so when l=0, time to reload and reset hl
  279.     LD    (DTAPTR),HL    ; Updated value
  280.     LD    A,(HL)        ; Get a byte
  281.     LD    (DE),A        ; Put it in it's destination
  282.     INC    DE        ; Incr dest pointer
  283.     JR    GETDTA        ; And possible loop for more data
  284. ;                ;
  285. ;................................
  286. ;                ;
  287. RELOD:    PUSH    DE        ;
  288.     PUSH    BC        ;
  289.     LD    DE,PAGE+80H    ; Read 1 record to 2nd half of this page
  290.     LD    H,D        ; Reset HL to this value for the program's use
  291.     LD    L,E        ;
  292.     LD    C,SETDMA    ;
  293.     CALL    BDOSAV        ;
  294.     LD    C,READ        ;
  295.     CALL    FCBDOS        ;
  296.     POP    BC        ; Rtn w/ HL reset, BC and DE unaffected
  297.     POP    DE        ;
  298.     RET            ;
  299. ;...............................;
  300. ;
  301. ;..............................................................................
  302. ;
  303. ; Filename processing code.
  304. ;
  305. ; Entry: BC has length of filename field
  306. ;     HL points to filename field
  307. ;     NAME is a 12 byte target area for processed filename
  308. ;
  309. ; Plan of attack: First strip off any pathnames contained in the filename
  310. ; field. This is accomplished by searching for any "/" characters; if one
  311. ; is found the effective beginning (and length) of the filename field is
  312. ; adjusted so as to start in a position one past the slash character; the
  313. ; process is repeated to find any additional slash characters.
  314. ; Next, we attempt to force the filename to fit an "8.3" mold (up to 8 chars,
  315. ; a dot, and up to 3 chars). If this is possible, the filename is displayed
  316. ; with appropriate additional spaces injected to align the dots. If, on the
  317. ; other hand, the filename has more than 8 characters before any dot, or has
  318. ; more than three characters following a dot, or has more than one dot, then
  319. ; up to 12 characters of the filename are displayed, left justified, with
  320. ; no additional spaces. If, in this case, the #of characters in the filename
  321. ; is greater than 12, then a ? will be displayed in the 1st column followed
  322. ; by the filename truncated to a length of eleven.
  323. ;
  324. DONAME:    CALL    BLNAME        ; Init the target field to spaces...
  325.     LD    A,'.'        ; And a dot.
  326.     LD    (NAME+8),A    ;
  327. ;................................
  328.                 ;
  329. SVINFO:    LD    (NLEN),BC    ; Current value of length of field
  330.     LD    (NPTR),HL    ; Current pointer to beginning of field
  331.     LD    A,'/'        ; Character to search for
  332.     CPIR            ; Do it
  333.     JR    Z,SVINFO    ; If found, re-save BC and HL (one past patch)
  334. ;...............................;
  335.     LD    IX,(NPTR)    ; IX: Source pointer
  336.     LD    HL,(NLEN)    ; HL: Overall field size counter
  337.     DEC    HL        ; (since it will decr to -1, not zero)
  338.     LD    DE,-1        ; DE: -1, used to decr HL
  339.     LD    IY,NAME        ; IY: Dest pointer
  340.     LD    B,8        ; B: Counts down from 8, then from 3
  341. ;................................
  342.                 ;
  343. LP8:    LD    A,(IX)        ; Get a char, incr source pntr
  344.     INC    IX        ;
  345.     CP    '.'        ; Dot?
  346.     JR    Z,GOTDOT    ; Br if so
  347.     LD    (IY),A        ; Else xfer to dest and incr that pntr
  348.     INC    IY        ;
  349.     ADD    HL,DE        ; Decr overall count
  350.     RET    NC        ; Means we are done
  351.     DJNZ    LP8        ; Counts down from 8
  352. ;...............................;
  353.     LD    A,(IX)        ; After 8 chars, check if next is a dot
  354.     INC    IX        ;
  355.     CP    '.'        ;
  356.     JR    NZ,LJFF        ; If not, exit and go use left-justified format
  357. ;                ;
  358. GOTDOT:    ADD    HL,DE        ; Decr overall count to account for the dot
  359.     RET    NC        ; Means we are done
  360.     LD    B,3        ; Length of ext part of filename
  361.     LD    IY,NAME+9    ; One past '.' in destination
  362. ;................................
  363. ;                ;
  364. LP3:    LD    A,(IX)        ; Transfer up to 3 characters after the dot
  365.     INC    IX        ;
  366.     CP    '.'        ; (a second dot violates the 8.3 format)
  367.     JR    Z,LJFF        ;
  368.     LD    (IY),A        ; Char goes here
  369.     INC    IY        ;
  370.     ADD    HL,DE        ; Decr overall count
  371.     RET    NC        ; Rtn if done
  372.     DJNZ    LP3        ; Else loop
  373. ;...............................;
  374.     JR    LJFF        ; More than 3 chars after dot; violates 8.3
  375. ;..............................................................................
  376. ;
  377. ; Filename is nonstandard. Display up to 12 characters, left justified, with
  378. ; no further processing. If >12 chars, display "?" plus 1st 11 characters.
  379. ;
  380. LJFF:    CALL    BLNAME        ; Init destination feild to blanks
  381.     LD    BC,(NLEN)    ;
  382.     LD    A,B        ; Check if overall length is >12
  383.     OR    A        ;
  384.     JR    NZ,TRUNC    ; Indeed, it is over 256!
  385.     LD    A,C        ;
  386.     CP    13        ;
  387.     JR    NC,TRUNC    ; If it is over 12
  388.     LD    DE,NAME        ; Destination
  389. ;
  390. XF:    LD    HL,(NPTR)    ; Beg of source field
  391.     LDIR            ; Do it
  392.     RET            ; And return
  393. ;
  394. TRUNC:    LD    A,'?'        ; Inject a leading "?", indicating truncation
  395.     LD    (NAME+0),A    ;
  396.     LD    BC,11        ; #of filename characters we can now display
  397.     LD    DE,NAME+1    ; Start them here
  398.     JR    XF        ; Use code above to xfer 11 characters
  399. ;
  400. ;..............................................................................
  401. ;
  402. ; Misc. subroutines
  403. ;................................
  404. ;                ;
  405. READ2:    LD    DE,PAGE        ; Random reads 2 records (HL, HL+1) to PAGE
  406.     CALL    RD1        ; Read the first
  407.     INC    HL        ; Incr rec#
  408.     LD    DE,PAGE+80H    ; Advance dma pntr
  409. ;
  410. RD1:    LD    (FCB+@R0),HL    ; Set rec#
  411.     LD    C,SETDMA    ;
  412.     CALL    BDOSAV        ; Set dma
  413.     LD    C,RDRND        ;
  414.     CALL    FCBDOS        ; Perform the read
  415.     RET            ;
  416. ;...............................;
  417. ;                ;
  418. PFN:    LD    B,8        ; Subr to type the filename at HL, w/o blanks
  419.     CALL    PFNAUX        ;
  420.     LD    A,'.'        ;
  421.     CALL    PCHAR        ;
  422.     LD    B,3        ;
  423. ;                ;
  424. PFNAUX:    LD    A,(HL)        ;
  425.     CP    ' '        ;
  426.     CALL    NZ,PCHAR    ;
  427.     INC    HL        ;
  428.     DJNZ    PFNAUX        ;
  429.     RET            ;
  430. ;................................
  431. ;                ;
  432. BLNAME:    PUSH    BC        ; Init 'name' to 8 blanks, '.', & 3 blanks
  433.     PUSH    HL        ;
  434.     LD    HL,NAME        ;
  435.     LD    B,12        ;
  436. ;                ;
  437. BLP:    LD    (HL),' '    ;
  438.     INC    HL        ;
  439.     DJNZ    BLP        ;
  440.     POP    HL        ;
  441.     POP    BC        ;
  442.     RET            ;
  443. ;...............................;
  444. ;
  445. ;..............................................................................
  446. ;
  447. ; Terminate. Return to CCP, or do a warm boot if desired
  448. ;
  449. RETCCP:    DS    0
  450. ;
  451.      IF    WBFLAG
  452.     JP    BOOT
  453.      ELSE
  454.     LD    SP,(OLDSTK)
  455.     RET
  456.      ENDIF
  457. ;..............................................................................
  458. ;
  459. GIVUSG:    LD    DE,USAGE    ; Give usage instructions and exit
  460. MSGRTS:    CALL    PRINTX
  461.     JR    RETCCP
  462. TOOBIG:    LD    DE,TBMSG    ; Type "ZIPfile too large" and exit
  463.     JR    MSGRTS
  464. BADZIP:    LD    DE,BZMSG    ; Type "ZIPfile corrupt" and exit
  465.     JR    MSGRTS
  466. ;
  467. NOSUCH:    LD    DE,NSMSG    ; Type "File not found" and exit
  468.     JR    MSGRTS
  469. ;
  470. ABORT:    LD    DE,ABMSG    ; Type "++ Aborted ++" and exit
  471.     JR    MSGRTS
  472. ;..............................................................................
  473. ;
  474. BDOSAV:    PUSH    BC        ; Call bdos; save all regs (except A)
  475.     PUSH    DE
  476.     PUSH    HL
  477.     PUSH    IX
  478.     PUSH    IY
  479.     CALL    BDOS
  480.     POP    IY
  481.     POP    IX
  482.     POP    HL
  483.     POP    DE
  484.     POP    BC
  485.     RET
  486. ;..............................................................................
  487. ;
  488. FCBDOS:    PUSH    DE        ; Call BDOS with DE = fcb; restore DE on exit
  489.     LD    DE,FCB
  490.     CALL    BDOSAV
  491.     POP    DE
  492.     RET
  493. ;
  494. ; ==========================================================================
  495. ; All code below this point is taken nearly verbatim from R. Freed's UNARC16
  496. ; ==========================================================================
  497. ;
  498. ; List file information
  499. ;
  500. LIST:    LD    HL,(TFILES)    ; Get total files so far
  501.     LD    A,H        ; Test if this is first file
  502.     OR    L
  503.     INC    HL        ; Add one more
  504.     LD    (TFILES),HL    ; Update total files
  505.     CALL    Z,LTITLE    ; If first file, list column titles
  506.     LD    DE,SIZE        ; Point to compressed file size
  507.     PUSH    DE        ; Save for later
  508.     LD    HL,TSIZE    ; Update total compressed size
  509.     CALL    LADD
  510.     LD    DE,LEN        ; Point to uncompressed length
  511.     PUSH    DE        ; Save for later
  512.     LD    HL,TLEN        ; Update total length
  513.     CALL    LADD
  514.     LD    HL,LINE        ; Setup listing line pointer
  515.     LD    DE,NAME        ; List file name from output FCB
  516.     LD    C,0        ; (with blank fill)
  517.     CALL    LNAME
  518.     POP    DE        ; Recover file length ptr
  519.     PUSH    DE        ; Save again for factor calculation
  520.     CALL    LTODA        ; List file length
  521.     CALL    LDISK        ; Compute and list disk space
  522.     CALL    LSTOW        ; List stowage method and version
  523.     POP    BC        ; Restore uncompressed length ptr
  524.     POP    DE        ; Restore compressed size ptr
  525.     CALL    LSIZE        ; List size and compression factor
  526.     LD    A,(DATE)    ; Check for valid file date
  527.     OR    A        ; (This anticipates no-date CP/M files)
  528.     JR    NZ,LIST1    ; Skip if valid
  529.     LD    B,18        ; Else, clear out date and time fields
  530.     CALL    FILLB
  531.     JR    LIST2        ; Skip
  532. ;
  533. LIST1:    CALL    LDATE        ; List file date
  534.     CALL    LTIME        ; List file time
  535. ;
  536. LIST2:    CALL    LCRC        ; List CRC value
  537. ;
  538. ; Terminate and print listing line
  539. ;
  540. LISTL:    LD    DE,LINE        ; Setup listing line ptr
  541.     JR    LIST3        ; Go finish up and list it
  542. ;
  543. ; List file totals
  544. ;
  545. LISTT:    LD    HL,LINE        ; Setup listing line ptr
  546.     LD    DE,(TFILES)    ; List total files
  547.     CALL    WTODA
  548.     LD    DE,TLEN        ; List total file length
  549.     PUSH    DE        ; And save ptr for factor calculation
  550.     CALL    LTODA
  551.     LD    DE,(TDISK)    ; List total disk space
  552.     CALL    LDISK1
  553.     LD    B,8        ; Fill next columns with blanks
  554.     CALL    FILLB
  555.     POP    BC        ; Recover total uncompressed length ptr
  556.     LD    DE,TSIZE    ; Get total compressed size ptr
  557.     CALL    LSIZE        ; List overall size, compression factor
  558.     LD    B,19        ; Fill next columns with blanks
  559.     CALL    FILLB
  560.     LD    DE,(TCRC32+2)    ; List sum of all CRC values
  561.     CALL    WHEX
  562.     LD    B,1
  563.     CALL    FILLB
  564.     LD    DE,(TCRC32+0)    ; LS word
  565.     CALL    WHEX
  566.     LD    DE,TOTALS    ; Point to totals string (precedes line)
  567. ;
  568. LIST3:    LD    (HL),0        ; Terminate listing line
  569.     JR    PRINTL        ; Go print it, followed by new line
  570. ;
  571. ; Print character.  Saves all registers except A.
  572. ;
  573. PCHAR:    PUSH    DE        ; Save register
  574. ;
  575. PCHAR2:    LD    E,A        ; Setup char
  576.     PUSH    BC
  577.     LD    C,CONOUT    ; Send to BDOS console output
  578.     CALL    BDOSAV
  579.     POP    BC
  580.     POP    DE        ; Restore register
  581.     RET            ; Return
  582. ;
  583. ; Print string on new line, then start another
  584. ;
  585. PRINTX:    CALL    CRLF
  586. ;
  587. ; Print string, then start new line
  588. ;
  589. PRINTL:    CALL    PRINTS
  590. ;
  591. ; Start new line
  592. ; Note: Must preserve DE
  593. ;
  594. CRLF:    LD    A,CR
  595.     CALL    PCHAR
  596.     LD    A,LF
  597.     CALL    PCHAR
  598.     LD    HL,LPSCT    ; Reached end of screen?
  599.     DEC    (HL)
  600.     RET    NZ        ; No, return
  601.     LD    A,LPSCRN    ; But are screen pauses enabled?
  602. ;
  603. LPS    EQU    $-1        ; (lines per screen = 0 if not)
  604. ;
  605.     OR    A
  606.     RET    Z        ; No, return
  607.     LD    (HL),A        ; Reset count of lines left
  608.     PUSH    DE        ; Save register
  609.     LD    DE,MORE        ; Print '[more]' on the new line
  610.     CALL    PRINTS
  611. ;
  612. CRLF1:    CALL    CABORT        ; Wait for char (or ^C abort)
  613.     JR    Z,CRLF1
  614.     PUSH    AF        ; Save input response
  615.     LD    DE,NOMORE    ; Blank out the '[more]' line
  616.     CALL    PRINTS
  617.     POP    AF        ; Restore response
  618.     POP    DE        ; Restore register
  619.     XOR    ' '        ; Was response the space bar?
  620.     RET    NZ        ; Anything else scrolls another screen
  621.     INC    A        ; Yes, set to pause after one more line
  622.     LD    (LPSCT),A
  623.     RET            ; Return
  624. ;
  625. ; Print string on new line
  626. ;
  627. ; Note: Restricted to at most 5 stack levels (c.f. CHECK).  CRLF will
  628. ;    not perform page pause during this restriction, but PCHAR will
  629. ;    execute PNAME (during ABOMSG print), so we're now at the limit!
  630. ;
  631. PRINT:    CALL    CRLF
  632. ;
  633. ; Print NUL-terminated string
  634. ;
  635. PRINTS:    LD    A,(DE)
  636.     OR    A
  637.     RET    Z
  638.     CALL    P,PCHAR        ; (Ignore help msg chars with MSB set)
  639.     INC    DE
  640.     JR    PRINTS
  641. ;
  642. ; List column titles
  643. ;
  644. ; Note: This saves some much-needed space, by using the same template
  645. ;    to generate the title line and the 'equal signs' separator line.
  646. ;
  647. LTITLE:    CALL    CRLF
  648.     LD    DE,TITLES
  649.     PUSH    DE
  650.     LD    A,(DE)
  651. ;
  652. LTITL1:    CP    '='        ; For titles, convert '=' to blank
  653.     JR    NZ,LTITL2
  654.     LD    A,' '
  655. ;
  656. LTITL2:    CALL    PCHAR
  657.     INC    DE
  658.     LD    A,(DE)
  659.     OR    A
  660.     JR    NZ,LTITL1
  661.     POP    DE
  662.     CALL    CRLF
  663. ;
  664. LTITL3:    LD    A,(DE)
  665.     OR    A
  666.     JR    Z,CRLF
  667.     CP    ' '        ; Separator converts non-blank to '='
  668.     JR    Z,LTITL4
  669.     LD    A,'='
  670. ;
  671. LTITL4:    CALL    PCHAR
  672.     INC    DE
  673.     JR    LTITL3
  674. ;
  675. ; List file name (rewritten for ZIP)
  676. ;
  677. LNAME:    LD    BC,12
  678.     EX    DE,HL
  679.     LDIR
  680.     EX    DE,HL
  681.     RET
  682. ;
  683. ; Compute and list disk space for uncompressed file
  684. ;
  685. LDISK:    PUSH    HL        ; Save line pointer
  686.     LD    HL,(LEN)    ; Convert file length to 1k disk space
  687.     LD    A,(LEN+2)    ; (Most we can handle here is 16 Mb)
  688.     LD    DE,1023        ; First, round up to next 1k
  689.     ADD    HL,DE
  690.     ADC    A,0
  691.     RRA            ; Now, shift to divide by 1k
  692.     RR    H
  693.     RRA
  694.     RR    H
  695.     AND    3FH
  696.     LD    L,H        ; Result -> HL
  697.     LD    H,A
  698.     LD    A,(LBLKSZ)    ; Get disk block size
  699.     DEC    A        ; Round up result accordingly
  700.     LD    E,A
  701.     LD    D,0
  702.     ADD    HL,DE
  703.     CPL            ; Form mask for lower bits
  704.     AND    L
  705.     LD    E,A        ; Final result -> DE
  706.     LD    D,H
  707.     LD    HL,(TDISK)    ; Update total disk space used
  708.     ADD    HL,DE
  709.     LD    (TDISK),HL
  710.     POP    HL        ; Restore line pointer
  711. ;
  712. LDISK1:    CALL    WTODA        ; List result
  713.     LD    (HL),'k'
  714.     INC    HL
  715.     RET
  716. ;
  717. ; List stowage method and version
  718. ;
  719. LSTOW:    CALL    FILL2B        ; Blanks first
  720.     EX    DE,HL
  721.     LD    HL,STOWTX    ; Point to stowage text table
  722.     LD    A,(METHOD)    ; Get header version no.
  723. ;    CP    7
  724. ;    cp    8        ; one more due to imploding    25Aug89    [jsf]
  725.     cp    10        ; two more due to red/tok    20Feb94 [jce]
  726.     JR    C,NCLAMP
  727. ;    LD    A,6
  728. ;    ld    a,7        ; one more due to imploding    25Aug89 [jsf]
  729.     cp    10        ; two more due to red/tok    20Feb94 [jce]
  730. ;
  731. NCLAMP:    SLA    A        ; X2
  732.     LD    C,A
  733.     RLA            ; X4
  734.     ADD    A,C        ; X6
  735.     LD    C,A
  736.     LD    B,0
  737.     ADD    HL,BC
  738.     LD    BC,6
  739. ;
  740. LSTOW1:    LDIR            ; List stowage text
  741.     EX    DE,HL        ; Restore line ptr
  742.     RET            ;
  743. ;
  744. ; List compressed file size and compression factor
  745. ;
  746. LSIZE:    PUSH    DE        ; Save compressed size ptr
  747.     PUSH    BC        ; Save uncompressed length ptr
  748.     CALL    LTODA        ; List compressed size
  749.     POP    DE        ; Recover length ptr
  750.     EX    (SP),HL        ; Save line ptr, recover size ptr
  751. ;
  752. ; Compute compression factor = 100 - [100*size/length]
  753. ; (HL = pointer to size, DE = pointer to length, A = result)
  754. ;
  755.     PUSH    DE        ; Save length ptr
  756.     CALL    LGET        ; Get BCDE = size
  757.     LD    H,B        ; Compute 100*size
  758.     LD    L,C        ; In HLIX:
  759.     PUSH    DE
  760.     POP    IX        ; Size
  761.     ADD    IX,IX
  762.     ADC    HL,HL        ; 2*size
  763.     ADD    IX,DE
  764.     ADC    HL,BC        ; 3*size
  765.     ADD    IX,IX
  766.     ADC    HL,HL        ; 6*size
  767.     ADD    IX,IX
  768.     ADC    HL,HL        ; 12*size
  769.     ADD    IX,IX
  770.     ADC    HL,HL        ; 24*size
  771.     ADD    IX,DE
  772.     ADC    HL,BC        ; 25*size
  773.     ADD    IX,IX
  774.     ADC    HL,HL        ; 50*size
  775.     ADD    IX,IX
  776.     ADC    HL,HL        ; 100*size
  777.     EX    (SP),HL        ; Swap back length ptr, save upper
  778.     CALL    LGET        ; Get BCDE = length
  779.     PUSH    IX
  780.     POP    HL        ; Now have (SP),HL = 100*size
  781.     LD    A,B        ; Length = 0?
  782.     OR    C        ; (Unlikely, but possible)
  783.     OR    D
  784.     OR    E
  785.     JR    Z,LSIZE2    ; Yes, go return result = 0
  786.     LD    A,101        ; Initialize down counter for result
  787. ;
  788. LSIZE1:    DEC    A        ; Divide by successive subtractions
  789.     SBC    HL,DE
  790.     EX    (SP),HL
  791.     SBC    HL,BC
  792.     EX    (SP),HL
  793.     JR    NC,LSIZE1    ; Loop until remainder < length
  794. ;
  795. LSIZE2:    POP    HL        ; Clean stack
  796.     POP    HL        ; Restore line ptr
  797.     CALL    BTODA        ; List the factor
  798.     LD    (HL),'%'
  799.     INC    HL
  800.     RET            ; Return
  801. ;
  802. ; List file creation date
  803. ;
  804. ; ARC files use MS-DOS 16-bit date format:
  805. ;
  806. ; Bits [15:9] = year - 1980
  807. ; Bits    [8:5] = month of year
  808. ; Bits    [4:0] = day of month
  809. ;
  810. ; (All zero means no date, checked before call to this routine)
  811. ;
  812. LDATE:    LD    A,(DATE)    ; Get date
  813.     AND    1FH        ; List day
  814.     CALL    BTODA
  815.     LD    (HL),' '    ; Then a blank
  816.     INC    HL
  817.     EX    DE,HL        ; Save listing line ptr
  818.     LD    HL,(DATE)    ; Get date again
  819.     PUSH    HL        ; Save for listing year (in upper byte)
  820.     ADD    HL,HL        ; Shift month into upper byte
  821.     ADD    HL,HL
  822.     ADD    HL,HL
  823.     LD    A,H        ; Get month
  824.     AND    0FH
  825.     CP    13        ; Make sure it's valid
  826.     JR    C,LDATE1
  827.     XOR    A        ; (Else will show as "???")
  828. ;
  829. LDATE1:    LD    C,A        ; Use to index to 3-byte string table
  830.     LD    B,0
  831.     LD    HL,MONTX
  832.     ADD    HL,BC
  833.     ADD    HL,BC
  834.     ADD    HL,BC
  835.     LD    C,3
  836.     LDIR            ; Move month text into listing line
  837.     EX    DE,HL        ; Restore line ptr
  838.     LD    (HL),' '    ; Then a blank
  839.     INC    HL
  840.     POP    AF        ; Recover high byte of date
  841.     SRL    A        ; Get 1980-relative year
  842.     ADD    A,80        ; Get true year in century
  843.  
  844. LDATE2:    LD    BC,256*2+'0'    ; Setup for 2 digits with high-zero fill
  845.     JP    BTOD        ; And convert binary to decimal ASCII
  846. ;
  847. ; List file creation time
  848. ; ARC files use MS-DOS 16-bit time format:
  849. ;
  850. ; Bits [15:11] = hour
  851. ; Bits [10:5]  = minute
  852. ; Bits    [4:0]  = second/2 (not shown here)
  853. ;
  854. LTIME:    EX    DE,HL        ; Save listing line ptr
  855.     LD    HL,(TIME)    ; Fetch time
  856.     LD    A,H        ; Copy high byte
  857.     RRA            ; Get hour
  858.     RRA
  859.     RRA
  860.     AND    1FH
  861. ;
  862. LTIME2:    ADD    HL,HL        ; Shift minutes up to high byte
  863.     ADD    HL,HL
  864.     ADD    HL,HL
  865.     PUSH    HL        ; Save minutes
  866.     EX    DE,HL        ; Recover listing line ptr
  867.     LD    B,3        ;
  868.     CALL    BTODB        ; List hour
  869.     LD    (HL),':'    ; Then ":"
  870.     INC    HL
  871.     POP    AF        ; Restore and list minutes
  872.     AND    3FH
  873.     CALL    LDATE2
  874.     RET            ; Return
  875. ;
  876. ; List hex CRC value
  877. ;
  878. LCRC:    CALL    FILL2B
  879.     PUSH    HL
  880.     LD    HL,(TCRC32+0)    ; Update CRC total
  881.     LD    DE,(CRC32+0)    ; LS word
  882.     ADD    HL,DE
  883.     LD    (TCRC32+0),HL
  884.     LD    HL,(TCRC32+2)
  885.     LD    DE,(CRC32+2)    ; MS word
  886.     ADC    HL,DE
  887.     LD    (TCRC32+2),HL
  888.     POP    HL
  889.     CALL    WHEX        ; List ms word
  890.     LD    B,1
  891.     CALL    FILLB
  892.     LD    DE,(CRC32+0)    ; Fall thru and list ls word
  893. ;
  894. ; List hex word in DE
  895. ;
  896. WHEX:    CALL    DHEX
  897.     LD    D,E
  898. ;
  899. ; List hex byte in D
  900. ;
  901. DHEX:    LD    (HL),D
  902.     RLD
  903.     CALL    AHEX
  904.     LD    A,D
  905. ;
  906. ; List hex nibble in A
  907. ;
  908. AHEX:    OR    0F0H
  909.     DAA
  910.     CP    60H
  911.     SBC    A,1FH
  912.     LD    (HL),A
  913.     INC    HL
  914.     RET
  915. ;
  916. ; A few decimal ASCII conversion callers, for convenience
  917. ;
  918. WTODA:    LD    B,5        ; List blank-filled word in 5 cols
  919. WTODB:    LD    C,' '        ; List blank-filled word in B cols
  920.     JR    WTOD        ; List C-filled word in B cols
  921. BTODA:    LD    B,4        ; List blank-filled byte in 4 cols
  922. BTODB:    LD    C,' '        ; List blank-filled byte in B cols
  923.     JR    BTOD        ; List C-filled byte in B cols
  924. LTODA:    LD    BC,9*256+' '    ; List blank-filled long in 9 cols
  925. ;    JR    LTOD
  926. ;
  927. ; Convert Long (or Word or Byte) Binary to Decimal ASCII
  928. ;
  929. ; R. A. Freed
  930. ; 2.0    15 Mar 85
  931. ;
  932. ; Entry:    A  = Unsigned 8-bit byte value (BTOD)
  933. ;        DE = Unsigned 16-bit word value (WTOD)
  934. ;        DE = Pointer to low byte of 32-bit long value (LTOD)
  935. ;        B  = Max. string length (0 implies 256, i.e. no limit)
  936. ;        C  = High-zero fill (0 to suppress high-zero digits)
  937. ;        HL = Address to store ASCII byte string
  938. ;
  939. ; Return:    HL = Adress of next byte after last stored
  940. ;
  941. ; Stack:    n+1 levels, where n = no. significant digits in output
  942. ;
  943. ; Notes:    If B > n, (B-n) leading fill chars (C non-zero) stored.
  944. ;        If B < n, high-order (n-B) digits are suppressed.
  945. ;        If only word or byte values need be converted, use the
  946. ;         shorter version of this routine (WTOD or BTOD) instead.
  947. ;
  948. RADIX    EQU    10        ; (Will work with any radix <= 10)
  949. ;
  950. LTOD:    PUSH    DE        ; Entry for 32-bit long pointed to by DE
  951.     EXX            ; Save caller's regs, swap in alt set
  952.     POP    HL        ; Get pointer and fetch value to HADE
  953.     LD    E,(HL)
  954.     INC    HL
  955.     LD    D,(HL)
  956.     INC    HL
  957.     LD    A,(HL)
  958.     INC    HL
  959.     LD    H,(HL)
  960.     EX    DE,HL        ; Value now in DAHL
  961.     JR    LTOD1        ; Join common code
  962.  
  963. BTOD:    LD    E,A        ; Entry for 8-bit byte in A
  964.     LD    D,0        ; Copy to 16-bit word in DE
  965. ;
  966. WTOD:    PUSH    DE        ; Entry for 16-bit word in DE, save it
  967.     EXX            ; Swap in alt regs for local use
  968.     POP    HL        ; Recover value in HL
  969.     XOR    A        ; Set to clear upper bits in DE
  970.     LD    D,A
  971. ;
  972. ; Common code for all entries
  973. ;
  974. LTOD1:    LD    E,A        ; Now have 32-bit value in DEHL
  975.     LD    C,RADIX        ; Setup radix for divides
  976.     SCF            ; Set first-time flag
  977.     PUSH    AF        ; Save for stack emptier when done
  978. ;
  979. ; Top of conversion loop
  980. ; Method:  Generate output digits on stack in reverse order.  Each loop
  981. ; divides the value by the radix.  Remainder is the next output digit,
  982. ; quotient becomes the dividend for the next loop.  Stop when get zero
  983. ; quotient or no. of digits = max. string length.  (Always generates at
  984. ; least one digit, i.e. zero value has one "significant" digit.)
  985. ;
  986. LTOD2:    CALL    DIVLB        ; Divide to get next digit
  987.     OR    '0'        ; Convert to ASCII (clears carry)
  988.     EXX            ; Swap in caller's regs
  989.     DJNZ    LTOD5        ; Skip if still more room in string
  990. ;
  991. ; All done (value fills string), this is the output loop
  992. ;
  993. LTOD3:    LD    (HL),A        ; Store digit in string
  994.     INC    HL        ; Bump string pointer
  995. ;
  996. LTOD4:    POP    AF        ; Unstack next digit
  997.     JR    NC,LTOD3    ; Loop if any
  998.     RET            ; Return to caller
  999. ;
  1000. ; Still more room in string, test if more significant digits
  1001. ;
  1002. LTOD5:    PUSH    AF        ; Stack this digit
  1003.     EXX            ; Swap back local regs
  1004.     LD    A,H        ; Last quotient = 0?
  1005.     OR    L
  1006.     OR    D
  1007.     OR    E
  1008.     JR    NZ,LTOD2    ; No, loop for next digit
  1009. ;
  1010. ; Can stop early (no more digits), handle leading zero-fill (if any)
  1011. ;
  1012.     EXX            ; Swap back caller's regs
  1013.     OR    C        ; Any leading fill wanted?
  1014.     JR    Z,LTOD4        ; No, go to output loop
  1015. ;
  1016. LTOD6:    LD    (HL),A        ; Store leading fill
  1017.     INC    HL        ; Bump string ptr
  1018.     DJNZ    LTOD6        ; Repeat until fill finished
  1019.     JR    LTOD4        ; Then go store the digits
  1020. ;
  1021. ; Note: The following general-purpose routine is currently used in this
  1022. ;    program only to divide longs by 10 (by decimal convertor, LTOD).
  1023. ;    Thus, a few unneeded code locations have been commented out.
  1024. ;    (May be restored if program requirements change.)
  1025. ; Unsigned Integer Division of Long (or Word or Byte) by Byte
  1026. ;
  1027. ; R. A. Freed
  1028. ;
  1029. ; Divisor in C, dividend in (A)DEHL or (A)HL or L (depends on call used)
  1030. ; Quotient returned in DEHL (or just HL), remainder in A
  1031. ;
  1032. ;DIVXLB:OR    A        ; 40-bit dividend in ADEHL (A < C)
  1033. ;;    JR    NZ,DIVLB1    ; Skip if have more than 32 bits
  1034. ;
  1035. DIVLB:    LD    A,D        ; 32-bit dividend in DEHL
  1036.     OR    E        ; But is it really only 16 bits?
  1037.     JR    Z,DIVWB        ; Yes, skip (speeds things up a lot)
  1038.     XOR    A        ; Clear high quotient for first divide
  1039. ;
  1040. DIVLB1:    CALL    DIVLB2        ; Get upper quotient first, then swap:
  1041.  
  1042. DIVLB2:    EX    DE,HL        ; Upper quotient in DE, lower in HL
  1043. ;
  1044. DIVXWB:    OR    A        ; 24-bit dividend in AHL (A < C)
  1045. ;
  1046.     JR    NZ,DIVWB1    ; Skip if have more than 16 bits
  1047. ;
  1048. DIVWB:    LD    A,H        ; 16-bit dividend in HL
  1049.     CP    C        ; Will quotient be less than 8 bits?
  1050.     JR    C,DIVBB1    ; Yes, skip (small dividend speed-up)
  1051.     XOR    A        ; Clear high quotient
  1052. DIVWB1:    LD    B,16        ; Setup count for 16-bit divide
  1053.     JR    DIVB        ; Skip to divide loop
  1054. ;;DIVBB:XOR    A        ; 8-bit dividend in L
  1055. ;
  1056. DIVBB1:    LD    H,L        ; For very small nos., pre-shift 8 bits
  1057.     LD    L,0        ; High byte of quotient will be zero
  1058.     LD    B,8        ; Setup count for 8-bit divide
  1059. ;
  1060. ; Top of divide loop (vanilla in-place shift-and-subtract)
  1061. ;
  1062. DIVB:    ADD    HL,HL        ; Divide AHL (B=16) or AH (B=8) by C
  1063.     RLA            ; Shift out next remainder bit
  1064. ;;    JR    C,DIVB1     ; (This needed only for divsors > 128)
  1065.     CP    C        ; Greater than divisor?
  1066.     JR    C,DIVB2        ; No, skip (next quotient bit is 0)
  1067. ;
  1068. DIVB1:    SUB    C        ; Yes, reduce remainder
  1069.     INC    L        ; And set quotient bit to 1
  1070. ;
  1071. DIVB2:    DJNZ    DIVB        ; Loop for no. bits in quotient
  1072.     RET            ; Done (quotient in HL, remainder in A)
  1073. ;
  1074. ; Fetch a long (4-byte) value
  1075. ;
  1076. LGET:    LD    E,(HL)        ; Fetch BCDE from (HL)
  1077.     INC    HL
  1078.     LD    D,(HL)
  1079.     INC    HL
  1080.     LD    C,(HL)
  1081.     INC    HL
  1082.     LD    B,(HL)
  1083.     RET
  1084. ;
  1085. ; Add two longs
  1086. ;
  1087. LADD:    LD    B,4        ; (DE) + (HL) -> (HL)
  1088.     OR    A
  1089. ;
  1090. LADD1:    LD    A,(DE)
  1091.     ADC    A,(HL)
  1092.     LD    (HL),A
  1093.     INC    HL
  1094.     INC    DE
  1095.     DJNZ    LADD1
  1096.     RET
  1097. ;
  1098. ; Fill routines
  1099. ;
  1100. FILL2B:    LD    B,2        ; Fill 2 blanks
  1101. ;
  1102. FILLB:    LD    C,' '        ; Fill B blanks
  1103. ;
  1104. FILL:    LD    (HL),C        ; Fill B bytes with char in C
  1105.     INC    HL
  1106.     DJNZ    FILL
  1107.     RET
  1108. ;
  1109. ; Check for CTRL-C abort (and/or read console char if any). Destroys C.
  1110. ;
  1111. CABORT:    LD    C,CONST        ; Get console status
  1112.     CALL    BDOSAV
  1113.     OR    A        ; Character ready?
  1114.     RET    Z        ; Return (Z set) if not
  1115.     LD    C,CONIN        ; Input console char (echo if printable)
  1116.     CALL    BDOSAV
  1117. ;
  1118. ; Note: Following added in UNARC 1.5 to handle any ^S input which is not
  1119. ;    detected by CP/M 2.2 BDOS.
  1120. ;
  1121.     AND    7FH        ; Mask to 7 bits
  1122.     CP    CTLS        ; Is it CTRL-S (suspend output)?
  1123.     LD    C,CONIN
  1124.     CALL    Z,BDOSAV    ; Yes, wait for another char
  1125.     AND    7FH        ; Mask to 7 bits
  1126.     CP    CTLC        ; Is it CTRL-C?
  1127.     JR    Z,GABORT    ; Yes, go abort
  1128.     CP    CTLK        ; Or is it CTRL-K (RCP/M alternate ^C)?
  1129.     RET    NZ        ; No, return char (and NZ) to caller
  1130. ;
  1131. GABORT:    JP    ABORT        ; Abort
  1132. ;
  1133. MORE:    DB    '[more] ',0
  1134. NOMORE:    DB    CR,'        ',HT,CR,0
  1135. ABMSG:    DB    '++ Aborted ++',0
  1136. TBMSG:    DB    'Zipfile too large.',0
  1137. BZMSG:    DB    'Zipfile corrupt.',0
  1138. NSMSG:    DB    'Not found.',0
  1139. IDSTR:    DB    CR,LF,'Zipfile = ',0
  1140. USAGE:    DB    'ZIPDIR v1.0 SGG  03-15-89   ',CR,LF,LF
  1141.     DB    'Usage:  ZD  <zipfile>[.zip]',0
  1142. MONTX:    DB    '???JanFebMarAprMayJunJulAugSepOctNovDec'
  1143. STOWTX:    DB    'Stored'
  1144.     DB    'Shrunk'
  1145.     DB    'Reduc1'
  1146.     DB    'Reduc2'
  1147.     DB    'Reduc3'
  1148.     DB    'Reduc4'
  1149.     db    'Implod'        ;for PKZIP 1.01        25Aug89 [jsf]
  1150.     DB    'Token '        ;            20Feb94 [jce]
  1151.     DB    'Deflat'        ;            20Feb94 [jce]
  1152.     DB    ' ???  '
  1153. TITLES:    DB    'Name========  =Length  Disk  Method  =Stored Save'
  1154.     DB    'd ==Date=== Time=  ===CRC==='
  1155. ;
  1156. LINLEN    EQU    $-TITLES
  1157. ;
  1158.     DB    0
  1159. TOTALS:    DB    '        ====  =======  ====          =======  ==='
  1160.     DB    '                   ========='
  1161.     DB    CR,LF
  1162.     DB    'Total  '    ; (LINE must follow!)
  1163. LINE:    DS    LINLEN+1    ; Listing line buffer (follow TOTALS!)
  1164. LBLKSZ:    DB    1        ; Disk allocation block size for listing
  1165. ;----
  1166. ;
  1167. TOTS    EQU    $        ; Start of listing totals
  1168. TFILES:    DS    2        ; Total files processed
  1169. TLEN:    DS    4        ; Total uncompressed bytes
  1170. TDISK:    DS    2        ; Total 1K disk blocks
  1171. TSIZE:    DS    4        ; Total compressed bytes
  1172. TCRC32:    DS    4        ; Total of all CRC values
  1173. TOTC    EQU    $-TOTS        ; Count of bytes to clear
  1174. ;................................
  1175. ;                ;
  1176. HDRBUF    EQU    $        ; ZIP file header buffer...
  1177. ;                ;
  1178. SIG:    DS    4        ; Central file header signature
  1179. PRGVER:    DS    2        ; Program version
  1180. EXTVER:    DS    2        ; Version needed to extract
  1181. BITFLG:    DS    2        ; General purpose bit flag
  1182. METHOD:    DS    2        ; Compression method
  1183. TIME:    DS    2        ; Modification time
  1184. DATE:    DS    2        ; Modification date
  1185. CRC32:    DS    4        ; 32-bit CRC check of uncompressed file
  1186. SIZE:    DS    4        ; Compressed bytes
  1187. LEN:    DS    4        ; Uncompressed bytes
  1188. NAMLEN:    DS    2        ; Filename length
  1189. XLEN:    DS    2        ; Extra field length
  1190. COMLEN:    DS    2        ; File comment length
  1191. STDISK:    DS    2        ; Starting disk number
  1192. INTATR:    DS    2        ; Internal file attributes
  1193. EXTATR:    DS    4        ; External file attributes
  1194. HDRLOC:    DS    4        ; Relative offset of local header
  1195. ;                ;
  1196. HDRLEN    EQU    $-HDRBUF    ; Length of all of the above
  1197. ;...............................;
  1198. NAME:    DS    12        ; Post-processed filename
  1199. ;...............................;
  1200. LPSCT:    DS    1        ; Lines per screen counter
  1201. NFILES:    DS    2        ; #of files in the ZIP to list
  1202. NLEN:    DS    2        ;
  1203. NPTR:    DS    2        ;
  1204. DTAPTR:    DS    2        ;
  1205. OLDSTK:    DS    2        ; Save system stack here
  1206.     DS    80H        ; Stack area for program's use
  1207. ;
  1208. STACK    EQU    $        ; TOS
  1209. ;
  1210. NXTPG    EQU    ($+00FFH) AND (0FF00H)
  1211. ;
  1212. ;
  1213.     ORG    NXTPG
  1214. ;
  1215. ;
  1216. PAGE:    DS    100H
  1217. ;
  1218. NAMBUF    EQU    $
  1219. ;
  1220.     END
  1221.