home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / BBS_UTIL / BM0406_A.ZIP / BMASM.ZIP / QBARCV6.ASM < prev    next >
Assembly Source File  |  1992-08-01  |  46KB  |  1,721 lines

  1.     page    74,132
  2.     title    ARCV - Verbose ARC directory listing
  3. ;
  4. ; Changes made by Scott McNay (1:395/11) July 26, 1992, to allow routine to be
  5. ; used with code compiled with BC's /Fs option.  (Most) changes marked with
  6. ; ;BCFS0726.  May have optimized some code also.  This is a plug-in replacement
  7. ; for the original code.
  8. ;
  9.  
  10. ;BCFS0801: Standardized code format.  Made sure that DI, SI, BP, and DS are
  11. ;  saved to meet requirements of BC 7.x.
  12.  
  13. ;    Special version of ARCV to be called by QB program
  14. ; usage:
  15. ;
  16. ;    CALL ARCV (Workname$,"filename[.PAK]", RETCD%)        ' CPC151AC
  17. ;
  18. ; notes:
  19. ;    This code originated from ARCV 1.15d - Verbose ARC directory display
  20. ;    written by V.Buerg and was modified to run as a called routine under
  21. ;    Microsoft QuickBasic. It was further modified to allow PAK files by
  22. ;    Robert J. Simoneau.
  23. ;
  24. ;    Change 9/14/86 to dis-allow wildcards
  25. ;    Change 1/1/87 to recognize squash format
  26. ;    Change 2/18/87 to support network usage - - - - Jon Martin   ' CPC151A
  27. ;    Change 1/7/89 to support Pak files -------------Bob Simoneau
  28.  
  29. ;    Change 890320 to support ZIP files    David Kirschbaum, Toad Hall
  30. ;    - Question:  Why do we "have to look for the damned thing" when it
  31. ;    comes to finding ARC/PAK headers?  All comments are at file ends,
  32. ;    so the header should be EXACTLY where it should be .. at the end of
  33. ;    the file's compressed code.  Hacked severely to reflect this,
  34. ;    and vastly cleaning up the code.
  35. ;    - Replaced old SDIR Binary to Ascii conversion with a hacked version
  36. ;    from JMODEM .. about 10 times faster, plus offers integer conversion
  37. ;    as well as long integers.
  38. ;v1.3    - FAAR RBBS reports this sucker runs once and then just returns
  39. ;    a usage message (in the output file).
  40. ;    Trying to find out why.  Found it .. dumb mistake, not clearing
  41. ;    variables between runs.
  42. ;    - Adding true EOF testing for file pointer bumps.
  43. ;    ZIP files have a good way to find EOF (e.g., the central directory),
  44. ;    but PAK and ARC files don't.
  45. ;    - Added some more error msgs.
  46. ;    - Tightened hex output (CvH).
  47. ;    - Reduced buffer sizes to minimum (archdr and inbuf).
  48. ;
  49. ;v1.4    - Adding the new Japanese .LHZ capability.    Toad Hall
  50. ;    See LHARC10E.ZIP (available on GEnie and BBS's) for details.
  51. ;    - Neatening up total line.
  52. ;    - Found some bugs in trying to predetermine ARC/PAK EOF.
  53. ;    Fixed (hopefully).
  54. ;    - Added a bunch of [bx] references .. saved 100 bytes!
  55. ;    - Credits for LHARC (.LHZ) file header structure to:
  56. ;        Daniel Durbin
  57. ;        SysOp: Cygnus X-1 BBS        | CIS: 73447,1744
  58. ;        (805) 541-8505 (data)        | GEnie: D.DURBIN
  59. ;        EL major at PolySlo        | ddurbin@polyslo.CalPoly.EDU
  60. ;    from his LVIEW.C code.
  61. ;
  62. ;Fix    - Correct bug that kept version 1.4 from functioning when linked
  63. ;08/23/89 with RBBS-PC that had been compiled using QB4.5 compiler.
  64. ;      As it turned out it was an out and out bug that just did not
  65. ;      happen to crash when RBBS-PC was compiled using QB3.0.
  66. ;
  67. ;      Jon Martin AIRCOMM (415) 689-2090
  68. ;
  69. ;Fix    - Correct bug that did not support Implode as valid ZIP compression
  70. ;09/02/89 type.
  71. ;
  72. ;      Jon Martin AIRCOMM (415) 689-2090
  73. ;
  74.  
  75.       Extrn  StringAddress:far                          ;BCFS0726
  76.  
  77. STDOUT    equ    1            ;Standard Output        v1.3
  78. STDERR    equ    2            ;Std Error (console)        v1.3
  79. FALSE    equ    0
  80. TRUE    equ    NOT FALSE
  81. DEBUG    equ    FALSE
  82.  
  83. Print    macro    name            ; display a field
  84.     mov    dx,offset name
  85.     call    PrintS
  86.     endm
  87.  
  88. header    struc                ; archive header
  89. aMbrflag    db    1AH        ;unique ARC/PAK flag        v1.3
  90. aCmpMeth    db    0        ;  compression code
  91. aMbrName    db    13 dup (0)    ;  file name
  92. aCmpSiz        dw    0,0        ;  file size in archive
  93. aModDate    dw    0        ;  creation date
  94. aModTime    dw    0        ;  creation time
  95. aCrc16        dw    0        ;  cyclic redundancy check
  96. aUncmpSiz    dw    0,0        ;  true file size, bytes
  97. header    ends
  98.  
  99. ARCHDRLEN    equ    29        ;size of ARC/PAK header.    v1.3
  100.  
  101. ;v1.3    ZIP Local file header structure:
  102.  
  103. zLocalEntry    STRUC
  104.  
  105. zdig0    db    50H,4BH,03H,04H    ;local file header signature    4 bytes
  106.                 ;(0x04034b50)
  107. zVerMade    dw    ?    ;version needed to extract    2 bytes
  108. zBitflag    dw    ?    ;general purpose bit flag    2 bytes
  109. zCmpMeth    dw    ?    ;compression method        2 bytes
  110. zModTime    dw    ?    ;last mod file time         2 bytes
  111. zModDate    dw    ?    ;last mod file date        2 bytes
  112. zCrc32        dw    ?,?    ;crc-32               4 bytes
  113. zCmpSiz        dw    ?,?    ;compressed size        4 bytes
  114. zUncmpSiz    dw    ?,?    ;uncompressed size        4 bytes
  115. zNameLen    dw    ?    ;filename length        2 bytes
  116. zExtraLen    dw    ?    ;extra field length        2 bytes
  117. zMbrName    db    ?    ;filename (variable size)
  118.                 ;extra field (variable size)
  119. ZLocalEntry    ENDS
  120.  
  121. ZIPHDRLEN    equ    30        ;length of initial ZIP hdr read    v1.3
  122.  
  123. ;v1.4    LZH header structure
  124.  
  125. lzhlfh    STRUC            ;Local file header
  126. lUnk1        db    ?,?    ;char unknown1[2];    ;?
  127. lCmpMeth    db    5 dup(?) ;char method[5];    ;compression method
  128. lCmpSiz        dw    ?,?    ;long csize;    ;compressed size
  129. lUncmpSiz    dw    ?,?    ;long fsize;    ;uncompressed size
  130. lModTime    dw    ?    ;int ftime;    ;last mod file time
  131. lModDate    dw    ?    ;int fdate;    ;last mod file date
  132. lFAttr        db    ?    ;char fattr;    ;file attributes
  133. lUnk2        db    ?    ;char unknown2;    ;?
  134. lNameLen    db    ?    ;char namelen;    ;filename length
  135. lMbrName    db    ?    ;char *fname;    ;filename
  136. ;lCrc16        dw    ?    ;int crc;    ;crc-16
  137. lzhlfh    ENDS
  138.  
  139. LZHHDRLEN    equ    22    ;not including lMbrName or lCrc16
  140.  
  141.  
  142. CSEG    segment    public para 'CODE'
  143.     assume    CS:CSEG,DS:CSEG,ES:CSEG
  144.  
  145.     public    ArcV
  146.  
  147. ArcV    proc    far
  148.     push    bp            ; save BASIC reg
  149.     mov    bp,sp            ; get parameter list pointer
  150.     mov    CS:stkptr,sp        ; save stack ptr
  151.     mov    CS:saveds,DS        ; save QB seg reg
  152.     mov    CS:savees,ES        ; save QB seg reg
  153.     mov    CS:savedi,DI                              ;BCFS0801
  154.     mov    CS:savesi,SI                              ;BCFS0801
  155.     call    Start            ; do our thing            v1.3
  156.  
  157. ;    set DOS error level and exit
  158. ;v1.3a    We aren't relying on the CF flag anymore to indicate errors.
  159. ;    Instead, check AL.
  160. ;    0 = success
  161. ;    1 = command line parm error
  162. ;    2..6 are file-related (not found, etc.)
  163. ;    11 = Invalid format (probably didn't find a member header)
  164. ;    13 = invalid data (probably a bad file header structure)
  165. ;    18 = Unexpected EOF ('no further files to be found')
  166.  
  167. Exit:    mov    sp,stkptr        ; restore entry stack value
  168.  
  169.     push    ax            ;save error value        v1.3
  170.  
  171. ;v1.3    Numerous errors could be returned
  172.  
  173.     or    al,al            ;no errors?
  174.     jz    Exit_NoErr        ;yep, ok
  175.  
  176.     mov    bx,offset errtbl    ;assume unknown error
  177.     mov    di,bx            ;various error values
  178.     mov    cx,ERRTBLLEN        ;table length
  179.     repne    scasb            ;find the offset
  180.     jnz    Err_TblDone        ;unknown, BX has table start
  181.  
  182.     dec    di            ;back up to actual error
  183.     sub    di,bx            ;current psn - start = relative nr
  184.     mov    bx,di            ;into BX for msg offset
  185.  
  186. Err_TblDone:
  187.     shl    bx,1            ;*2 for words
  188. Err_Unk:
  189.     add    bx,offset errmsgtbl    ;table of addresses
  190.     mov    dx,[bx]            ;ptr to string
  191.     call    PrintS            ;output error msg
  192.  
  193. Exit_NoErr:
  194.  
  195.     mov    bx,word ptr outhdl    ; close listing file
  196.     cmp    bl,STDERR        ;never opened or STDERR?    v1.3
  197.     jna    Exit1            ;not a real handle        v1.3
  198.     mov    ah,3eh            ;close file handle
  199.     int    21h
  200. Exit1:
  201.     mov    bx,word ptr archdl    ;close ARC/PAK/ZIP file        v1.3
  202.     or    bx,bx            ; if it was opened        v1.3
  203.     jz    Exit2            ; nope                v1.3
  204.     mov    ah,3EH            ;close file handle        v1.3
  205.     int    21H            ;                v1.3
  206. Exit2:                    ;                v1.3
  207.  
  208. ;v1.3    Adding a test to insure we switched DTAs
  209. ;    (so we don't blow away the caller's DTA with a vector 0:0!)
  210.  
  211.     lds    dx,dword ptr savedta    ;get orig DTA vector
  212.     or    dx,dx            ;did we ever get it?
  213.     jz    Exit_NoDTA        ;nope
  214.     mov    ax,DS            ;check out seg
  215.     or    ax,ax
  216.     jz    Exit_NoDTA        ;nope
  217.     mov    ah,1ah            ;set DTA
  218.     int    21h
  219. Exit_NoDTA:
  220.  
  221.     les    ax,dword ptr CS:saveds    ;recover calling seg regs    08/23/89
  222.                     ;(low word is orig DS)    08/23/89
  223.     mov    ds,ax            ;            08/23/89
  224.     mov    di,CS:savedi                              ;BCFS0801
  225.     mov    si,CS:savesi                              ;BCFS0801
  226.     ASSUME    DS:NOTHING,ES:NOTHING    ;a reminder
  227.  
  228.     pop    ax            ;restore error level        v1.3
  229.     xor    ah,ah            ;insure msb clear        v1.3a
  230.  
  231.     mov    bp,sp            ; parm ptr from entry
  232.     mov    6[bp],ax        ;return retcd variable        v1.3
  233.     pop    bp
  234.     ret    6            ; clear parms from stack    ' CPC151A
  235.  
  236.     subttl    '--- constants, equates and work areas'
  237.     page
  238.  
  239. CR    equ    13
  240. LF    equ    10
  241. BEL    equ    7
  242. TAB    equ    9
  243.  
  244. STOPPER equ    0            ; end of display line indicator
  245. ARCMARK equ    26            ; special archive marker
  246. ARCVER  equ    10            ; highest compression code used
  247.  
  248.     even                ;v1.3a
  249.  
  250. stkptr  dw    0            ; stack pointer upon entry
  251.  
  252. arctitl db    CR,LF,'Archive:  '    ;keep this even            v1.3a
  253. saveds  dw    0            ; QB seg reg
  254. savees  dw    0            ; QB seg reg
  255. savedi    dw    0                                  ;BCFS0801
  256. savesi    dw    0                                  ;BCFS0801
  257.  
  258.     subttl    '--- i/o control variables'
  259.     page
  260.  
  261. INBUFSZ    equ    128    ;512        ; size of input buffer        v1.3
  262.  
  263. ;v1.3    Completely reordered these runtime variables
  264. ;    so we can purge them with one fell swoop
  265.  
  266. PURGESTART    equ    $        ;                v1.3
  267.  
  268. totsf    dw    0,0            ; average stowage factor
  269. totlen  dw    0,0            ; total of file lengths
  270. totsize dw    0,0            ; total of file sizes
  271. totmbrs dw    0            ; total number of files
  272.  
  273. archdl  dw    0            ; file handle
  274. fileptr dw    0            ; ptr to filename part of arcname
  275. arclen    dw    0            ;full archive filename length    v1.3
  276. arcname db    76 dup (0)
  277.  
  278. outhdl  dw    0            ; handle for output listing    v1.3
  279. templen    dw    0            ;output filename length        v1.3
  280. temp    db    76 dup (0)        ; and temporary file name
  281.  
  282. filelen    dw    0,0            ;absolute archive file length    v1.3a
  283. curpsn    dw    0,0            ;remember current file ptr pos v1.3a
  284.  
  285. savedta dw    0,0            ; addr of QB dta
  286. dta    db    48 dup (0)        ; data transfer area
  287.  
  288.     even                ;                v1.3
  289.  
  290. PURGELEN    EQU    ($ - PURGESTART) SHR 1    ;amount to purge each run v1.3
  291.  
  292. ;    display lines for verbose
  293.  
  294. vhdr    db    CR,LF
  295.     db    CR,LF,'Name          Length    Stowage    SF   Size now  Date       Time    CRC '
  296.     db    CR,LF,'============  ========  ========  ====  ========  =========  ======  ===='
  297.     db    CR,LF            ;v1.4
  298.     db    STOPPER
  299.  
  300. ;vline    db    CR,LF
  301. vline    label    byte            ;v1.4
  302. vname    db    14 dup (' ')
  303. vlength db    '      '        ; length in archive        v1.3
  304. vstyle  db    '      '        ; compression method
  305. vfactor db    ' xx%  '        ; compression factor
  306. vsize    db    10 dup (' ')        ; actual file bytes
  307. vdate    db    'dd '            ; creation date
  308.  vmonth db    'mmm '
  309.  vyear  db    'yy  '
  310.  vtime  db    'hh:mm   '        ; creation time
  311.  vcrc    db    'xxxx'            ; crc in hex
  312.     db    CR,LF            ;v1.4
  313.     db    STOPPER
  314.  
  315. hundred    dw    100            ; for computing percentages
  316.  
  317. ;    final totals line
  318.  
  319. vthdr    db '------    --- --------        ----  --------',CR,LF    ;v1.4
  320.     db    '*Total    '                        ;v1.4
  321. vtmbrs    db    '    '
  322. vtlen    db    8 dup (' '),'  '
  323.     db    10 dup (' ')
  324. vtsf    db    '   %  '
  325. vtsize    db    8 dup (' ')
  326.     db    CR,LF            ; for tom
  327.     db    STOPPER
  328.  
  329. sign    db    ' '
  330.  
  331. styles  db    '*  -----'    ; 1 = old, no compression (obsolete)
  332.     db    '   -----'    ; 2 = new, no compression
  333.     db    '    Pack'    ; 3 = dle for repeat chars
  334.     db    ' Squeeze'    ; 4 = huffman encoding after dle
  335.     db    '* crunch'    ; 5 = 12-bit lzw (obsolete)
  336.     db    '  crunch'    ; 6 = 12-bit lzw after dle
  337.     db    '* Crunch'    ; 7 = same as above, faster hash (accidental)
  338.     db    '  Crunch'    ; 8 = 9-12-bit lzw with reset after dle
  339.     db    '  Squash'    ; 9 = 9-13-bit lz with reset (PKARC)
  340.     db    '   Crush'    ;10 = Pak 1.0 file ---------Bob Simoneau
  341.     db    ' Distill'    ;11 = Pak 2.51                      ;BCFS0801
  342. ;Check out the type number on the next one.                      ;BCFS0801
  343. ;    db    '  Subdir'    ;30 = ARC 6.x, compressed & orig sizes are N/A;BCFS0801
  344.     ; The SubDir type has no data, in spite of what the sizes say.          ;BCFS0801
  345. ;    db    ' unknown'    ;31 = ARC 6.x, dunno what this is.          ;BCFS0801
  346.  
  347. ;v1.3    ZIP compression types:
  348.  
  349. zstyles    label    byte
  350.     db    '   -----'    ;0 - The file is stored (no compression)
  351.     db    '  Shrink'    ;1 - The file is Shrunk
  352.     db    ' Reduce1'    ;2 - Reduced with compression factor 1
  353.     db    ' Reduce2'    ;3 - Reduced with compression factor 2
  354.     db    ' Reduce3'    ;4 - Reduced with compression factor 3
  355.     db    ' Reduce4'    ;5 - Reduced with compression factor 4
  356.     db    ' Implode'    ;6 - PKZip 1.x                    v1.6
  357.     db    '*  Token'    ;7 - Token format, need 3rd party archiver    ;BCFS0801
  358.     db    ' Deflate'    ;8 - PKZip 2.x                      ;BCFS0801
  359.  
  360. ;v1.4    LZH compression types are already coded as 5 chars of text
  361. ;    in the compressed file.
  362. ;    All we need to do is pad them out to the correct width.
  363.  
  364. months  db    'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
  365.  
  366. ARCPAK    =    0            ;                v1.3
  367. ZIP    =    1            ;                v1.4
  368. LZH    =    2            ;                v1.4
  369. ftype    db    ZIP            ;flag which type file        v1.3
  370.  
  371. ;v1.4    4 types of archive file
  372.  
  373. ziptype    db    'ZIP'
  374. arctype    db    'ARC'
  375. paktype    db    'PAK'
  376. lzhtype    db    'LZH'            ;v1.4
  377. larctype db    'LZS'            ;v1.4 not enabled for now
  378.  
  379. ;zfilesig db    50H,4BH,03H,04H        ;local file header signature    v1.3
  380. ;zdirsig db    50H,4BH,01H,02H        ;central file header signature    v1.3
  381.  
  382. ZSIG    equ    4B50H            ;unique ZIP signature        v1.4
  383. ZFILESIG equ    0403H            ;file member signature        v1.4
  384. ZDIRSIG    equ    0201H            ;central file header signature    v1.4
  385.  
  386. ;v1.3    Centralizing errors at the exit point
  387.  
  388. ;    1 = command line parm error
  389. ;    2..6 are file-related (not found, etc.)
  390. ;    11 = Invalid format (probably didn't find a member header)
  391. ;    12 = Invalid file type (not an ARC, PAK, ZIP)
  392. ;    13 = invalid data (probably a bad file header structure)
  393. ;    18 = Unexpected EOF ('no further files to be found')
  394.  
  395. errtbl db    0,1,2,3,4,5,6,11,12,13,18,25,27,29,30            ;v1.3a
  396. ERRTBLLEN    equ    $ - errtbl
  397.  
  398. errmsgtbl dw    msg0,msg1,msg2,msg3                    ;v1.3a
  399.     dw    msg4,msg5,msg6,msg11
  400.     dw    msg12,msg13,msg18,msg25
  401.     dw    msg27,msg29,msg30
  402.  
  403. msg0    db    'Unknown error',0
  404.  
  405. msg1    db    'Invalid function number',0
  406. msg2    db    'Archive file not found',0
  407. msg3    db    'Path not found',0
  408. msg4    db    'No handle available',0
  409. msg5    db    'Access denied',0
  410. msg6    db    'Invalid handle',0
  411. msg11    db    'Archive header error',0
  412. msg12    db    'Invalid file type',0
  413. msg13    db    'Archive format error',0
  414. msg18    db    'No further files to be found',0
  415. msg25    db    'Disk seek error',0
  416. msg27    db    'Disk sector not found',0
  417. msg29    db    'Write error',0
  418. msg30    db    'Read error',0
  419.  
  420.  
  421.     subttl    '--- mainline processing'
  422.     page
  423. ;
  424. Start    proc    near            ;                v1.3
  425.  
  426.     mov    ax,CS            ;just set ES for now        v1.3
  427.     mov    ES,ax
  428.     ASSUME    DS:NOTHING,ES:CSEG    ;a reminder            v1.3a
  429.  
  430. ;v1.3    Insure all variables are cleared
  431.     cld
  432.     mov    di,offset PURGESTART
  433.     xor    ax,ax            ;clear all the variables    v1.3
  434.     mov    cx,PURGELEN        ;nr words to clear        v1.3
  435.     rep    stosw            ;                v1.3
  436.  
  437. ;v1.3    Move first parameter (output filename) into code space
  438.  
  439.     push    es                                  ;BCFS0726
  440.     push    [bp+10]                                  ;BCFS0726
  441.     call    StringAddress                              ;BCFS0726
  442.     pop    es                                  ;BCFS0726
  443.     jcxz    Copy_Parm2        ;empty, forget it        v1.3
  444.     mov    si,ax                                  ;BCFS0726
  445.     mov    ax,cx
  446.     mov    di,offset templen    ;str length            v1.3
  447.     stosw                ;save length            v1.3
  448.     mov    ds,dx                                  ;BCFS0726
  449.  
  450.     rep    movsb            ;copy in the string        v1.3
  451.  
  452. Copy_Parm2:
  453.  
  454. ;v1.3    Now copy 2d parameter (target archive filename)
  455.  
  456.     push    es                                  ;BCFS0726
  457.     push    [bp+8]                                  ;BCFS0726
  458.     call    StringAddress                              ;BCFS0726
  459.     pop    es                                  ;BCFS0726
  460.     jcxz    Parm2_Done        ;empty, forget it        v1.3
  461.     mov    si,ax                                  ;BCFS0726
  462.     mov    ax,cx                                  ;BCFS0726
  463.     mov    di,offset arclen    ;archive name length        v1.3
  464.     stosw                ;save length            v1.3
  465.     mov    ds,dx                                  ;BCFS0726
  466.  
  467.     mov    ah,'a'            ;constant for uppercasing    v1.3
  468. Parm2_Upper:                ;                v1.3
  469.     lodsb                ;snarf char            v1.3
  470.     cmp    al,ah            ;need uppercasing?        v1.3
  471.     jb    Parm2_NoU        ;nope                v1.3
  472.     sub    al,20H            ;uppercase it            v1.3
  473. Parm2_NoU:                ;                v1.3
  474.     stosb                ;                v1.3
  475.     loop    Parm2_Upper        ;                v1.3
  476.  
  477. Parm2_Done:
  478.  
  479. ;v1.3    All done with DS
  480.  
  481.     mov    ax,CS            ;                v1.3
  482.     mov    DS,ax            ;                v1.3
  483.     ASSUME    DS:CSEG,ES:CSEG        ;a reminder            v1.3a
  484.  
  485.     mov    ax,STDERR        ;assume no output filename    v1.3a
  486.     cmp    temp,0            ;any output filename?        v1.3
  487.     jz    Temp_Opened        ;nope, use STDERR        v1.3a
  488.  
  489. ;v1.3    Forcing output file to STDERR for debugging.
  490. ;v1.3    mov    al,1            ; will show usage        v1.3
  491. ;v1.3    ret                ;back to Exit            v1.3
  492.  
  493. ;v1.3a    mov    ax,STDERR        ;force to STDERR        v1.3
  494. ;v1.3a    jmp    short Temp_Opened    ;continue            v1.3
  495.  
  496. ;Got_Temp:
  497.     mov    dx,offset temp        ; open temporary file for output
  498.     xor    cx,cx            ;no special attributes        v1.3
  499.     mov    ah,3ch            ;create file
  500.     int    21h
  501.     jnb    Temp_Opened        ;fine                v1.3
  502.     ret                ;back to Exit, AL=error code    v1.3
  503.                     ;CF set                v1.3a
  504. Temp_Opened:
  505.     mov    outhdl,ax        ;save handle
  506.  
  507. ;v1.3    Parse the target archive name
  508. ;    Separate path from name
  509. ;    Insure it's an ARC, PAK or ZIP type.
  510.  
  511.     mov    di,offset arclen    ;archive name length        v1.3
  512.     mov    ax,[di]            ;snarf length            v1.3a
  513.     inc    di            ;bump to name proper        v1.3a
  514.     inc    di            ;                v1.3a
  515.     mov    cx,ax            ;into CX for scans to come    v1.3a
  516.     jcxz    No_ArcName        ;no length, ergo no name    v1.3a
  517.  
  518.     mov    dx,ax            ;save in DX for later        v1.3
  519.     xor    al,al            ;will scan for AsciiZ terminator v1.3
  520.     cmp    [di],al            ;no name at all?        v1.3
  521.     jnz    Got_ArcName        ;yep                v1.3
  522.  
  523. No_ArcName:
  524.     mov    al,2            ;'Archive file not found'    v1.3
  525.     ret                ;back to Exit            v1.3
  526.  
  527. Got_ArcName:
  528.  
  529. ;v1.3    We have some sort of target name.
  530. ;    But is it a legal type?
  531. ;    DX = filename length
  532. ;    DI -> archive filename (arcname)
  533.  
  534.     add    di,dx            ;+ length -> last char+1    v1.3
  535.     dec    di            ;back up to last char        v1.3
  536.     mov    bx,di            ;BX -> last char        v1.3
  537.  
  538.     mov    al,'\'            ;look for normal path delimiter    v1.3
  539.     mov    cx,dx            ;length for scan        v1.3
  540.     std                ;backwards scanning now        v1.3
  541.     repne    scasb            ;                v1.3
  542.     jz    Got_Start        ;found one            v1.3
  543.  
  544. ;Ugh .. tired of typing in v1.3's!
  545.  
  546.     mov    di,bx            ;back to end
  547.     mov    cx,dx            ;restore length
  548.     mov    al,'/'            ;funny path delimiter
  549.     repne    scasb
  550.     jz    Got_Start        ;found one
  551.  
  552.     mov    di,bx            ;back to end .. sigh ..
  553.     mov    cx,dx            ;restore length
  554.     mov    al,':'            ;ok, how about a drive?
  555.     repne    scasb
  556.     jnz    No_Paths        ;nope, DI -> name start
  557.  
  558. Got_Start:
  559.     inc    di            ;bump up to the separator
  560. No_Paths:
  561.     inc    di            ;bump to the first name char
  562.     cld                ;forward again
  563.     mov    fileptr,di        ;remember real filename start
  564.  
  565. ;v1.4    You MUST specify the type .. .ARC, .PAK, .ZIP, or .LZH.
  566. ;    If .ARC or .PAK, we'll use the old code to display ARC-type
  567. ;    files.
  568. ;v1.4    Else if ZIP or LZH, it's a totally new format!
  569. ;    We remember the type archiving format in 'ftype'.
  570.  
  571. ;v1.3    DS:SI -> filename's first char.
  572.  
  573.     mov    al,'.'            ;find the separator        v1.3
  574.     mov    cx,word ptr 12        ;max of 12 chars        v1.3
  575.     repne    scasb            ;find it            v1.3
  576.     jnz    BadType            ;forget it            v1.3
  577.  
  578.     mov    dx,di            ;save pointer to file type    v1.3
  579.                     ;(just past the separator)    v1.3
  580.     mov    ax,3            ;3 chars constant
  581.  
  582.     mov    ftype,ZIP        ;assume ZIP
  583.  
  584.     mov    si,offset ziptype    ;is it a ZIP?
  585.     mov    di,dx            ;back to filename type
  586.     mov    cx,ax            ;3 chars
  587.     repz    cmpsb            ;compare
  588.     jz    Got_Type        ;a match
  589.  
  590.     mov    ftype,ARCPAK        ;ok, assume ARC or PAK        v1.3a
  591.  
  592.     mov    si,offset arctype    ;is it an ARC?            v1.3
  593.     mov    di,dx            ;back to filename type
  594.     mov    cx,ax            ;3 chars
  595.     repz    cmpsb            ;compare
  596.     jz    Got_Type        ;a match
  597.  
  598.     mov    si,offset paktype    ;is it a PAK?
  599.     mov    di,dx            ;back to filename type
  600.     mov    cx,ax            ;3 chars
  601.     repz    cmpsb            ;compare
  602.     jz    Got_Type        ;a match
  603.  
  604. ;v1.4    Adding .LZH types
  605.     mov    ftype,LZH        ;ok, assume .LZH file        v1.4
  606.  
  607.     mov    si,offset lzhtype    ;is it an LZH?
  608.     mov    di,dx            ;back to filename type
  609.     mov    cx,ax            ;3 chars
  610.     repz    cmpsb            ;compare
  611.     jz    Got_Type        ;a match
  612.  
  613. BadType:
  614.     mov    al,12            ;'Invalid file type'        v1.3a
  615.     ret                ;back to Exit            v1.3
  616.  
  617. Got_Type:                ;v1.3
  618.  
  619. ;    find first matching file
  620.  
  621.     push    ES
  622.     mov    ah,2fh            ; get current dta ptr
  623.     int    21h            ; returned in ES:bx
  624.     mov    savedta,ES
  625.     mov    savedta[2],bx
  626.     pop    ES
  627.  
  628.     mov    dx,offset dta        ; set local dta for murkers
  629.     mov    ah,1ah
  630.     int    21h
  631.  
  632.     call    OpenArc            ; see if archive exists
  633. ;    jb    ArcV_X            ;nope, return, AL = error    v1.3
  634.     jnb    ArcV1            ;ok
  635.     jmp    ArcV_X            ;nope, return, AL=error        v1.4
  636.  
  637. ;v1.3a    Display archive filename, header,
  638. ;    then into a loop for each archive member.
  639.  
  640. ArcV1:    mov    dx,fileptr        ;pointer to filename        v1.3a
  641.     call    PrintS            ;display, CR/LF            v1.3a
  642.     jb    ArcV_X            ;output failed            v1.3a
  643.  
  644.     Print    vhdr
  645.     jb    ArcV_X            ;output failed, AL = error    v1.3
  646.  
  647. ArcVNext:
  648. IF    DEBUG
  649.     Print    debug1
  650.     jmp    short debugj1
  651. debug1    db    'Calling GetHdr',CR,LF,0
  652. debugj1:
  653. ENDIF
  654.     call    GetHdr            ; load next header
  655.     jb    ArcV_NoHdr        ;failed somehow, AL=error    v1.3a
  656.                     ;(could be EOF, which is ok)    v1.3a
  657. IF    DEBUG
  658.     Print    debug2
  659.     jmp    short debugj2
  660. debug2    db    'Calling ArcVgo',CR,LF,0
  661. debugj2:
  662. ENDIF
  663.     call    ArcVgo            ;format, write out file report
  664.     jb    Arcv_NoHdr        ;something failed, AL=error    v1.3a
  665.  
  666. IF    DEBUG
  667.     Print    debug3
  668.     jmp    short debugj3
  669. debug3    db    'Calling Bump_ArcPtrs',CR,LF,0
  670. debugj3:
  671. ENDIF
  672.     call    Bump_ArcPtrs        ;bump to next archive file    v1.3
  673.     jnb    ArcVNext        ;loop if ok, else AL=error    v1.3a
  674.                     ;(could be EOF)            v1.3a
  675.  
  676. ArcV_NoHdr:
  677.     cmp    archdr.aCmpMeth,0    ; archive eof?
  678.     jnz    ArcV_X            ;nope, something else happened    v1.3
  679.  
  680.     cmp    totmbrs,0        ;any totals?            v1.3
  681.     jz    ArcV_X            ;nope                v1.3
  682.     push    ax            ;save previous error value    v1.3
  683.     call    Format_Totals        ;yep, format and output        v1.3
  684.     pop    ax            ;restore prev err value        v1.3
  685.  
  686. ArcV_X:    ret                ;AL=error            v1.3a
  687.  
  688. Start    endp                ;                v1.3
  689.  
  690.  
  691. ;v1.3    Format, display single line for each member
  692. ;    On success, return:
  693. ;    CF clear
  694. ;    AL = 0
  695. ;    On error, return:
  696. ;    CF set (because of output write fail)
  697. ;    AL = error code
  698.  
  699. ArcVgo    proc    near
  700.     mov    di,offset vname        ; copy file name
  701.     mov    si,offset archdr.aMbrName
  702.     mov    cx,word ptr 13        ;up to 12 chars long, AsciiZ 0
  703. ArcV3:
  704.     lodsb
  705.     or    al,al            ; end of name?            v1.3
  706.     je    ArcV4
  707.     stosb
  708.     loop    ArcV3
  709.     jmp    short ArcV5
  710.  
  711. ArcV4:
  712.     mov    al,' '            ; pad with blanks
  713.     rep    stosb
  714. ArcV5:
  715. ; reduce the size/length to word values
  716.  
  717.     mov    bx,offset archdr.aCmpSiz    ;-> compressed size    v1.4
  718.     mov    cx,[bx]            ;.lo                v1.4
  719.     mov    dx,2[bx]        ;.hi                v1.4
  720.     mov    bx,offset archdr.aUncmpSiz    ;-> uncompressed size    v1.4
  721.     mov    ax,2[bx]        ;.hi                v1.4
  722.     mov    bx,[bx]            ;.lo                v1.4
  723.  
  724. ArcV51: or    ax,ax            ; big number?
  725.     jz    ArcV52            ; nope, can use it
  726.     shr    ax,1            ; yup, divide by two
  727.     rcr    bx,1
  728.     shr    dx,1
  729.     rcr    cx,1
  730.     jmp    short ArcV51
  731.  
  732. ArcV52:
  733.     mov    ax,bx            ; low word of actual size
  734.     mov    sign,' '
  735.     cmp    ax,cx            ; arc member is larger?
  736.     jb    ArcV520
  737.     sub    ax,cx            ; amount saved
  738.     jmp    short ArcV56
  739.  
  740. ArcV520:
  741.     sub    ax,cx
  742.     neg    ax
  743.     mov    sign,'-'
  744.  
  745. ArcV56:
  746.     mul    hundred            ; to percentage
  747.     add    ax,50
  748.     adc    dx,0            ; round up percent
  749.     or    bx,bx            ; empty file?
  750.     jnz    ArcV53
  751.     mov    ax,100
  752.     jmp    short ArcV54
  753.  
  754. ArcV53: div    bx
  755. ArcV54:
  756.     cmp    ax,100            ; archive fouled?
  757.     jbe    ArcV55
  758.     sub    ax,ax
  759. ArcV55:
  760.     mov    di,offset vfactor-2    ;format stowage factor        v1.3
  761.     call    Asciify            ;display AX
  762.  
  763.     mov    al,sign
  764.     mov    vfactor,al
  765.  
  766.     mov    cx,word ptr 3        ;gonna need it in a sec        v1.4
  767.     cmp    ftype,LZH        ;LZH type? (compression method    v1.4
  768.                     ; is already text)        v1.4
  769.     jnz    ArcV_GetStyles        ;nope                v1.4
  770.  
  771. ;v1.4    The LZH compression method (5 chars) is still in inbuf.
  772.  
  773.     mov    si,offset inbuf.lCmpMeth    ;-> 5-char compression    v1.4
  774.                     ;   method string    v1.4
  775.     mov    di,si
  776.     add    di,5            ;point to beyond chars        v1.4
  777.     mov    ax,'  '            ;need 3 trailing blanks        v1.4
  778.     stosw
  779.     stosb
  780.     mov    di,offset vstyle+1    ;indent to be neat        v1.4
  781.     jmp    short ArcV_GotStyle    ;skip                v1.4
  782.  
  783. ArcV_GetStyles:                ;                v1.4
  784.  
  785.     mov    si,offset zstyles    ;assume ZIP            v1.3
  786.     cmp    ftype,ZIP        ;ZIP file?            v1.3
  787.     jz    ArcV55A            ;yep                v1.3
  788.     mov    si,offset styles    ;ARC or PAK            v1.3
  789. ArcV55A:                ;                v1.3
  790.  
  791.     sub    bx,bx            ; determine style
  792.     mov    bl,archdr.aCmpMeth
  793.     dec    bl            ;adjust for table offset    v1.3
  794. ;v1.4    mov    cl,3            ; eight bytes each entry
  795. ;v1.4    CX = 3 (eight bytes each entry)
  796.     shl    bx,cl            ;*8
  797.  
  798.     add    si,bx            ;point into style table        v1.3
  799.     mov    di,offset vstyle
  800.  
  801. ArcV_GotStyle:                ;                v1.4
  802.     inc    cx            ;CX=4=words to move        v1.4
  803.     rep    movsw            ;                v1.3
  804.  
  805.     mov    bx,offset archdr.aCmpSiz    ;-> compressed size    v1.4
  806.     mov    ax,[bx]            ;.lo                v1.4
  807.     mov    dx,2[bx]        ;.hi                v1.4
  808.     mov    bx,offset totsize    ;-> accumulated compressed size    v1.4
  809.     add    [bx],ax            ;.lo                v1.4
  810.     adc    2[bx],dx        ;.hi                v1.4
  811.  
  812.     mov    di,offset vsize        ;format file size        v1.3
  813.     call    Asciify_Long        ;                v1.3
  814.  
  815.     mov    bx,offset archdr.aUncmpSiz    ;-> uncompressed size    v1.4
  816.     mov    ax,[bx]            ;.lo                v1.4
  817.     mov    dx,2[bx]        ;.hi                v1.4
  818.     mov    bx,offset totlen    ;-> total length accumulator    v1.4
  819.     add    [bx],ax            ;.lo                v1.4
  820.     adc    2[bx],dx        ;.hi                v1.4
  821.  
  822.     mov    di,offset vlength    ;format file length        v1.3
  823.     call    Asciify_Long        ;                v1.3
  824.  
  825.     mov    ax,archdr.aModDate    ; format file date
  826.     call    GetDate
  827.  
  828.     mov    ax,archdr.aModTime    ; format file time
  829.     call    GetTime
  830.  
  831.     mov    ax,archdr.aCrc16    ; format crc in hex
  832.     mov    di,offset vcrc
  833.     call    Cvh
  834.  
  835.     inc    totmbrs            ;NOW bump total count        v1.3a
  836.     Print    vline            ; display this file info
  837.                     ;(may return error)        v1.3a
  838.     ret
  839.  
  840. ArcVgo    endp
  841.  
  842.  
  843.     subttl    '--- load next archive header'
  844.     page
  845.  
  846. ;v1.3    Adding ZIP file searching
  847. ;v1.3a    For ARC/PAK files, now testing to see if we're at the archive
  848. ;    file end.  If so (a proper file), return with EOF (CF set
  849. ;    but AL=0).
  850. ;    Archive files may have picked up some garbage on the end
  851. ;    (from XMODEM xfers, whatever).  We'll see if we at LEAST have
  852. ;    enough data for an archive header.
  853. ;    If not, assume EOF, ignoring garbage.
  854. ;    If there's more than 29 bytes of garbage .. the header will be
  855. ;    garbage and we're gonna report a format error .. but that's ok for now.
  856. ;    Zip files have a definite ending (the central directory,
  857. ;    and they'll look out for their own endings.
  858. ;
  859. ;    Also returning CF and AL per any errors.
  860.  
  861. GetHdr  proc    near
  862.  
  863.     xor    ax,ax            ;handy 0
  864.     mov    archdr.aCmpMeth,al    ;assume archive EOF
  865.  
  866.     cmp    ftype,ZIP        ;doing ZIP files?
  867.     jnz    GH_NotZip        ;nope                v1.4
  868.     jmp    Get_ZipHdr        ;yep, they look out for themselves
  869.  
  870. GH_NotZip:
  871.     cmp    ftype,LZH        ;doing an LZH file?        v1.4
  872.     jnz    GH_ArcPak_Hdr        ;nope                v1.4
  873.     jmp    Get_LZHHdr        ;yep                v1.4
  874.  
  875. GH_ArcPak_Hdr:                ;                v1.4
  876.  
  877. ;v1.3    New code
  878. ;    ARC/PAK headers look like this:
  879. ;aMbrFlag    db    1AH        ;unique header flag
  880. ;aCmpMeth    db    0        ;  compression code
  881. ;aMbrName    db    13 dup (0)    ;  file name
  882. ;aCmpSiz    dw    0,0        ;  file size in archive
  883. ;aModDate    dw    0        ;  creation date
  884. ;aModTime    dw    0        ;  creation time
  885. ;aCrc16        dw    0        ;  cyclic redundancy check
  886. ;aUncmpSiz    dw    0,0        ;  true file size, bytes
  887.  
  888.     mov    dx,offset archdr    ;read into here
  889.     mov    cx,ARCHDRLEN        ;nr bytes to read
  890.     mov    bx,archdl        ;archive file handle
  891.     mov    ah,3FH            ;read from file/device
  892.     int    21H
  893.     jnb    GH_ChkHdr        ;read ok            v1.3a
  894.     ret                ;return CF set, AL=error    v1.3a
  895.  
  896. GH_ChkHdr:
  897.     mov    bx,dx            ;DS:BX -> structure start    v1.3a
  898.  
  899.     cmp    [bx].aMbrFlag,ARCMARK    ;start of header?
  900.     jne    Hdr_InvalFmt        ;'invalid format', exit CF set
  901.  
  902.     mov    al,[bx].aCmpMeth    ;type compression
  903.     cmp    al,ARCVER        ;reasonable code?
  904.     ja    Hdr_InvalFmt        ;nope, funny stuff
  905.  
  906.     or    al,al            ; archive eof?
  907.     je    Hdr_RetCF        ;yep, done, return CF set
  908.                     ;but AL=0 = not a REAL error    v1.3a
  909.     cmp    al,1            ; old format?
  910.     jne    GetHdrX            ; if so, it's short
  911.     mov    si,offset archdr.aCmpSiz            ; CPC15-1C
  912.     mov    di,offset archdr.aUncmpSiz            ; CPC15-1C
  913.     movsw                ;                v1.3
  914.     movsw                ;                v1.3
  915. GetHdrX:
  916.     xor    al,al            ;return AL=0, success        v1.3a
  917.     clc
  918.     ret
  919.  
  920. Hdr_InvalFmt:
  921.     mov    al,0BH            ;'invalid format'
  922. Hdr_EarlyEOF:                ;                ;v1.4
  923.     mov    [bx].aCmpMeth,al    ;signal EOF or invalid format    v1.4
  924. Hdr_RetCF:
  925.     stc                ;return CF set, AL=error
  926.     ret
  927.  
  928. GetHdr    endp
  929.  
  930.  
  931. Get_ZipHdr    proc    near
  932. ;v1.4    GetHdr Subroutine for ZIP files
  933. ;v1.3    Reads in ZIP file entry.
  934. ;    Then scans for the unique file entry signature.
  935. ;    On success:
  936. ;    DS:BX -> file entry directory structure
  937. ;    CF clear
  938. ;    Else CF set for failure
  939.  
  940.     call    Read_Zip_Entry
  941.     jb    Get_ZHdrX        ;failed, AL=ERRORLEVEL
  942.  
  943.     mov    bx,offset inbuf        ;use for field base
  944.     mov    di,offset archdr.aCmpMeth    ;moving into this structure
  945.  
  946. ;v1.4    Remember, the ZIP header we'll be snarfing data from
  947. ;    looks like this:
  948. ;zVerMade    dw    ?    ;version needed to extract    2 bytes
  949. ;zBitflag    dw    ?    ;general purpose bit flag    2 bytes
  950. ;zCmpMeth    dw    ?    ;compression method        2 bytes
  951. ;zModTime    dw    ?    ;last mod file time         2 bytes
  952. ;zModDate    dw    ?    ;last mod file date        2 bytes
  953. ;zCrc32        dw    ?,?    ;crc-32               4 bytes
  954. ;zCmpSiz    dw    ?,?    ;compressed size        4 bytes
  955. ;zUncmpSiz    dw    ?,?    ;uncompressed size        4 bytes
  956. ;zNameLen    dw    ?    ;filename length        2 bytes
  957. ;zExtraLen    dw    ?    ;extra field length        2 bytes
  958. ;zMbrName    db    ?    ;filename (variable size)
  959.                 ;extra field (variable size)
  960. ;
  961. ;    and the ARC/PAK record we'll be formatting to
  962. ;    looks like this:
  963. ;aMbrFlag    db    1AH
  964. ;aCmpMeth    db    0        ;  compression code
  965. ;aMbrName    db    13 dup (0)    ;  file name
  966. ;aCmpSiz    dw    0,0        ;  file size in archive
  967. ;aModDate    dw    0        ;  creation date
  968. ;aModTime    dw    0        ;  creation time
  969. ;aCrc16        dw    0        ;  cyclic redunancy check
  970. ;aUncmpSiz    dw    0,0        ;  true file size, bytes
  971.  
  972.     mov    ax,[bx].zCmpMeth    ;compression method
  973.     inc    al            ;bump to be non-0
  974.     stosb                ;->  aCmpMeth
  975.  
  976. ;For now, assuming a normal file name (no paths)
  977.  
  978.     mov    ax,[bx].zNameLen    ;filename length
  979.     and    ax,15            ;constrain to max 12 chars
  980.     mov    cx,ax            ;into CX for move
  981.     lea    si,[bx].zMbrName    ;pointer to actual filename
  982.     rep    movsb            ;do the move
  983.     xor    al,al            ;terminating 0
  984.     stosb
  985.  
  986.     mov    di,offset archdr.aCmpSiz    ;bump past name
  987.  
  988. ;    mov    ax,[bx].zCmpSiz        ;compressed size.lo
  989. ;    stosw                ; -> aCmpSiz
  990. ;    mov    ax,[bx].zCmpSiz[2]    ;compressed size.hi
  991. ;    stosw                ; -> aCmpSiz[2]
  992.     mov    si,offset inbuf.zCmpSiz    ;-> compressed size
  993.     movsw                ;aCmpSiz.lo
  994.     movsw                ;aCmpSiz.hi
  995.  
  996.     mov    ax,[bx].zModDate    ;last mod date
  997.     stosw                ; -> aModDate
  998.     mov    ax,[bx].zModTime    ;last mod time
  999.     stosw                ; -> aModTime
  1000.     mov    ax,[bx].zCrc32        ;CRC-32 value.lo
  1001.     stosw                ; -> aCrc16
  1002.  
  1003. ;    mov    ax,[bx].zUncmpSiz    ;uncompressed size.lo
  1004. ;    stosw                ; -> aUncmpSiz
  1005. ;    mov    ax,[bx].zUncmpSiz[2]    ;uncompressed size.hi
  1006. ;    stosw                ; -> aUncmpSiz[2]
  1007.     mov    si,offset inbuf.zUncmpSiz    ;-> uncompressed size
  1008.     movsw                ;aUncmpSiz.lo
  1009.     movsw                ;aUncmpSiz.hi
  1010.  
  1011.     xor    ax,ax            ;return AX 0
  1012.     clc                ;return CF clear
  1013. Get_ZHdrX:
  1014.     ret
  1015.  
  1016. Get_ZipHdr    endp        ;GetHdr subroutine
  1017.  
  1018.  
  1019.  
  1020. Get_LZHHdr    proc    near
  1021. ;v1.4    GetHdr Subroutine for LZH headers
  1022. ;    LZH file header has already been read in to inbuf.
  1023. ;
  1024. ;    If all is ok, we move the appropriate LZH fields into the
  1025. ;    standard ARC/PAK structure (archdr) (so far as we can).
  1026. ;
  1027. ;    Gleaning from the LHARCDOC documentation, the 'laCmpMeth' field
  1028. ;    (5 characters) can be:
  1029. ;        '-lh0-'        stored as is (no compression)
  1030. ;        '-lh1-'        compressed by LZHuf coding
  1031. ;    There appear to be at least two more possible compression codes
  1032. ;    that may appear:  "LARC type 4 and type 5" (whatever they may be!).
  1033. ;
  1034. ;    Assuming this field will ALWAYS be text, we are NOT gonna try to
  1035. ;    snarf some magic code number out of the field, but will just
  1036. ;    protect the field (in inbuf) and move the text directly into our
  1037. ;    formatted display line later.
  1038. ;
  1039. ;    The only way we can test this as an LZH header is to look
  1040. ;    for a '-%%%-' starting at the 2d header byte (the laCmpMeth
  1041. ;    field).
  1042. ;
  1043. ;    On success:
  1044. ;    DS:BX -> file entry directory structure
  1045. ;    CF clear
  1046. ;    Else CF set for failure
  1047.  
  1048. ;v1.4    LZH files don't have a decent, clean EOF header.
  1049. ;    We have to test for near-EOF the hard way.
  1050.  
  1051.     mov    di,offset archdr.aMbrFlag    ;moving into this structure
  1052.     mov    ax,001AH        ;fake ARC/PAK flag
  1053.     stosw                ; and EOF compression code
  1054.  
  1055.     xor    ax,ax            ;handy 0
  1056.     mov    bx,offset filelen    ;-> file length
  1057.     mov    dx,[bx]            ;file length.lo
  1058.     mov    cx,2[bx]        ;file length.hi
  1059.  
  1060.     mov    bx,offset curpsn    ;for fast access
  1061.     cmp    cx,2[bx]        ;length.hi = psn.hi?
  1062.     jnz    GL_AddHdr        ;nope
  1063.     cmp    dx,[bx]            ;length.lo = psn.lo?
  1064.     jz    GL_TrueEof        ;yep, we're exactly at EOF
  1065.  
  1066. GL_AddHdr:
  1067.     sub    dx,LZHHDRLEN        ;sub header length
  1068.     sbb    cx,ax    ;0        ;handle the borrow
  1069.     jb    GL_Eof            ;<0, beyond EOF
  1070.     sub    dx,[bx]            ;- file psn.lo
  1071.     sbb    cx,2[bx]        ;- file psn.hi, minus any borrows
  1072.     jnb    GL_NotEof        ;not near end .. ok
  1073.  
  1074. ;There must've been junk on the file end.
  1075. ;However .. there ALWAYS seems to be junk on the end.
  1076. ; So .. we'll return no message at all (AL=0)
  1077. ;If we ever figure out how to detect a TRUE LZH EOF,
  1078. ;we can enable this ERRORLEVEL=18 business.
  1079.  
  1080. GL_Eof:
  1081. ;    mov    al,18            ;'No further files to be found'
  1082. GL_TrueEof:
  1083.     stc                ;CF set for EOF            v1.4
  1084.     ret
  1085.  
  1086. GL_NotEof:
  1087.  
  1088.     push    di            ;save ptr -> archdr.aMbrName
  1089.     call    Read_LZH_Entry
  1090.     pop    di
  1091.     jb    Get_LHdrX        ;failed, AL=ERRORLEVEL
  1092.  
  1093.     mov    bx,offset inbuf        ;use for field base
  1094.  
  1095. ;v1.4    Remember, the LZH header we'll be snarfing data from
  1096. ;    looks like this:
  1097. ;lUnk1        db    ?,?    ;char unknown1[2];    ;?
  1098. ;lCmpMeth    db    5 dup(?) ;char method[5];    ;compression method
  1099. ;lCmpSiz    dw    ?,?    ;long csize;    ;compressed size
  1100. ;lUncmpSiz    dw    ?,?    ;long fsize;    ;uncompressed size
  1101. ;lModTime    dw    ?    ;int ftime;    ;last mod file time
  1102. ;                        ; (msdos format)
  1103. ;lModDate    dw    ?    ;int fdate;    ;last mod file date
  1104. ;lfAttr        db    ?    ;char fattr;    ;file attributes
  1105. ;unknown2    db    ?    ;char unknown2;    ;?
  1106. ;lNameLen    db    ?    ;char namelen;    ;filename length
  1107. ;
  1108. ;lMbrName    db    ?    ;char *fname;    ;filename
  1109. ;;lCrc16    dw    ?    ;int crc;    ;crc-16
  1110. ;
  1111. ;    and the ARC/PAK record we'll be formatting to
  1112. ;    looks like this:
  1113. ;aMbrFlag    db    1AH
  1114. ;aCmpMeth    db    0        ;  compression code
  1115. ;aMbrName    db    13 dup (0)    ;  file name
  1116. ;aCmpSiz    dw    0,0        ;  file size in archive
  1117. ;aModDate    dw    0        ;  creation date
  1118. ;aModTime    dw    0        ;  creation time
  1119. ;aCrc16        dw    0        ;  cyclic redundancy check
  1120. ;aUncmpSiz    dw    0,0        ;  true file size, bytes
  1121.  
  1122.     mov    al,[bx].lNameLen    ;filename length
  1123.     and    ax,15            ;constrain to max 12 chars
  1124.     mov    cx,ax            ;into CX for move
  1125.     mov    si,offset inbuf.lMbrName    ;-> actual filename
  1126.     rep    movsb            ;do the move
  1127.     xor    al,al            ;terminating 0
  1128.     stosb
  1129.  
  1130. ;In LZH headers, the 2-byte CRC16 word lies immediately
  1131. ;after the filename.
  1132. ;Snarf it now and stuff in the ARC header.
  1133.  
  1134.     lodsw                ;lCrc16
  1135.     push    ax            ;save a sec
  1136.  
  1137.     mov    di,offset archdr.aCmpSiz    ;bump past name
  1138.  
  1139. ;    mov    ax,[bx].lCmpSiz        ;compressed size.lo
  1140. ;    stosw                ; -> aCmpSiz
  1141. ;    mov    ax,[bx].lCmpSiz[2]    ;compressed size.hi
  1142. ;    stosw                ; -> aCmpSiz[2]
  1143.     mov    si,offset inbuf.lCmpSiz    ;-> compressed size
  1144.     movsw                ;aCmpSiz.lo
  1145.     movsw                ;aCmpSiz.hi
  1146.  
  1147.     mov    ax,[bx].lModDate    ;last mod date
  1148.     stosw                ; -> aModDate
  1149.     mov    ax,[bx].lModTime    ;last mod time
  1150.     stosw                ; -> aModTime
  1151.     pop    ax            ;CRC-16 value
  1152.     stosw                ; -> aCrc16
  1153. ;    mov    ax,[bx].lUncmpSiz    ;uncompressed size.lo
  1154. ;    stosw                ; -> aUncmpSiz
  1155. ;    mov    ax,[bx].lUncmpSiz[2]    ;uncompressed size.hi
  1156. ;    stosw                ; -> aUncmpSiz[2]
  1157.     mov    si,offset inbuf.lUncmpSiz    ;-> uncompressed size
  1158.     movsw                ;aUncmpSiz.lo
  1159.     movsw                ;aUncmpSiz.hi
  1160.  
  1161.     xor    ax,ax            ;return AX 0
  1162.     clc                ;return CF clear
  1163. Get_LHdrX:
  1164.     ret
  1165.  
  1166. Get_LZHHdr    endp            ;GetHdr Subroutine        v1.4
  1167.  
  1168.  
  1169. Read_LZH_Entry    proc    near        ;GetHdr Subroutine        v1.4
  1170.  
  1171.     mov    dx,offset inbuf        ;read into here
  1172.     mov    cx,LZHHDRLEN        ;entry structure size
  1173.                     ;(does NOT include variable
  1174.                     ; length filename, and the
  1175.                     ;two CRC bytes following the
  1176.                     ;filename)
  1177.     mov    bx,archdl        ;file handle
  1178.     call    ReadZ_It        ;try to read in header
  1179.                     ;(up to filename)
  1180.     jb    ReadL_Eof        ;failed, AL=error
  1181.  
  1182.     mov    si,dx            ;structure start
  1183.     mov    al,'-'            ;test for '-l%-' or whatever
  1184.     cmp    [si].lCmpMeth,al    ;first part of compression
  1185.                     ;method string?
  1186.     jnz    ReadL_InvalDat        ;bogus, failed
  1187.     cmp    [si].lCmpMeth+4,al    ;how about last char?
  1188.     jz    ReadL_Ok1        ;yep, fine
  1189. ReadL_InvalDat:
  1190.     mov    al,0DH            ;force to 'invalid data'
  1191. ReadL_Eof:
  1192.     mov    archdr.aCmpMeth,al    ;set per EOF or error
  1193.     stc                ;return CF set
  1194.     ret
  1195.  
  1196. ReadL_Ok1:
  1197.     mov    dx,offset inbuf.lMbrName    ;-> lMbrName psn
  1198.     mov    cl,inbuf.lNameLen    ;length of member filename
  1199.     xor    ch,ch            ;clear msb
  1200.     call    ReadZ_It        ;read in the name
  1201.     jb    ReadL_Eof        ;failed
  1202.     add    dx,cx            ;bump buff ptr past name
  1203.     mov    cx,2            ;LZH CRC is a word
  1204.     call    ReadZ_It        ;read in the CRC word
  1205.     jb    ReadL_Eof        ;failed
  1206.     ret                ;success
  1207.  
  1208. Read_LZH_Entry    endp            ;GetHdr Subroutine        v1.4
  1209.  
  1210.  
  1211. Read_Zip_Entry    proc    near        ;GetHdr Subroutine
  1212.  
  1213.     mov    dx,offset inbuf        ;read into here
  1214.     mov    cx,ZIPHDRLEN        ;entry structure size
  1215.                     ;(does NOT include filename or
  1216.                     ; Extra fields, which are
  1217.                     ;dynamic)
  1218.     mov    bx,archdl        ;file handle
  1219.     call    ReadZ_It        ;try to read in header
  1220.                     ;(up to filename)
  1221.     jb    ReadZ_Eof        ;failed, AL=error    v1.3a
  1222.  
  1223.     mov    si,dx            ;->file signature    v1.4
  1224.     lodsw                ;snarf first 2 chars    v1.4
  1225.     cmp    ax,ZSIG            ;ZIP header?        v1.4
  1226.     jnz    ReadZ_InvalDat        ;nope, bogus        v1.4
  1227.     lodsw                ;file or central sig    v1.4
  1228.     cmp    ax,ZFILESIG        ;next member?        v1.4
  1229.     jz    ReadZ_Ok1        ;yep, fine        v1.4
  1230.     cmp    ax,ZDIRSIG        ;central directory?    v1.4
  1231.                     ;(means we're done)    v1.4
  1232.     mov    al,0            ;assume yes, EOF    v1.4
  1233.     jz    ReadZ_Eof        ;yep            v1.4
  1234.  
  1235. ReadZ_InvalDat:
  1236.     mov    al,0DH            ;'Invalid data'        v1.4
  1237. ReadZ_Eof:                ;            v1.3a
  1238.     mov    archdr.aCmpMeth,al    ;set per EOF or error    v1.3a
  1239.     stc                ;return CF set        v1.3a
  1240.     ret
  1241.  
  1242. ReadZ_Ok1:
  1243.     mov    dx,offset inbuf.zMbrName    ;move to zFilename psn
  1244.     mov    cx,inbuf.zNameLen    ;length of member filename
  1245.                     ;fall thru to ...    v1.3a
  1246.  
  1247. ;v1.4    Common subroutine for ReadZ and Read_LZH
  1248. ;    DX -> buffer
  1249. ;    CX = bytes to read
  1250. ;    BX MUST have archdl .. so protect BX!
  1251.  
  1252. ReadZ_It:
  1253.     mov    ah,3FH            ;read from file/device
  1254.     int    21H
  1255.     jb    ReadZ_ItX        ;failed, error in AX    v1.3a
  1256.  
  1257. ;v1.4    We'll update our curpsn file pointers later
  1258. ;    when we try to read past compressed file contents.
  1259.  
  1260. ;v1.4    add    curpsn,ax        ;bump current file ptr    v1.3a
  1261.                     ;by amount read        v1.3a
  1262. ;v1.4    adc    word ptr curpsn[2],0    ;bump psn.hi if carry    v1.3a
  1263.  
  1264.     cmp    ax,cx            ;read all we expected?
  1265.     mov    ax,0            ;clear AX        v1.3a
  1266.     jz    ReadZ_ItX        ;yep, return CF clear    v1.3a
  1267.     mov    al,0BH            ;assume unexpected EOF
  1268.                     ;('invalid format')
  1269.     stc
  1270. ReadZ_ItX:
  1271.     ret                ;CF, AL set per error    v1.3a
  1272.  
  1273. Read_Zip_Entry    endp            ;GetHdr subroutine
  1274.  
  1275.  
  1276. ;v1.3    Common subroutine
  1277. ;    Bumps archive file pointers to next entry
  1278. ;    On success, return:
  1279. ;    CF clear
  1280. ;    AL = 0
  1281. ;    On failure (e.g., couldn't move ptrs), return:
  1282. ;    CF set
  1283. ;    AL = error
  1284.  
  1285. Bump_ArcPtrs    proc    near
  1286.  
  1287.     cmp    ftype,ZIP        ;ZIP file?            v1.3
  1288.     jz    Next_ZEntry        ;bump file ptr to next entry    v1.3
  1289.  
  1290. ;v1.3    Entirely new code
  1291.  
  1292.     mov    bx,offset archdr.aCmpSiz    ;-> encoded file length    v1.4
  1293.     mov    dx,[bx]            ;.lo                v1.4
  1294.     mov    cx,2[bx]        ;.hi
  1295.     jmp    short Bump_Common    ;common code
  1296.  
  1297.  
  1298. ;v1.3    Positions ZIP file pointer to next local entry.
  1299. ;    We've already read in the entire header, plus the filename,
  1300. ;    so the file pointer should be just beyond the filename
  1301. ;    (at the Extra field).
  1302. ;    Move file pointers beyond the Extra field, and then past
  1303. ;    the actual entry data (the compressed size).
  1304.  
  1305. Next_ZEntry:
  1306.  
  1307.     mov    bx,offset inbuf        ;point back to structure
  1308.     mov    dx,[bx].zCmpSiz        ;size.lo
  1309.     mov    cx,[bx].zCmpSiz[2]    ;size.hi
  1310.     add    dx,[bx].zExtraLen    ;add in extra field length
  1311.     adc    cx,0            ;in case of carry
  1312.  
  1313. Bump_Common:
  1314.  
  1315.     mov    bx,archdl        ;file handle
  1316.     mov    ax,4201H        ;move pointer from current loc
  1317.     int    21H
  1318.     jb    Bump_X            ;seek error        v1.3a
  1319.                     ;return CF set, AL=error v1.3a
  1320.  
  1321. ;v1.4    Updating curpsn variables now
  1322. ;    so the NEXT GetHdr call will have current data.
  1323.     mov    bx,offset curpsn
  1324.     mov    [bx],ax
  1325.     mov    2[bx],dx
  1326.     xor    ax,ax            ;AX,CF clear        v1.3a
  1327. Bump_X:
  1328.     ret
  1329.  
  1330. Bump_ArcPtrs    endp
  1331.  
  1332.  
  1333. ;v1.3    Formats, displays totals
  1334.  
  1335. Format_Totals    proc    near
  1336.  
  1337.     mov    ax,totmbrs        ;total members            v1.3
  1338.     mov    di,offset vtmbrs-2    ;format total members        v1.3
  1339.     call    Asciify            ;                v1.3
  1340.  
  1341.     mov    bx,offset totlen    ;-> total actual file size    v1.4
  1342.     mov    ax,[bx]            ;.lo                v1.4
  1343.     mov    dx,2[bx]        ;.hi                v1.4
  1344.  
  1345.     push    ax            ;save totlen.lo            v1.4
  1346.     push    dx            ; and totlen.hi            v1.4
  1347.  
  1348.     mov    di,offset vtlen        ;format total actual file size    v1.3
  1349.     call    Asciify_Long        ;                v1.3
  1350.  
  1351.     mov    bx,offset totsize    ;-> total compressed file sizes    v1.4
  1352.     mov    ax,[bx]            ;.lo                v1.4
  1353.     mov    dx,2[bx]        ;.hi                v1.4
  1354.  
  1355.     push    ax            ;save totsize.lo        v1.4
  1356.     push    dx            ; and totsize.hi        v1.4
  1357.  
  1358.     mov    di,offset vtsize    ;format total archive file size    v1.3
  1359.     call    Asciify_Long        ;                v1.3
  1360.  
  1361. ; reduce the total size/length to word values
  1362.  
  1363.     pop    dx            ;totsize.hi            v1.4
  1364.     pop    cx            ;totsize.lo            v1.4
  1365.     pop    ax            ;totlen.hi            v1.4
  1366.     pop    bx            ;totlen.lo            v1.4
  1367.  
  1368. ArcV2b: or    ax,ax            ; big number?
  1369.     jz    ArcV2c            ; nope, can use it
  1370.     shr    ax,1            ; yup, divide by two
  1371.     rcr    bx,1
  1372.     shr    dx,1
  1373.     rcr    cx,1
  1374.     jmp    short ArcV2b
  1375.  
  1376. ArcV2c:
  1377.     mov    ax,bx
  1378.     mov    sign,' '        ; whata kludge
  1379.     cmp    ax,cx            ; arc is bigger than orig?
  1380.     jb    ArcV2c1
  1381.     sub    ax,cx            ; amount saved
  1382.     jmp    short ArcV2f
  1383.  
  1384. ArcV2c1:
  1385.     sub    ax,cx
  1386.     neg    ax
  1387.     mov    sign,'-'
  1388.  
  1389. ArcV2f:
  1390.     mul    hundred            ; to percentage
  1391.     add    ax,50
  1392.     adc    dx,0            ; round up percent
  1393.     or    bx,bx            ; empty file?
  1394.     jnz    ArcV2d
  1395.     mov    ax,100
  1396.     jmp    short ArcV2e
  1397.  
  1398. ArcV2d: div    bx
  1399. ArcV2e:
  1400.     mov    di,offset vtsf-2    ;format stowage factor        v1.3
  1401.     call    Asciify            ;AX                v1.3
  1402.  
  1403.     mov    al,sign
  1404.     mov    vtsf,al
  1405.     Print    vthdr            ; display totals
  1406.     ret
  1407.  
  1408. Format_Totals    endp
  1409.  
  1410.  
  1411. OpenArc proc    near            ; open new archive
  1412.  
  1413.     mov    dx,offset arcname
  1414.     mov    ax,3d00h        ; for input
  1415.     int    21h
  1416.     jnb    Open_GetSize        ;opened ok            v1.3a
  1417.     ret                ;return CF set, AL=error    v1.3a
  1418.  
  1419. Open_GetSize:
  1420.     mov    bx,ax            ;handle into BX            v1.3a
  1421.     mov    archdl,ax        ; save file handle
  1422.  
  1423. ;v1.3a    We get the total file size now for later EOF testing.
  1424.     xor    dx,dx            ;0 offset
  1425.     xor    cx,cx
  1426.     mov    ax,4202H        ;from file end
  1427.     int    21H
  1428.     mov    filelen,ax        ;length.low
  1429.     mov    filelen[2],dx        ;length.hi
  1430.     xor    cx,cx            ;back to start
  1431.     xor    dx,dx
  1432.     mov    ax,4200H        ;psn file pointer from start
  1433.     int    21H
  1434.     ret                ;CF should be clear
  1435.  
  1436. OpenArc endp
  1437.  
  1438.  
  1439. ClosArc proc    near
  1440.  
  1441.     mov    bx,archdl        ; previous handle
  1442.     or    bx,bx            ; already open?
  1443.     jz    Closed
  1444.     mov    ah,3eh            ; yes, so close it
  1445.     int    21H
  1446. Closed:    mov    archdl,0        ;flag as closed
  1447.     ret
  1448.  
  1449. ClosArc endp
  1450.  
  1451. ;
  1452. ;    print null-terminated (AsciiZ) string like int 21h function 9
  1453. ;    Enter with DS:DX -> AsciiZ string
  1454. ;    destroys AX
  1455. ;    On success, return:
  1456. ;    CF clear
  1457. ;    AL = 0
  1458. ;    On failure (write fail), return:
  1459. ;    CF set
  1460. ;    AL = error
  1461.  
  1462. PrintS  proc    near
  1463.  
  1464.     push    di            ;v1.3
  1465.     push    bx
  1466.     push    cx
  1467.  
  1468.     mov    cx,0FFFFH        ;max scan            v1.3
  1469.     xor    al,al            ;handy 0            v1.3
  1470.     mov    di,dx            ;string start            v1.3
  1471.     repne    scasb            ;find the terminator        v1.3
  1472.     inc    cx            ;adjust                v1.3
  1473.     not    cx            ;CX=length            v1.3
  1474.  
  1475.     mov    bx,outhdl        ; using std out or temp file
  1476.     or    bx,bx            ;never opened?            v1.3
  1477.     jnz    Print_S1        ;nope, we got a handle        v1.3
  1478.     inc    bx            ;make it StdErr            v1.3
  1479.     inc    bx
  1480. Print_S1:                ;                v1.3
  1481.     mov    ah,40h            ; write to file
  1482.     int    21h
  1483.     jnb    PrintS_Done        ;fine                v1.3
  1484.  
  1485. ;v1.3    What happens if we're trying to write to an output file
  1486. ;    and THAT fails?  Even error msgs can't get out.
  1487. ;    We switch to StdErr, that's what!
  1488.  
  1489.     mov    di,ax            ;save error level        v1.3a
  1490.     mov    bx,STDERR        ;force to STdErr        v1.3a
  1491.     mov    outhdl,bx        ;and for future output        v1.3a
  1492.     mov    ah,40H            ;write to STDOUT        v1.3a
  1493.     int    21H            ;(CX,DX unchanged)        v1.3a
  1494.     mov    ax,di            ;restore orig error        v1.3a
  1495.     stc                ;return CF set            v1.3a
  1496.  
  1497. PrintS_Done:
  1498.     pop    cx            ; recover registers
  1499.     pop    bx
  1500.     pop    di
  1501.     ret
  1502.  
  1503. PrintS  endp
  1504.  
  1505.     page
  1506. ;
  1507. ;    format the time (in AX)
  1508.  
  1509. time    record  hour:5,min:6,sec:5    ;packed time
  1510.  
  1511. GetTime proc    near            ;format the date
  1512.     mov    di,offset vtime
  1513.     or    ax,ax            ;it is zero?
  1514.     jz    GotTime
  1515.  
  1516.     push    ax            ;save date
  1517.     and    ax,mask hour        ;get hour part
  1518.     mov    cl,hour            ;bits to shift
  1519.     shr    ax,cl
  1520.     call    Cnvrt1
  1521.     stosw
  1522.     mov    al,':'
  1523.     stosb
  1524.  
  1525. GT3:    pop    ax            ;get the time back
  1526.     and    ax,mask min        ;get min part
  1527.     mov    cl,min            ;bits to shift
  1528.     call    Cnvrt
  1529.     stosw
  1530. GotTime:ret
  1531. GetTime endp
  1532.  
  1533.  
  1534. Cnvrt2  proc    near            ;convert to ascii
  1535.     call    Cnvrt
  1536.     cmp    al,'0'            ;suppress leading zero
  1537.     jne    Cnvrtd
  1538.     mov    al,' '
  1539.     ret
  1540.  
  1541. Cnvrt:  shr    ax,cl
  1542. Cnvrt1: aam                ;make al into bcd
  1543.     or    ax,'00'            ; and to ascii
  1544.     xchg    al,ah
  1545. Cnvrtd: ret
  1546. Cnvrt2  endp
  1547.  
  1548.     page
  1549. ;
  1550. ;    format the date (in AX)
  1551.  
  1552. date    record  yr:7,mo:4,dy:5        ;packed date
  1553.  
  1554. GetDate proc    near            ;format the date
  1555.     or    ax,ax            ;is it zero?
  1556.     jz    GotDate
  1557.  
  1558.     push    ax            ;save date
  1559.     and    ax,mask yr        ;get year part
  1560.     mov    cl,yr            ;bits to shift
  1561.     call    Cnvrt
  1562.     mov    di,offset vyear
  1563.     or    al,'8'            ;adjust for base year
  1564.     stosw
  1565.  
  1566.     pop    bx            ;get the date back
  1567.     push    bx            ;save it
  1568.     and    bx,mask mo        ;get month part
  1569.     mov    cl,mo            ;bits to shift
  1570.     shr    bx,cl
  1571.     add    bx,bx            ; form month table index
  1572.     add    bx,bx
  1573.     lea    si,word ptr months-4[bx]
  1574.     mov    cx,word ptr 3
  1575.     mov    di,offset vmonth
  1576.     rep    movsb
  1577.  
  1578.     pop    ax            ;get the date back
  1579.     and    ax,mask dy        ;get day part
  1580.     mov    cl,dy            ;bits to shift
  1581.     call    Cnvrt
  1582.     mov    di,offset vdate
  1583.     stosw
  1584. GotDate:ret
  1585. GetDate endp
  1586.  
  1587.     page
  1588. ;
  1589. ;v1.3    A severely hacked single/double precision number conversion function.
  1590. ;    Originally from JMODEM, but severely hacked by Toad Hall.
  1591. ;    ES:DI -> string
  1592. ;    Destroys everything almost.
  1593.  
  1594. ;Enter here if integer in AX
  1595. Asciify    proc    near
  1596.  
  1597.     xor    dx,dx            ; clear fake long.hi
  1598.     mov    si,ax            ;move integer into SI
  1599.     xor    ah,ah            ;clear msb (flag)
  1600.     jmp    short Ascii_Ax        ;jump into the code
  1601.  
  1602. ;Enter here if long integer in DX:AX.
  1603. Asciify_Long:
  1604.  
  1605.     mov    si,ax            ;move long.lo into SI
  1606.     xor    ah,ah            ;clear msb (flag)
  1607. Comment    ~
  1608.     MOV    CX,3B9AH        ; Get billions
  1609.     MOV    BX,0CA00H
  1610.     CALL    Subtr            ; Subtract them out
  1611.  
  1612.     MOV    CX,05F5H        ; Get hundred-millions
  1613.     MOV    BX,0E100H
  1614.     CALL    Subtr            ; Subtract them out
  1615. Comment    ends    ~
  1616.  
  1617.     and    dx,4FFH            ;seems likely            v1.3
  1618.     MOV    CX,word ptr 0098H    ; Get ten-millions
  1619.     MOV    BX,9680H
  1620.     CALL    Subtr            ; Subtract them out
  1621.  
  1622.     MOV    CX,word ptr 000FH    ; Get millions
  1623.     MOV    BX,4240H
  1624.     CALL    Subtr            ; Subtract them out
  1625.  
  1626.     MOV    CX,word ptr 1        ; Get hundred-thousands
  1627.     MOV    BX,86A0H
  1628.     CALL    Subtr            ; Subtract them out
  1629.  
  1630. Ascii_Ax:
  1631.     xor    cx,cx            ; Get ten-thousands
  1632.     MOV    BX,2710H
  1633.     CALL    Subtr            ; Subtract them out
  1634.     MOV    BX,03E8H
  1635.     CALL    Subtr            ; Subtract them out
  1636.  
  1637.     MOV    BX,word ptr 0064H
  1638.     CALL    Subtr            ; Subtract them out
  1639.     MOV    BX,word ptr 10
  1640.     CALL    Subtr            ; Subtract them out
  1641.     mov    ax,si            ;residual in SI
  1642.     add    AL,'0'            ; Add bias to residual
  1643.     stosb                ; Put in the string
  1644.     RET
  1645.  
  1646. ;Common subroutine for Asciify
  1647.  
  1648. Subtr:    mov    al,'0'-1
  1649.  
  1650. Subtr1:    INC    al            ; Bump the digit character
  1651.     SUB    si,BX            ; Dword subtraction
  1652.     SBB    DX,CX
  1653.     JNB    Subtr1            ; Continue until a carry
  1654.  
  1655.     ADD    si,BX            ; One too many, add back
  1656.     ADC    DX,CX            ;   and the remainder
  1657.  
  1658.     cmp    al,'0'
  1659.     jnz    Subtr2            ;nope, turn off leading flag, stuff
  1660.     or    ah,ah            ;no more leading spaces?
  1661.     jnz    Sub_Stuff        ;right, stuff the '0'
  1662.     mov    al,' '            ;make it neat with leading spaces
  1663. Sub_Stuff:
  1664.     stosb                ;stuff the char
  1665.     RET
  1666.  
  1667. Subtr2:    inc    ah            ;turn off leading space flag
  1668.     stosb
  1669.     ret
  1670. Asciify    ENDP
  1671.  
  1672.  
  1673. ;v1.3a    Convert 16-bit binary word in AX
  1674. ;    to hex ASCII string at ES:DI
  1675. ;    (No need to save any registers)
  1676.  
  1677. hexchar db    '0123456789ABCDEF'
  1678.  
  1679. Cvh    proc    near
  1680.  
  1681.     mov    si,offset hexchar    ;for faster access        v1.3a
  1682.     mov    dx,ax            ; save 16-bits
  1683.  
  1684.     mov    bl,dh            ; third nibble
  1685.     mov    cx,0F04H        ;CL=4 for shifting,        v1.3a
  1686.                     ;CH=0FH for masking        v1.3a
  1687.     shr    bl,cl
  1688.     mov    al,[si][bx]        ;snarf hex char            v1.3a
  1689.     stosb
  1690.  
  1691.     mov    bl,dh            ; last nibble
  1692.     and    bl,ch    ;0fh        ;                v1.3a
  1693.     mov    al,[si][bx]        ;snarf hex char            v1.3a
  1694.     stosb
  1695.  
  1696.     mov    bl,dl            ; first nibble
  1697.     sub    bh,bh
  1698.     shr    bl,cl            ; isolate (CL still 4)        v1.3a
  1699.     mov    al,[si][bx]        ;snarf hex char            v1.3a
  1700.     stosb
  1701.  
  1702.     mov    bl,dl            ; second nibble
  1703.     and    bl,ch    ;0fh        ; isolate            v1.3a
  1704.     mov    al,[si][bx]        ;snarf hex char            v1.3a
  1705.     stosb
  1706.     ret
  1707.  
  1708. Cvh    endp
  1709.  
  1710.     subttl    '--- i/o data areas'
  1711.  
  1712. ArcV    endp
  1713.  
  1714. archdr  db    30 dup (0)        ; i/o area for a header        v1.3a
  1715.  
  1716. inbuf    db    INBUFSZ dup (0)        ;just big enough for ZIP
  1717.                     ;directories and filenames    v1.3a
  1718.  
  1719. CSEG    ENDS
  1720.     END
  1721.