home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / open / zipv107.lzh / ZIPV.ASM next >
Assembly Source File  |  1989-03-16  |  25KB  |  1,047 lines

  1.     page    74,132
  2.     title    ZIPV - Display directory of ZIP files
  3.  
  4. ; name:     ZIPV, version 1, 7 March 1989
  5. ; copyright:    1989, for personal use only; may not be sold.
  6. ; author:    Vernon D. Buerg
  7. ;
  8. ; syntax:
  9. ;        ZIPV [filespec[.ZIP] [/p] [/b] [/c]
  10. ; where:
  11. ;    /p  pauses the display after a screen full
  12. ;    /b  suppresses display of d:\path information for bbs use
  13. ;    /c  displays ZIPfile and file comments and extra fields
  14. ;
  15. ; output:
  16. ;    - errorlevel returned:
  17. ;    0 - normal completion
  18. ;    1 - wrong DOS version
  19. ;    2 - no files found
  20. ;    3 - some invalid ZIP file(s) encountered
  21. ;
  22. ; notes:
  23. ;    - supports DOS 3 file sharing
  24. ;    - requires about 56k of memory, figure 64k for a .COM program
  25. ;    - assembled using SLR Systems OPTASM; you figure the JMPs for MASM
  26. ;    - handles self-extracting ZIP files (.EXE type)
  27.  
  28.     .xlist
  29. print    macro    name            ; display a field
  30.     mov    dx,offset name
  31.     call    prints
  32.     endm
  33.  
  34. printl    macro    text            ; display a literal
  35.     local    txt,nxt
  36.     mov    dx,offset txt
  37.     call    prints
  38.     jmp    nxt
  39. txt    db    cr,lf,text
  40.     db    stopper
  41. nxt    equ    $
  42.     endm
  43.  
  44. save    macro    reglist         ; save registers
  45.     irp    reg, <reglist>
  46.     push    reg
  47.     endm
  48.     endm
  49.  
  50. restore macro    reglist         ; restore registers
  51.     irp    reg, <reglist>
  52.     pop    reg
  53.     endm
  54.     endm
  55.     .list
  56.  
  57. central_dir    struc            ; from APPNOTES.TXT
  58. cd_sig        db    02h,01h,4bh,50h ; signature
  59. cdver_made    db    0,0        ; version made by
  60. cdver_ext    db    0,0        ; version to extract
  61. cd_flag     db    0,0        ; general purpose bit flag
  62. cd_method    dw    0        ; compression method
  63. cd_mod_time    dw    0        ; last mod time
  64. cd_mod_date    dw    0        ; last mod date
  65. cd_crc        dw    0,0        ; crc-32
  66. cd_comp_size    dw    0,0        ; compressed size
  67. cd_true_size    dw    0,0        ; uncompressed size
  68. cd_flnm_len    dw    0        ; filename length
  69. cd_extra_len    dw    0        ; extra field length
  70. cd_comment_len    dw    0        ; file comment length
  71. cd_disk_start    dw    0        ; disk number start
  72. cd_intfile_attr dw    0        ; internal file attributes
  73. cd_extfile_attr dw    0,0        ; external file attributes
  74. cd_local_offset dw    0,0        ; file offset of local header
  75.                     ; variable length fields follow (boo-hiss)
  76. central_dir    ends
  77.  
  78. cd_filename    equ    size central_dir; filename (variable size)
  79. cd_extra    equ    size central_dir; extra field (variable size)
  80. cd_comment    equ    size central_dir; file comment (variable size)
  81.  
  82. central_end    struc            ; length 22+n
  83. ce_sig        db    06h,05h,4bh,50h ; signature
  84. ce_disk_number    dw    0        ; number of this disk
  85. ce_disk_start    dw    0        ; disk number with central dir start
  86. ce_disk_entries dw    0        ; entries in central dir on this disk
  87. ce_entries    dw    0        ; total entries in central dir
  88. ce_size     dw    0,0        ; size of central dir
  89. ce_offset    dw    0,0        ; offset to central dir on this disk
  90. ce_comment_len    dw    0        ; length of zipfile comment
  91.                     ; variable length fields follow (nerts)
  92. central_end    ends
  93.  
  94. ce_comment    equ    size central_end; zipfile comment (variable size)
  95.  
  96. dtantry struc                ; DOS Data Transfer Area
  97. dtarsvd db    21 dup (0)        ;  reserved
  98. dtaattr db    0            ;  attribute
  99. dtatime dw    0            ;  update time
  100. dtadate dw    0            ;  update date
  101. dtasize dw    0,0            ;  size bytes (lo,hi)
  102. dtaname db    12 dup (' ')            ;  name and ext
  103.     db    0,13,10,255        ;  stopper and print
  104. dtantry ends
  105.  
  106.     subttl    ZIPV - Mainline routines
  107.     page
  108.  
  109. cseg    segment public para 'CODE'
  110.     assume    cs:cseg, ds:cseg, ss:cseg, es:cseg
  111.     org    100h
  112.  
  113. zipv    proc    far
  114.     jmp    start            ; skip around data
  115.  
  116.     subttl    --- constants, equates and data areas
  117.     page
  118.  
  119. bel    equ    7            ; honker
  120. bs    equ    8            ; backspace
  121. tab    equ    9            ; tabski
  122. lf    equ    10            ; Line Feed
  123. cr    equ    13            ; la Carriage Return
  124. eof    equ    26            ; end of file character
  125. stopper equ    255            ; ends print strings
  126.  
  127.     db    bs,bs,bs,'   '          ; overlay entry jmp for type
  128.  
  129. usage    db    cr,lf,     'ZIPV Version 1.07 Copyright (c) 1989 Vernon D. Buerg'
  130.     db    cr,lf,     'For personal use only. May not be sold.'
  131.     db    cr,lf,lf,'  Usage:  zipv [d:][\path\]filespec[.ZIP]  [/p] [/b] [/c]'
  132.     db    cr,lf
  133.     db    cr,lf,     '  Where:  /P pauses after each screenful'
  134.     db    cr,lf,     '          /B suppresses display of d:\path'
  135.     db    cr,lf,     '          /C displays comments'
  136.     db    cr,lf,stopper,eof
  137.  
  138. errlvl    db    0            ; dos error level returned
  139. opencod db    0            ; open code for share
  140. flags    db    255            ; find-first return code
  141.  
  142. options db    0            ; command options
  143. b_parm     equ    1            ; /b -bbs display option
  144. p_parm     equ    2            ; /p -pause at screen full
  145. c_parm     equ    4            ; /c - display comments
  146.  
  147. stkptr    dw    0            ; stack pointer upon entry
  148. ce_ptr    dw    0            ; offset to central_end dir record
  149. ce_count dw    0            ; count of entries in central dir
  150.  
  151. fileptr dw    filenm            ; spot after d:\path
  152. filehdl dw    0            ; file handle
  153.  
  154. ziptitl db    cr,lf,'Archive:  ',stopper
  155.  
  156. zipname db    13 dup (0),0,stopper    ; ZIP file name for heading
  157.  
  158. ;    display lines for verbose
  159.  
  160. vhdr    db    cr,lf
  161.     db    cr,lf,'Name          Length    Method     SF   Size now  Mod Date    Time    CRC-32 '
  162. dashes    db    cr,lf,'============  ========  ========  ====  ========  =========  ======  ========'
  163.     db    stopper
  164.  
  165. vline    db    cr,lf
  166. vname    db    14 dup (' ')
  167. vsize    db    '       0  '            ; acutal file size
  168. vstyle    db    '          '            ; compression method
  169. vfactor db    ' xx%  '                ; compression factor
  170. vlength db    10 dup (' ')            ; compressed length
  171. vdate    db    'dd '                   ; creation date
  172.  vmonth db    'mmm '
  173.  vyear    db    'yy  '
  174.  vtime    db    'hh:mm   '              ; creation time
  175.  vcrc    db    'xxxxxxxx'              ; crc in hex
  176.     db    stopper
  177. len_vline equ    $-vline         ; length of print line
  178.  
  179. totsf    dw    0,0            ; average stowage factor
  180. totlen    dw    0,0            ; total of file lengths
  181. totsize dw    0,0            ; total of file sizes
  182. totmbrs dw    0            ; total number of files
  183.  
  184. ;    final totals line
  185.  
  186. vthdr    db    cr,lf,'*total'
  187.  vtmbrs db    '        '
  188.  vtsize db    8 dup (' '),'  '
  189.     db    10 dup (' ')
  190.  vtsf    db    '   %  '
  191.  vtlen    db    8 dup (' ')
  192.     db    cr,lf
  193.     db    stopper
  194.  sign    db    ' '
  195.  
  196. vtotal    db    '*total'
  197. ctitle    db    cr,lf,'Comment:  ',stopper
  198. cextra    db    cr,lf,'Extra:    ',stopper
  199.  
  200. styles    db    'Stored  '              ; compression method names
  201.     db    'Shrunk  '
  202.     db    'Reduced1'
  203.     db    'Reduced2'
  204.     db    'Reduced3'
  205.     db    'Reduced4'
  206.  
  207. hundred dw    100            ; for computing percentages
  208. months    db    'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
  209.     subttl    --- Mainline
  210.     page
  211.  
  212. start:
  213.     mov    sp,offset cs:stk_end    ; local stack
  214.     mov    stkptr,sp        ; save for dos return
  215.  
  216.     mov    ah,30h            ; get dos version
  217.     int    21h            ;
  218.     cmp    al,2            ; version 2 or later?
  219.     jb    badver            ; no, gotta quit
  220.     cmp    al,3            ; enough for share?
  221.     jb    dos_okay        ; no, open as-is
  222.     mov    opencod,40h        ; yes, add read-only
  223.  
  224. dos_okay:
  225.     mov    bx,paras        ; size of program
  226.     mov    ah,4ah            ; shrink allocated memory
  227.     int    21h            ; setblock function
  228.  
  229.     mov    di,offset filenm    ; clear operands
  230.     mov    cx,offset stk-filenm    ;  and work areas
  231.     mov    al,0            ;
  232.     rep    stosb            ;
  233.  
  234.     subttl    --- gather command line parameters
  235.     page
  236.  
  237. getparm:
  238.     mov    si,82h            ; Command tail
  239.     sub    cx,cx            ;
  240.     or    cl,byte ptr -2[si]    ; test parm length
  241.     jz    getparms        ; none, return as-is
  242.  
  243. sw1:    lodsb                ; scan for switch
  244.     cmp    al,'/'                  ;
  245.     loopne    sw1            ;
  246.     or    cx,cx            ; found one?
  247.     jz    getparms        ; no, done
  248.     mov    byte ptr -1[si],cr    ; yes, stop command line there
  249.     jmp    sw2a            ; and check next character
  250.  
  251. sw2:    lodsb                ; Next character
  252.     cmp    al,'/'                  ; Another switch?
  253.     loopne    sw2            ;
  254.     jcxz    getparms        ;
  255.  
  256. sw2a:    lodsb                ; yes, get letter following
  257.     and    al,0dfh         ; make upper case
  258.     dec    cx            ;
  259.     jle    sw3            ; missing switch
  260.  
  261. sw3:    cmp    al,'P'                  ; Pause?
  262.     jne    sw4            ;
  263.     or    options,p_parm        ;
  264.  
  265. sw4:    cmp    al,'B'                  ; BBS use
  266.     jne    sw5            ;
  267.     or    options,b_parm        ;
  268.  
  269. sw5:    cmp    al,'C'                  ; display Comments?
  270.     jne    sw2            ;
  271.     or    options,c_parm        ;
  272.     jmp    sw2            ; Try for another option
  273.  
  274.     subttl    --- Gather command operands
  275.     page
  276.  
  277. ;    copy first command line operand as ZIP selection filespec
  278.  
  279. getparms:
  280.     mov    si,80h            ; offset to command line
  281.     sub    cx,cx            ; its length
  282.     or    cl,byte ptr [si]    ; any operand?
  283.     jnz    parm0            ; no,
  284.     print    usage            ;  display usage
  285.     jmp    zipv_exit        ;   and quit
  286.  
  287. parm0:    inc    si            ; point to operands
  288. parm2:    lodsb                ; strip leading blanks
  289.     cmp    al,' '                  ;
  290.     loope    parm2            ;
  291.  
  292.     mov    di,offset filenm    ; first operand target
  293.     stosb                ;
  294. parm3:    lodsb                ; copy filename
  295.     cmp    al,cr            ; end of name?
  296.     je    parm4            ;
  297.     cmp    al,' '                  ; don't know why this is here
  298.     je    parm4            ;
  299.     stosb                ;
  300.     loop    parm3            ;
  301. parm4:
  302.     mov    si,offset filenm +75    ; end of filename stuff
  303.     mov    cx,76            ;
  304.     std                ;
  305. parm5:
  306.     lodsb                ;
  307.     cmp    al,'/'                  ; funny path delimiter?
  308.     je    parm6            ;
  309.     cmp    al,'\'                  ; normal path delimiter?
  310.     je    parm6            ;
  311.     cmp    al,':'                  ; bumped into drive?
  312.     je    parm6            ;
  313.     loop    parm5            ;
  314.     dec    si            ;
  315. parm6:
  316.     cld                ;
  317.     add    si,2            ; point to where filename goes
  318.     mov    fileptr,si        ; and save for later
  319.  
  320. ;    add default ZIP extension if necessary
  321.  
  322.     mov    si,fileptr        ; start of filespec
  323.     mov    cx,13            ;
  324. parm10:
  325.     lodsb                ;
  326.     cmp    al,0            ; end of name?
  327.     je    parm11            ;
  328.     cmp    al,'.'                  ; got extension?
  329.     je    parm12            ;
  330.     loop    parm10            ;
  331. parm11:
  332.     mov    di,si            ; ptr to end of name
  333.     dec    di            ;
  334.     mov    ax,'Z.'                 ; default extension
  335.     stosw                ;
  336.     mov    ax,'PI'                 ;
  337.     stosw                ;
  338. parm12:
  339.  
  340.     subttl    --- Find matching files
  341.     page
  342. ;
  343. ;    set up next matching file name
  344.  
  345. process:
  346.     mov    dx,offset dta        ; set local dta for murkers
  347.     mov    ah,1ah            ;
  348.     int    21h            ;
  349.  
  350.     mov    dx,offset filenm    ; find first matching file
  351.     sub    cx,cx            ; normal attribute
  352.     mov    ah,4eh            ;
  353.     int    21h            ;
  354.     mov    flags,al        ; indicate find-first status
  355.     or    ax,ax            ; any return code?
  356.     jz    gotfirst        ; nope, continue
  357.     jmp    nofiles         ; yup, abort
  358.  
  359. ;    set up next matching file name
  360.  
  361. gotfirst:
  362.     mov    si,offset dta+30    ; point to filename found
  363.     mov    di,fileptr        ; and overlay old name
  364.     mov    cx,13            ;
  365. gotfirst1:
  366.     lodsb                ; next char
  367.     stosb                ;
  368.     cmp    al,0            ; end of name?
  369.     loopne    gotfirst1        ;
  370.     mov    al,0FFh         ; append stoppers
  371.     stosb                ;
  372.  
  373.     mov    si,offset dta+30    ; copy filename for heading
  374.     mov    di,offset zipname    ;
  375.     mov    cx,13            ; asciiz filename
  376. gotfirst2:
  377.     lodsb                ; next char
  378.     stosb                ;
  379.     cmp    al,0            ; end of name?
  380.     loopne    gotfirst2        ;
  381.     mov    al,0FFh         ; append stoppers
  382.     stosb                ;
  383.  
  384. process_loop:                ; open the file
  385.     mov    dx,offset filenm    ; point to d:\path\filename
  386.     mov    ah,3dh            ; open function
  387.     mov    al,opencod        ; share parameters
  388.     int    21h            ; issue open
  389.     jc    open_err1        ; oops
  390.     mov    filehdl,ax        ; save file handle
  391.  
  392.     call    posfile         ; position and read central directory
  393.  
  394.     call    close            ; release the ZIP file
  395.  
  396.     call    dispdir         ; display directory contents
  397.  
  398. getnext:
  399.     mov    ah,4fh            ; get next file name
  400.     int    21h            ;
  401.     jc    alldone         ;
  402.     or    ax,ax            ;
  403.     jz    gotfirst        ;
  404. alldone:
  405.     jmp    zipv_exit        ; all done
  406.  
  407.     subttl    --- Display directory entries
  408.     page
  409.  
  410. ecount    dw    0            ; entries on current disk
  411.  
  412. dispdir proc    near
  413.     sub    ax,ax            ; reset totals counters
  414.     mov    totmbrs,ax        ;
  415.     mov    totsize,ax        ;
  416.     mov    totsize+2,ax        ;
  417.     mov    totlen,ax        ;
  418.     mov    totlen+2,ax        ;
  419.     mov    totsf,ax        ;
  420.  
  421. ;  display titles
  422.  
  423.     mov    ax,ce_count        ; number of entries
  424.     mov    ecount,ax        ; save as line counter
  425.     print    ziptitl         ;
  426.     test    options,b_parm        ; want short filename?
  427.     jz    dispdir1        ; no
  428.     print    zipname         ; show short name
  429.     jmp    dispdir2        ;
  430. dispdir1:
  431.     print    filenm            ; show full name
  432.  
  433. ;  display comments
  434.  
  435. dispdir2:
  436.     test    options,c_parm        ; want them?
  437.     jz    disp3            ; no
  438.     mov    si,ce_ptr        ; offset to ce dir
  439.     mov    cx,ce_comment_len[si]    ;
  440.     jcxz    disp3            ; if none
  441.     print    ctitle            ; yes, add heading item
  442.     lea    dx,ce_comment[si]    ; point to comment
  443.     mov    ah,40h            ; write to file
  444.     mov    bx,1            ; using std out
  445.     int    21h            ;
  446.  
  447. disp3:
  448.     print    vhdr            ; show headings
  449.     mov    bx,offset cdir        ; first header in central directory
  450. dispdir_loop:
  451.     mov    di,offset vname     ; clear print line
  452.     mov    cx,14            ;
  453.     mov    al, ' '                 ;
  454.     rep    stosb            ;
  455.  
  456.     call    stowage         ; compute stowage factor
  457.  
  458. disp_style:
  459.     mov    si,cd_method[bx]    ; compression method code
  460.     mov    cl,3            ;
  461.     shl    si,cl            ; time style length
  462.     add    si,offset styles    ; list of method names
  463.     mov    di,offset vstyle    ;
  464.     mov    cx,8            ;
  465.     rep    movsb            ;
  466.  
  467. disp_crc:
  468.     mov    di,offset vcrc        ; format crc-32 value
  469.     mov    ax,cd_crc+2[bx]     ; first word
  470.     call    cvh            ;
  471.     mov    ax,cd_crc[bx]        ; second word
  472.     call    cvh            ;
  473.  
  474.     mov    ax,cd_mod_time[bx]    ; last modified time
  475.     call    gettime         ; format it
  476.  
  477.     mov    ax,cd_mod_date[bx]    ; last modified date
  478.     call    getdate         ; format it
  479.  
  480.     mov    ax,word ptr cd_true_size[bx]   ; actual file size
  481.     mov    dx,word ptr cd_true_size+2[bx] ; high word
  482.     add    totsize,ax        ; accumulate total size
  483.     adc    totsize[2],dx        ;
  484.     mov    si,offset vsize     ;
  485.     call    format            ;
  486.  
  487.     mov    ax,word ptr cd_comp_size[bx]   ; compressed file size
  488.     mov    dx,word ptr cd_comp_size+2[bx] ; high word
  489.     add    totlen,ax        ; accumulate total length
  490.     adc    totlen[2],dx        ;
  491.     mov    si,offset vlength    ;
  492.     call    format            ;
  493.  
  494.     mov    cx,cd_flnm_len[bx]    ; file name length
  495.     lea    si,cd_filename[bx]    ;  and offset
  496.     mov    di,offset vname     ;   to print line
  497.     rep    movsb            ;
  498.  
  499.     inc    totmbrs         ; total files count
  500.     print    vline            ; display an entry
  501.  
  502. ;  process extra field
  503.  
  504. dispdir_extra:
  505.     test    options,c_parm        ; want comments?
  506.     jz    dispdir_next        ;  no
  507.     mov    cx,cd_extra_len[bx]    ; extra field
  508.     jcxz    dispdir_comment     ; if none
  509.     mov    si,cx            ; compute offset
  510.     add    si,bx            ;  to extra field
  511.     add    si,cd_flnm_len[bx]    ;
  512.     print    cextra            ;
  513.     lea    dx,cd_comment[si]    ; point to comment
  514.     mov    ah,40h            ; write to file
  515.     mov    bx,1            ; using std out
  516.     int    21h            ;
  517.  
  518. ;  display copmment field
  519.  
  520. dispdir_comment:
  521.     mov    cx,cd_comment_len[bx]    ; comment field
  522.     jcxz    dispdir_next        ; if none
  523.     mov    si,cx            ; compute offset
  524.     add    si,bx            ;  to comments
  525.     add    si,cd_flnm_len[bx]    ;
  526.     add    si,cd_extra_len[bx]    ;
  527.     print    ctitle            ;
  528.     lea    dx,cd_comment[si]    ; point to comment
  529.     mov    ah,40h            ; write to file
  530.     mov    bx,1            ; using std out
  531.     int    21h            ;
  532.  
  533. ; set-up for next entry
  534.  
  535. dispdir_next:
  536.     mov    cx,size central_dir    ; minimum cd entry size
  537.     add    cx,cd_flnm_len[bx]    ;  plus file name length
  538.     add    cx,cd_extra_len[bx]    ;   plus extra field length
  539.     add    cx,cd_comment_len[bx]    ;    plus comment field length
  540.     add    bx,cx            ;     to point to next entry
  541.     dec    ecount            ;
  542.     jnz    dispdir_loop        ; continue
  543.  
  544.     page
  545. ;
  546. ;    display totals for current file
  547.  
  548. dir_totals:
  549.     print    dashes            ; separate totals line
  550.  
  551.     mov    ax,totsize        ; total file sizes
  552.     mov    dx,totsize[2]        ; high word
  553.     mov    si,offset vtsize    ;
  554.     call    format            ;
  555.  
  556.     mov    ax,totlen        ; compressed file size
  557.     mov    dx,totlen[2]        ; high word
  558.     mov    si,offset vtlen     ;
  559.     call    format            ;
  560.  
  561.     mov    ax,totmbrs        ; count of members
  562.     sub    dx,dx            ;
  563.     mov    si,offset vtmbrs-2    ;
  564.     call    format            ;
  565.  
  566.     mov    cx,totlen        ; compressed file size
  567.     mov    dx,totlen[2]        ; high word
  568.     mov    bx,totsize        ; actual file size
  569.     mov    ax,totsize[2]        ; high word
  570.     call    stow_total        ;
  571.  
  572.     mov    si,offset vtotal    ; say *total
  573.     mov    di,offset vthdr+2    ;
  574.     mov    cx,6            ;
  575.     rep    movsb            ;
  576.  
  577.     print    vthdr            ; display totals
  578.     ret                ;
  579. dispdir endp
  580.  
  581.     subttl    --- Position file
  582.     page
  583. ;
  584. ;    Position to end of ZIP file less central directory size
  585.  
  586. margin    dw    size central_end    ; how far before ce to read
  587.  
  588. posfile proc    near            ;
  589.     mov    margin,size central_end ; how far before ce dir to point
  590.  
  591. posfile_point:
  592.     mov    bx,filehdl        ; get file handle
  593.     mov    cx,dta.dtasize[2]    ; high word of size
  594.     mov    dx,dta.dtasize        ; low word of size
  595.     sub    dx,margin        ; less size of central
  596.     sbb    cx,0            ;   directory end record
  597.     jl    posfile_start        ; if small file
  598.     mov    ax,4200h        ; move to central end directory
  599.     int    21h            ; lseek function
  600.     jmp    read_ce         ;
  601.  
  602. posfile_start:
  603.     mov    ax,dta.dtasize        ; use file size
  604.     mov    margin,ax        ;  as amount to position
  605.     jmp    posfile_point        ;
  606.  
  607. ;  read central-directory-end record
  608.  
  609. read_ce:
  610.     mov    cx,margin        ; how much to read (pos before eof)
  611.     mov    dx,offset cde        ; central end dir area
  612.     mov    ah,3fh            ;
  613.     int    21h            ;
  614.     jc    open_err2        ; failed
  615.     cmp    ax,cx            ; read it all?
  616.     jne    open_err3        ; nope
  617.  
  618. ;  search end of file for cde signature
  619.  
  620.     mov    bx,offset cde+1     ; point to centerl end dir record
  621.     mov    cx,margin        ; look back this far
  622.     sub    cx,size central_end-1    ;
  623.     add    bx,cx            ;
  624. search_loop:
  625.     mov    si,bx            ; next cde byte
  626.     dec    bx            ;
  627.     cmp    word ptr [si],4b50h    ; check signature
  628.     jne    search_loop1        ;
  629.     cmp    word ptr 2[si],0605h    ;
  630.     je    read_cd         ; found it
  631. search_loop1:
  632.     loop    search_loop        ; continue search
  633.     add    margin,256        ; not yet,
  634.     jmp    posfile_point        ;  back up some more
  635.  
  636. ; re-position to central-directory
  637.  
  638. read_cd:
  639.     mov    ce_ptr,si        ; save pointer to c_e dir start
  640.     mov    ax,ce_disk_entries[si]    ; number of entries
  641.     mov    ce_count,ax        ;  and save for later
  642.     mov    dx,ce_offset[si]    ; offset to central directory
  643.     mov    cx,ce_offset+2[si]    ;
  644.     mov    bx,filehdl        ; get file handle
  645.     mov    ax,4200h        ; move file pointer
  646.     int    21h            ; returns dx:ax position
  647.  
  648. ; read the central directory until end-of-file
  649.  
  650.     mov    bx,dta.dtasize[2]    ; get file size in bx:cx
  651.     mov    cx,dta.dtasize        ;  to compute
  652.     sub    cx,ax            ;   size of
  653.     sbb    bx,dx            ;    central dir to eof
  654.     mov    bx,filehdl        ; get file handle
  655.     mov    ah,3fh            ; for reading
  656.     mov    dx,offset cdir        ; central dir end area
  657.     int    21h            ;
  658.     jc    open_err4        ; failed
  659.     cmp    ax,cx            ; read it all?
  660.     jne    open_err5        ; nope
  661.  
  662.     ret                ;
  663. posfile endp
  664.  
  665.     page
  666. ;
  667. ;    compute stowage; reduce the size/length to word values
  668.  
  669. stowage proc    near            ; compute stowage factor
  670.     push    bx            ; save dir pointer
  671.  
  672.     mov    cx,word ptr cd_comp_size[bx]     ; compressed file size
  673.     mov    dx,word ptr cd_comp_size+2[bx]     ; high word
  674.  
  675.     mov    ax,word ptr cd_true_size+2[bx]     ; high word
  676.     mov    bx,word ptr cd_true_size[bx]     ; actual file size
  677.     mov    si,offset vfactor-5    ; target area
  678.     jmp    stow51            ;
  679.  
  680. stow_total:
  681.     push    bx            ; entry for totals calculation
  682.     mov    si,offset vtsf-5    ; target area
  683.  
  684. stow51: or    ax,ax            ; big number?
  685.     jz    stow52            ; nope, can use it
  686.     shr    ax,1            ; yup, divide by two
  687.     rcr    bx,1            ;
  688.     shr    dx,1            ;
  689.     rcr    cx,1            ;
  690.     jmp    stow51            ;
  691.  
  692. stow52:
  693.     mov    ax,bx            ; low word of actual size
  694.     mov    sign,' '                ;
  695.     cmp    ax,cx            ; zip member is larger?
  696.     jb    stow520         ;
  697.     sub    ax,cx            ; amount saved
  698.     jmp    stow56            ;
  699. stow520:
  700.     sub    ax,cx            ;
  701.     neg    ax            ;
  702.     mov    sign,'-'                ;
  703. stow56:
  704.     mul    hundred         ; to percentage
  705.     add    ax,50            ;
  706.     adc    dx,0            ; round up percent
  707.     or    bx,bx            ; empty file?
  708.     jnz    stow53            ;
  709.     mov    ax,100            ;
  710.     jmp    stow54            ;
  711.  
  712. stow53: div    bx            ;
  713. stow54: sub    dx,dx            ;
  714.     cmp    ax,100            ; archive fouled?
  715.     jbe    stow55            ;
  716.     sub    ax,ax            ;
  717. stow55:
  718.     call    format            ;
  719.     mov    al,sign         ; get + or -
  720.     mov    byte ptr [si],al    ;
  721.     pop    bx            ; restore dir pointer
  722.     ret                ; return to caller
  723. stowage endp                ;
  724.  
  725.     subttl    --- subroutines
  726.     page
  727. ;
  728. ;    close the file
  729.  
  730. close    proc    near            ;
  731.     mov    bx,filehdl        ; file handle
  732.     or    bx,bx            ; is it open
  733.     jz    close_done        ;
  734.     mov    ah,3eh            ; close function
  735.     int    21h            ;
  736.     sub    bx,bx            ;
  737. close_done:
  738.     mov    filehdl,bx        ; indicate closed
  739.     ret                ;
  740. close    endp                ;
  741.  
  742.     page
  743. ;
  744. ;    print string like int 21h function 9
  745.  
  746. pause    db    cr,lf,'... more?$'
  747. backup    db    cr,9 dup (8),'$'
  748. linecnt db    0        ; line counter for pause
  749. pagecnt db    23        ; lines per screen
  750.  
  751. prints    proc    near            ; dx has offset to string
  752.  
  753.     test    options,p_parm        ; want pausing?
  754.     jz    ps1            ; no, skip next
  755.  
  756.     save    <bx,cx,dx,si>        ; save work regs
  757.     mov    al,linecnt        ;
  758.     cmp    al,pagecnt        ; end of screen?
  759.     jbe    ps0            ; not yet
  760.     mov    dx,offset pause     ; yup, say so
  761.     mov    ah,9            ;
  762.     int    21h            ;
  763.     mov    ah,0            ; get a key
  764.     int    16h            ;
  765.     mov    dx,offset backup    ; over write pause prompt
  766.     mov    ah,9            ;
  767.     int    21h            ;
  768.     mov    linecnt,0        ; reset line counter
  769. ps0:    restore <si,dx,cx,bx>        ; restore work regs
  770.  
  771. ps1:    save    <si,bx,cx>        ; save work regs
  772.     mov    si,dx            ;
  773.     sub    cx,cx            ;
  774. ps2:    lodsb                ;
  775.     cmp    al,stopper        ; ending hex ff?
  776.     je    ps8            ;
  777.     inc    cx            ; incr text length
  778.     cmp    al,lf            ; another line?
  779.     jne    ps2            ;
  780.     inc    linecnt         ;
  781.     jmp    ps2            ;
  782.  
  783. ps8:    mov    ah,40h            ; write to file
  784.     mov    bx,1            ; using std out
  785.     int    21h            ;
  786.  
  787. ps9:    restore <cx,bx,si>        ; recover registers
  788.     ret                ;
  789. prints    endp
  790.  
  791.     page
  792. ;
  793. ;    format the time
  794.  
  795. time    record    hour:5,min:6,sec:5    ; packed time
  796.  
  797. gettime proc    near            ; format the date
  798.     mov    di,offset vtime     ;
  799.     push    ax            ; save date
  800.     and    ax,mask hour        ; get hour part
  801.     mov    cl,hour         ; bits to shift
  802.     shr    ax,cl            ;
  803.     call    cnvrt1            ;
  804.     stosw                ;
  805.     mov    al,':'                  ;
  806.     stosb                ;
  807.  
  808. gt3:    pop    ax            ; get the time back
  809.     and    ax,mask min        ; get min part
  810.     mov    cl,min            ; bits to shift
  811.     call    cnvrt            ;
  812.     stosw                ;
  813. gottime:ret                ;
  814. gettime endp
  815.  
  816. cnvrt    proc    near            ; convert to ascii
  817.     shr    ax,cl            ;
  818. cnvrt1: aam                ; make al into bcd
  819.     or    ax,'00'                 ; and to ascii
  820.     xchg    al,ah            ;
  821. cnvrtd: ret                ;
  822. cnvrt    endp
  823.  
  824.     page
  825. ;
  826. ;    format the date
  827.  
  828. date    record    yr:7,mo:4,dy:5        ; packed date
  829.  
  830. getdate proc    near            ; format the date
  831.     push    bx            ; save cd pointer
  832.     or    ax,ax            ; is it zero?
  833.     jz    gotdate         ;
  834.     push    ax            ; save date
  835.     and    ax,mask yr        ; get year part
  836.     mov    cl,yr            ; bits to shift
  837.     call    cnvrt            ;
  838.     mov    di,offset vyear     ;
  839.     or    al,'8'                  ; adjust for base year
  840.     stosw                ;
  841.  
  842.     pop    bx            ; get the date back
  843.     push    bx            ; save it
  844.     and    bx,mask mo        ; get month part
  845.     mov    cl,mo            ; bits to shift
  846.     shr    bx,cl            ;
  847.     add    bx,bx            ; form month table index
  848.     add    bx,bx            ;
  849.     lea    si,word ptr months-4[bx];
  850.     mov    cx,3            ;
  851.     mov    di,offset vmonth    ;
  852.     rep    movsb            ;
  853.  
  854.     pop    ax            ; get the date back
  855.     and    ax,mask dy        ; get day part
  856.     mov    cl,dy            ; bits to shift
  857.     call    cnvrt            ;
  858.     mov    di,offset vdate     ;
  859.     stosw                ;
  860. gotdate:                ;
  861.     pop    bx            ; restore cd pointer
  862.     ret                ; back to caller
  863. getdate endp
  864.  
  865.     page
  866. ;
  867. ;     format 4-byte binary into ASCII for display
  868.  
  869. ddptr    dw    0            ;
  870.  
  871. format    proc    near            ; formats a 32 bit integer in dx:ax
  872.     save    <bp,bx,di,si>        ;  to ds:si
  873.     mov    ddptr,si        ; addr of target field
  874.     mov    di,dx            ; routine uses di:si
  875.     mov    si,ax            ;
  876.     call    printdd         ;
  877.     restore <si,di,bx,bp>        ;
  878.     ret                ;
  879.  
  880. printdd:
  881.     xor    ax,ax            ; zero out the
  882.     mov    bx,ax            ; working
  883.     mov    bp,ax            ; registers.
  884.     mov    cx,32            ; # bits of precision
  885. j1:    shl    si,1            ;
  886.     rcl    di,1            ;
  887.     xchg    bp,ax            ;
  888.     call    j6            ;
  889.     xchg    bp,ax            ;
  890.     xchg    bx,ax            ;
  891.     call    j6            ;
  892.     xchg    bx,ax            ;
  893.     adc    al,0            ;
  894.     loop    j1            ;
  895.     mov    cx,1710h        ;
  896.     mov    ax,bx            ;
  897.     call    j2            ;
  898.     mov    ax,bp            ;
  899. j2:    push    ax            ;
  900.     mov    dl,ah            ;
  901.     call    j3            ;
  902.     pop    dx            ;
  903. j3:    mov    dh,dl            ;
  904.     shr    dl,1            ; move high
  905.     shr    dl,1            ;  nibble to
  906.     shr    dl,1            ;   the low
  907.     shr    dl,1            ;    position
  908.     call    j4            ;
  909.     mov    dl,dh            ;
  910. j4:    and    dl,0fh            ; mask low nibble
  911.     jz    j5            ; if not zero
  912.     mov    cl,0            ;
  913. j5:    dec    ch            ;
  914.     and    cl,ch            ;
  915.     or    dl,'0'                  ; fold in ascii zero
  916.     sub    dl,cl            ;
  917.     mov    bx,ddptr        ;
  918.     mov    [bx],dl         ; ptr to next target field
  919.     inc    ddptr            ;
  920.     ret                ;
  921.  
  922. j6:    adc    al,al            ;
  923.     daa                ;
  924.     xchg    al,ah            ;
  925.     adc    al,al            ;
  926.     daa                ;
  927.     xchg    al,ah            ;
  928.     ret                ;
  929. format    endp
  930.  
  931.     page
  932. ;
  933. ;    convert binary word to two hex characters
  934.  
  935. hexchar db    '0123456789ABCDEF'      ; for conversion
  936.  
  937. cvh    proc    near            ; convert 16-bit binary word in ax
  938.     save    <bx,cx,dx>        ; to hex ASCII string at ds:di
  939.     sub    bx,bx            ;
  940.     mov    dx,ax            ; save 16-bits
  941.  
  942.     mov    bl,dh            ; third nibble
  943.     mov    cl,4            ;
  944.     shr    bl,cl            ;
  945.     mov    al,hexchar[bx]        ;
  946.     stosb                ;
  947.  
  948.     mov    bl,dh            ; last nibble
  949.     and    bl,0fh            ;
  950.     mov    al,hexchar[bx]        ;
  951.     stosb                ;
  952.  
  953.     mov    bl,dl            ; first nibble
  954.     mov    cl,4            ;
  955.     sub    bh,bh            ;
  956.     shr    bl,cl            ; isolate
  957.     mov    al,hexchar[bx]        ;
  958.     stosb                ;
  959.  
  960.     mov    bl,dl            ; second nibble
  961.     and    bl,0fh            ; isolate
  962.     mov    al,hexchar[bx]        ;
  963.     stosb                ;
  964.     restore <dx,cx,bx>        ; restore registers
  965.     ret                ; return
  966.  
  967. cvh    endp
  968.  
  969.     subttl    --- Errors and exits
  970.     page
  971. ;
  972. ;    error messages and exits
  973.  
  974. errmsg    db    cr,lf,"ERROR! ",bel,stopper
  975. errmsg1 db    "Unable to open ",stopper
  976. errmsg2 db    "Reading central end directory: ",stopper
  977. errmsg3 db    "Central end directory incomplete: ",stopper
  978. errmsg4 db    "Reading central directory: ",stopper
  979. errmsg5 db    "Central directory incomplete: ",stopper
  980.  
  981. open_err1:
  982.     mov    dx,offset errmsg1    ; display message
  983.     jmp    zipv_error        ;   and quit
  984.  
  985. open_err2:
  986.     mov    dx,offset errmsg2    ; display message
  987.     jmp    zipv_error        ;   and quit
  988.  
  989. open_err3:
  990.     mov    dx,offset errmsg3    ; display message
  991.     jmp    zipv_error        ;   and quit
  992.  
  993. open_err4:
  994.     mov    dx,offset errmsg4    ; display message
  995.     jmp    zipv_error        ;   and quit
  996.  
  997. open_err5:
  998.     mov    dx,offset errmsg5    ; display message
  999.     jmp    zipv_error        ;   and quit
  1000.  
  1001. nofiles:
  1002.     printl    'No file(s) found '     ; display message
  1003.     mov    errlvl,2        ; set return code
  1004.     jmp    zipv_exit        ;   and quit
  1005.  
  1006. badver:
  1007.     printl    "DOS 2.0 or later is required."
  1008.     mov    errlvl,1        ; set return code
  1009.     jmp    zipv_exit        ;   and quit
  1010.  
  1011. zipv_error:
  1012.     mov    sp,cs:stkptr        ; insure stack pointer
  1013.     mov    errlvl,3        ; return error code
  1014.     push    dx            ;
  1015.     print    errmsg            ; make some noise
  1016.     pop    dx            ;
  1017.     call    prints            ; display error message
  1018.     print    filenm            ;  with file name
  1019.     cmp    flags,255        ; processed any files?
  1020.     jne    getnext         ; yes, try some more
  1021.  
  1022. zipv_exit:
  1023.     mov    sp,cs:stkptr        ; insure stack pointer
  1024.     mov    al,errlvl        ; get error level
  1025.     mov    ah,4ch            ; exit
  1026.     int    21h            ;
  1027.  
  1028.     subttl    --- data areas
  1029.     page
  1030.  
  1031. filenm    equ    $            ; command line filespec supplied
  1032.  
  1033. dta    equ    filenm+80        ; dos data transfer area
  1034.  
  1035. cde    equ    dta+48            ; central directory end record
  1036.                     ; with room for 8k of comments
  1037. cdir    equ    cde+(size central_end)+(8*1024) ; central directory
  1038.  
  1039. stk    equ    cdir+ (52*1024)     ; and what's left as room for comments
  1040.  
  1041. stk_end equ    stk+256         ; local stack
  1042.  
  1043. paras    equ    (stk_end+256-cseg)/16    ; paragraphs in module
  1044.  
  1045. zipv    endp
  1046.     end    zipv
  1047.