home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / zip / zipdir11.lbr / ZD.ZZ0 / ZD.Z80
Encoding:
Text File  |  1989-09-08  |  34.1 KB  |  1,217 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    23        ; 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.     JR    C,NCLAMP
  726. ;    LD    A,6
  727.     ld    a,7        ; one more due to imploding    25Aug89 [jsf]
  728. ;
  729. NCLAMP:    SLA    A        ; X2
  730.     LD    C,A
  731.     RLA            ; X4
  732.     ADD    A,C        ; X6
  733.     LD    C,A
  734.     LD    B,0
  735.     ADD    HL,BC
  736.     LD    BC,6
  737. ;
  738. LSTOW1:    LDIR            ; List stowage text
  739.     EX    DE,HL        ; Restore line ptr
  740.     RET            ;
  741. ;
  742. ; List compressed file size and compression factor
  743. ;
  744. LSIZE:    PUSH    DE        ; Save compressed size ptr
  745.     PUSH    BC        ; Save uncompressed length ptr
  746.     CALL    LTODA        ; List compressed size
  747.     POP    DE        ; Recover length ptr
  748.     EX    (SP),HL        ; Save line ptr, recover size ptr
  749. ;
  750. ; Compute compression factor = 100 - [100*size/length]
  751. ; (HL = pointer to size, DE = pointer to length, A = result)
  752. ;
  753.     PUSH    DE        ; Save length ptr
  754.     CALL    LGET        ; Get BCDE = size
  755.     LD    H,B        ; Compute 100*size
  756.     LD    L,C        ; In HLIX:
  757.     PUSH    DE
  758.     POP    IX        ; Size
  759.     ADD    IX,IX
  760.     ADC    HL,HL        ; 2*size
  761.     ADD    IX,DE
  762.     ADC    HL,BC        ; 3*size
  763.     ADD    IX,IX
  764.     ADC    HL,HL        ; 6*size
  765.     ADD    IX,IX
  766.     ADC    HL,HL        ; 12*size
  767.     ADD    IX,IX
  768.     ADC    HL,HL        ; 24*size
  769.     ADD    IX,DE
  770.     ADC    HL,BC        ; 25*size
  771.     ADD    IX,IX
  772.     ADC    HL,HL        ; 50*size
  773.     ADD    IX,IX
  774.     ADC    HL,HL        ; 100*size
  775.     EX    (SP),HL        ; Swap back length ptr, save upper
  776.     CALL    LGET        ; Get BCDE = length
  777.     PUSH    IX
  778.     POP    HL        ; Now have (SP),HL = 100*size
  779.     LD    A,B        ; Length = 0?
  780.     OR    C        ; (Unlikely, but possible)
  781.     OR    D
  782.     OR    E
  783.     JR    Z,LSIZE2    ; Yes, go return result = 0
  784.     LD    A,101        ; Initialize down counter for result
  785. ;
  786. LSIZE1:    DEC    A        ; Divide by successive subtractions
  787.     SBC    HL,DE
  788.     EX    (SP),HL
  789.     SBC    HL,BC
  790.     EX    (SP),HL
  791.     JR    NC,LSIZE1    ; Loop until remainder < length
  792. ;
  793. LSIZE2:    POP    HL        ; Clean stack
  794.     POP    HL        ; Restore line ptr
  795.     CALL    BTODA        ; List the factor
  796.     LD    (HL),'%'
  797.     INC    HL
  798.     RET            ; Return
  799. ;
  800. ; List file creation date
  801. ;
  802. ; ARC files use MS-DOS 16-bit date format:
  803. ;
  804. ; Bits [15:9] = year - 1980
  805. ; Bits    [8:5] = month of year
  806. ; Bits    [4:0] = day of month
  807. ;
  808. ; (All zero means no date, checked before call to this routine)
  809. ;
  810. LDATE:    LD    A,(DATE)    ; Get date
  811.     AND    1FH        ; List day
  812.     CALL    BTODA
  813.     LD    (HL),' '    ; Then a blank
  814.     INC    HL
  815.     EX    DE,HL        ; Save listing line ptr
  816.     LD    HL,(DATE)    ; Get date again
  817.     PUSH    HL        ; Save for listing year (in upper byte)
  818.     ADD    HL,HL        ; Shift month into upper byte
  819.     ADD    HL,HL
  820.     ADD    HL,HL
  821.     LD    A,H        ; Get month
  822.     AND    0FH
  823.     CP    13        ; Make sure it's valid
  824.     JR    C,LDATE1
  825.     XOR    A        ; (Else will show as "???")
  826. ;
  827. LDATE1:    LD    C,A        ; Use to index to 3-byte string table
  828.     LD    B,0
  829.     LD    HL,MONTX
  830.     ADD    HL,BC
  831.     ADD    HL,BC
  832.     ADD    HL,BC
  833.     LD    C,3
  834.     LDIR            ; Move month text into listing line
  835.     EX    DE,HL        ; Restore line ptr
  836.     LD    (HL),' '    ; Then a blank
  837.     INC    HL
  838.     POP    AF        ; Recover high byte of date
  839.     SRL    A        ; Get 1980-relative year
  840.     ADD    A,80        ; Get true year in century
  841.  
  842. LDATE2:    LD    BC,256*2+'0'    ; Setup for 2 digits with high-zero fill
  843.     JP    BTOD        ; And convert binary to decimal ASCII
  844. ;
  845. ; List file creation time
  846. ; ARC files use MS-DOS 16-bit time format:
  847. ;
  848. ; Bits [15:11] = hour
  849. ; Bits [10:5]  = minute
  850. ; Bits    [4:0]  = second/2 (not shown here)
  851. ;
  852. LTIME:    EX    DE,HL        ; Save listing line ptr
  853.     LD    HL,(TIME)    ; Fetch time
  854.     LD    A,H        ; Copy high byte
  855.     RRA            ; Get hour
  856.     RRA
  857.     RRA
  858.     AND    1FH
  859. ;
  860. LTIME2:    ADD    HL,HL        ; Shift minutes up to high byte
  861.     ADD    HL,HL
  862.     ADD    HL,HL
  863.     PUSH    HL        ; Save minutes
  864.     EX    DE,HL        ; Recover listing line ptr
  865.     LD    B,3        ;
  866.     CALL    BTODB        ; List hour
  867.     LD    (HL),':'    ; Then ":"
  868.     INC    HL
  869.     POP    AF        ; Restore and list minutes
  870.     AND    3FH
  871.     CALL    LDATE2
  872.     RET            ; Return
  873. ;
  874. ; List hex CRC value
  875. ;
  876. LCRC:    CALL    FILL2B
  877.     PUSH    HL
  878.     LD    HL,(TCRC32+0)    ; Update CRC total
  879.     LD    DE,(CRC32+0)    ; LS word
  880.     ADD    HL,DE
  881.     LD    (TCRC32+0),HL
  882.     LD    HL,(TCRC32+2)
  883.     LD    DE,(CRC32+2)    ; MS word
  884.     ADC    HL,DE
  885.     LD    (TCRC32+2),HL
  886.     POP    HL
  887.     CALL    WHEX        ; List ms word
  888.     LD    B,1
  889.     CALL    FILLB
  890.     LD    DE,(CRC32+0)    ; Fall thru and list ls word
  891. ;
  892. ; List hex word in DE
  893. ;
  894. WHEX:    CALL    DHEX
  895.     LD    D,E
  896. ;
  897. ; List hex byte in D
  898. ;
  899. DHEX:    LD    (HL),D
  900.     RLD
  901.     CALL    AHEX
  902.     LD    A,D
  903. ;
  904. ; List hex nibble in A
  905. ;
  906. AHEX:    OR    0F0H
  907.     DAA
  908.     CP    60H
  909.     SBC    A,1FH
  910.     LD    (HL),A
  911.     INC    HL
  912.     RET
  913. ;
  914. ; A few decimal ASCII conversion callers, for convenience
  915. ;
  916. WTODA:    LD    B,5        ; List blank-filled word in 5 cols
  917. WTODB:    LD    C,' '        ; List blank-filled word in B cols
  918.     JR    WTOD        ; List C-filled word in B cols
  919. BTODA:    LD    B,4        ; List blank-filled byte in 4 cols
  920. BTODB:    LD    C,' '        ; List blank-filled byte in B cols
  921.     JR    BTOD        ; List C-filled byte in B cols
  922. LTODA:    LD    BC,9*256+' '    ; List blank-filled long in 9 cols
  923. ;    JR    LTOD
  924. ;
  925. ; Convert Long (or Word or Byte) Binary to Decimal ASCII
  926. ;
  927. ; R. A. Freed
  928. ; 2.0    15 Mar 85
  929. ;
  930. ; Entry:    A  = Unsigned 8-bit byte value (BTOD)
  931. ;        DE = Unsigned 16-bit word value (WTOD)
  932. ;        DE = Pointer to low byte of 32-bit long value (LTOD)
  933. ;        B  = Max. string length (0 implies 256, i.e. no limit)
  934. ;        C  = High-zero fill (0 to suppress high-zero digits)
  935. ;        HL = Address to store ASCII byte string
  936. ;
  937. ; Return:    HL = Adress of next byte after last stored
  938. ;
  939. ; Stack:    n+1 levels, where n = no. significant digits in output
  940. ;
  941. ; Notes:    If B > n, (B-n) leading fill chars (C non-zero) stored.
  942. ;        If B < n, high-order (n-B) digits are suppressed.
  943. ;        If only word or byte values need be converted, use the
  944. ;         shorter version of this routine (WTOD or BTOD) instead.
  945. ;
  946. RADIX    EQU    10        ; (Will work with any radix <= 10)
  947. ;
  948. LTOD:    PUSH    DE        ; Entry for 32-bit long pointed to by DE
  949.     EXX            ; Save caller's regs, swap in alt set
  950.     POP    HL        ; Get pointer and fetch value to HADE
  951.     LD    E,(HL)
  952.     INC    HL
  953.     LD    D,(HL)
  954.     INC    HL
  955.     LD    A,(HL)
  956.     INC    HL
  957.     LD    H,(HL)
  958.     EX    DE,HL        ; Value now in DAHL
  959.     JR    LTOD1        ; Join common code
  960.  
  961. BTOD:    LD    E,A        ; Entry for 8-bit byte in A
  962.     LD    D,0        ; Copy to 16-bit word in DE
  963. ;
  964. WTOD:    PUSH    DE        ; Entry for 16-bit word in DE, save it
  965.     EXX            ; Swap in alt regs for local use
  966.     POP    HL        ; Recover value in HL
  967.     XOR    A        ; Set to clear upper bits in DE
  968.     LD    D,A
  969. ;
  970. ; Common code for all entries
  971. ;
  972. LTOD1:    LD    E,A        ; Now have 32-bit value in DEHL
  973.     LD    C,RADIX        ; Setup radix for divides
  974.     SCF            ; Set first-time flag
  975.     PUSH    AF        ; Save for stack emptier when done
  976. ;
  977. ; Top of conversion loop
  978. ; Method:  Generate output digits on stack in reverse order.  Each loop
  979. ; divides the value by the radix.  Remainder is the next output digit,
  980. ; quotient becomes the dividend for the next loop.  Stop when get zero
  981. ; quotient or no. of digits = max. string length.  (Always generates at
  982. ; least one digit, i.e. zero value has one "significant" digit.)
  983. ;
  984. LTOD2:    CALL    DIVLB        ; Divide to get next digit
  985.     OR    '0'        ; Convert to ASCII (clears carry)
  986.     EXX            ; Swap in caller's regs
  987.     DJNZ    LTOD5        ; Skip if still more room in string
  988. ;
  989. ; All done (value fills string), this is the output loop
  990. ;
  991. LTOD3:    LD    (HL),A        ; Store digit in string
  992.     INC    HL        ; Bump string pointer
  993. ;
  994. LTOD4:    POP    AF        ; Unstack next digit
  995.     JR    NC,LTOD3    ; Loop if any
  996.     RET            ; Return to caller
  997. ;
  998. ; Still more room in string, test if more significant digits
  999. ;
  1000. LTOD5:    PUSH    AF        ; Stack this digit
  1001.     EXX            ; Swap back local regs
  1002.     LD    A,H        ; Last quotient = 0?
  1003.     OR    L
  1004.     OR    D
  1005.     OR    E
  1006.     JR    NZ,LTOD2    ; No, loop for next digit
  1007. ;
  1008. ; Can stop early (no more digits), handle leading zero-fill (if any)
  1009. ;
  1010.     EXX            ; Swap back caller's regs
  1011.     OR    C        ; Any leading fill wanted?
  1012.     JR    Z,LTOD4        ; No, go to output loop
  1013. ;
  1014. LTOD6:    LD    (HL),A        ; Store leading fill
  1015.     INC    HL        ; Bump string ptr
  1016.     DJNZ    LTOD6        ; Repeat until fill finished
  1017.     JR    LTOD4        ; Then go store the digits
  1018. ;
  1019. ; Note: The following general-purpose routine is currently used in this
  1020. ;    program only to divide longs by 10 (by decimal convertor, LTOD).
  1021. ;    Thus, a few unneeded code locations have been commented out.
  1022. ;    (May be restored if program requirements change.)
  1023. ; Unsigned Integer Division of Long (or Word or Byte) by Byte
  1024. ;
  1025. ; R. A. Freed
  1026. ;
  1027. ; Divisor in C, dividend in (A)DEHL or (A)HL or L (depends on call used)
  1028. ; Quotient returned in DEHL (or just HL), remainder in A
  1029. ;
  1030. ;DIVXLB:OR    A        ; 40-bit dividend in ADEHL (A < C)
  1031. ;;    JR    NZ,DIVLB1    ; Skip if have more than 32 bits
  1032. ;
  1033. DIVLB:    LD    A,D        ; 32-bit dividend in DEHL
  1034.     OR    E        ; But is it really only 16 bits?
  1035.     JR    Z,DIVWB        ; Yes, skip (speeds things up a lot)
  1036.     XOR    A        ; Clear high quotient for first divide
  1037. ;
  1038. DIVLB1:    CALL    DIVLB2        ; Get upper quotient first, then swap:
  1039.  
  1040. DIVLB2:    EX    DE,HL        ; Upper quotient in DE, lower in HL
  1041. ;
  1042. DIVXWB:    OR    A        ; 24-bit dividend in AHL (A < C)
  1043. ;
  1044.     JR    NZ,DIVWB1    ; Skip if have more than 16 bits
  1045. ;
  1046. DIVWB:    LD    A,H        ; 16-bit dividend in HL
  1047.     CP    C        ; Will quotient be less than 8 bits?
  1048.     JR    C,DIVBB1    ; Yes, skip (small dividend speed-up)
  1049.     XOR    A        ; Clear high quotient
  1050. DIVWB1:    LD    B,16        ; Setup count for 16-bit divide
  1051.     JR    DIVB        ; Skip to divide loop
  1052. ;;DIVBB:XOR    A        ; 8-bit dividend in L
  1053. ;
  1054. DIVBB1:    LD    H,L        ; For very small nos., pre-shift 8 bits
  1055.     LD    L,0        ; High byte of quotient will be zero
  1056.     LD    B,8        ; Setup count for 8-bit divide
  1057. ;
  1058. ; Top of divide loop (vanilla in-place shift-and-subtract)
  1059. ;
  1060. DIVB:    ADD    HL,HL        ; Divide AHL (B=16) or AH (B=8) by C
  1061.     RLA            ; Shift out next remainder bit
  1062. ;;    JR    C,DIVB1     ; (This needed only for divsors > 128)
  1063.     CP    C        ; Greater than divisor?
  1064.     JR    C,DIVB2        ; No, skip (next quotient bit is 0)
  1065. ;
  1066. DIVB1:    SUB    C        ; Yes, reduce remainder
  1067.     INC    L        ; And set quotient bit to 1
  1068. ;
  1069. DIVB2:    DJNZ    DIVB        ; Loop for no. bits in quotient
  1070.     RET            ; Done (quotient in HL, remainder in A)
  1071. ;
  1072. ; Fetch a long (4-byte) value
  1073. ;
  1074. LGET:    LD    E,(HL)        ; Fetch BCDE from (HL)
  1075.     INC    HL
  1076.     LD    D,(HL)
  1077.     INC    HL
  1078.     LD    C,(HL)
  1079.     INC    HL
  1080.     LD    B,(HL)
  1081.     RET
  1082. ;
  1083. ; Add two longs
  1084. ;
  1085. LADD:    LD    B,4        ; (DE) + (HL) -> (HL)
  1086.     OR    A
  1087. ;
  1088. LADD1:    LD    A,(DE)
  1089.     ADC    A,(HL)
  1090.     LD    (HL),A
  1091.     INC    HL
  1092.     INC    DE
  1093.     DJNZ    LADD1
  1094.     RET
  1095. ;
  1096. ; Fill routines
  1097. ;
  1098. FILL2B:    LD    B,2        ; Fill 2 blanks
  1099. ;
  1100. FILLB:    LD    C,' '        ; Fill B blanks
  1101. ;
  1102. FILL:    LD    (HL),C        ; Fill B bytes with char in C
  1103.     INC    HL
  1104.     DJNZ    FILL
  1105.     RET
  1106. ;
  1107. ; Check for CTRL-C abort (and/or read console char if any). Destroys C.
  1108. ;
  1109. CABORT:    LD    C,CONST        ; Get console status
  1110.     CALL    BDOSAV
  1111.     OR    A        ; Character ready?
  1112.     RET    Z        ; Return (Z set) if not
  1113.     LD    C,CONIN        ; Input console char (echo if printable)
  1114.     CALL    BDOSAV
  1115. ;
  1116. ; Note: Following added in UNARC 1.5 to handle any ^S input which is not
  1117. ;    detected by CP/M 2.2 BDOS.
  1118. ;
  1119.     AND    7FH        ; Mask to 7 bits
  1120.     CP    CTLS        ; Is it CTRL-S (suspend output)?
  1121.     LD    C,CONIN
  1122.     CALL    Z,BDOSAV    ; Yes, wait for another char
  1123.     AND    7FH        ; Mask to 7 bits
  1124.     CP    CTLC        ; Is it CTRL-C?
  1125.     JR    Z,GABORT    ; Yes, go abort
  1126.     CP    CTLK        ; Or is it CTRL-K (RCP/M alternate ^C)?
  1127.     RET    NZ        ; No, return char (and NZ) to caller
  1128. ;
  1129. GABORT:    JP    ABORT        ; Abort
  1130. ;
  1131. MORE:    DB    '[more] ',0
  1132. NOMORE:    DB    CR,'        ',HT,CR,0
  1133. ABMSG:    DB    '++ Aborted ++',0
  1134. TBMSG:    DB    'Zipfile too large.',0
  1135. BZMSG:    DB    'Zipfile corrupt.',0
  1136. NSMSG:    DB    'Not found.',0
  1137. IDSTR:    DB    CR,LF,'Zipfile = ',0
  1138. USAGE:    DB    'ZIPDIR v1.0 SGG  03-15-89   ',CR,LF,LF
  1139.     DB    'Usage:  ZD  <zipfile>[.zip]',0
  1140. MONTX:    DB    '???JanFebMarAprMayJunJulAugSepOctNovDec'
  1141. STOWTX:    DB    'Stored'
  1142.     DB    'Shrunk'
  1143.     DB    'Reduc1'
  1144.     DB    'Reduc2'
  1145.     DB    'Reduc3'
  1146.     DB    'Reduc4'
  1147.     db    'Implod'        ;for PKZIP 1.01        25Aug89 [jsf]
  1148.     DB    ' ???  '
  1149. TITLES:    DB    'Name========  =Length  Disk  Method  =Stored Save'
  1150.     DB    'd ==Date=== Time=  ===CRC==='
  1151. ;
  1152. LINLEN    EQU    $-TITLES
  1153. ;
  1154.     DB    0
  1155. TOTALS:    DB    '        ====  =======  ====          =======  ==='
  1156.     DB    '                   ========='
  1157.     DB    CR,LF
  1158.     DB    'Total  '    ; (LINE must follow!)
  1159. LINE:    DS    LINLEN+1    ; Listing line buffer (follow TOTALS!)
  1160. LBLKSZ:    DB    1        ; Disk allocation block size for listing
  1161. ;----
  1162. ;
  1163. TOTS    EQU    $        ; Start of listing totals
  1164. TFILES:    DS    2        ; Total files processed
  1165. TLEN:    DS    4        ; Total uncompressed bytes
  1166. TDISK:    DS    2        ; Total 1K disk blocks
  1167. TSIZE:    DS    4        ; Total compressed bytes
  1168. TCRC32:    DS    4        ; Total of all CRC values
  1169. TOTC    EQU    $-TOTS        ; Count of bytes to clear
  1170. ;................................
  1171. ;                ;
  1172. HDRBUF    EQU    $        ; ZIP file header buffer...
  1173. ;                ;
  1174. SIG:    DS    4        ; Central file header signature
  1175. PRGVER:    DS    2        ; Program version
  1176. EXTVER:    DS    2        ; Version needed to extract
  1177. BITFLG:    DS    2        ; General purpose bit flag
  1178. METHOD:    DS    2        ; Compression method
  1179. TIME:    DS    2        ; Modification time
  1180. DATE:    DS    2        ; Modification date
  1181. CRC32:    DS    4        ; 32-bit CRC check of uncompressed file
  1182. SIZE:    DS    4        ; Compressed bytes
  1183. LEN:    DS    4        ; Uncompressed bytes
  1184. NAMLEN:    DS    2        ; Filename length
  1185. XLEN:    DS    2        ; Extra field length
  1186. COMLEN:    DS    2        ; File comment length
  1187. STDISK:    DS    2        ; Starting disk number
  1188. INTATR:    DS    2        ; Internal file attributes
  1189. EXTATR:    DS    4        ; External file attributes
  1190. HDRLOC:    DS    4        ; Relative offset of local header
  1191. ;                ;
  1192. HDRLEN    EQU    $-HDRBUF    ; Length of all of the above
  1193. ;...............................;
  1194. NAME:    DS    12        ; Post-processed filename
  1195. ;...............................;
  1196. LPSCT:    DS    1        ; Lines per screen counter
  1197. NFILES:    DS    2        ; #of files in the ZIP to list
  1198. NLEN:    DS    2        ;
  1199. NPTR:    DS    2        ;
  1200. DTAPTR:    DS    2        ;
  1201. OLDSTK:    DS    2        ; Save system stack here
  1202.     DS    80H        ; Stack area for program's use
  1203. ;
  1204. STACK    EQU    $        ; TOS
  1205. ;
  1206. NXTPG    EQU    ($+00FFH) AND (0FF00H)
  1207. ;
  1208. ;
  1209.     ORG    NXTPG
  1210. ;
  1211. ;
  1212. PAGE:    DS    100H
  1213. ;
  1214. NAMBUF    EQU    $
  1215. ;
  1216.     END
  1217.