home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / jsage / znode3 / uploads / zipdir13.lbr / ZD.ZZ0 / ZD.Z80
Encoding:
Text File  |  1992-04-29  |  37.0 KB  |  1,387 lines

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