home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / QBAS / QBARCV3.ZIP / QBARCV3.ASM next >
Assembly Source File  |  1989-03-21  |  31KB  |  1,250 lines

  1.     page    74,132
  2.     title    ARCV - Verbose ARC directory listing
  3.  
  4. ;    Special version of ARCV to be called by QB program
  5. ; usage:
  6. ;
  7. ;    CALL ARCV (Workname$,"filename[.PAK]", RETCD%)             ' CPC151AC
  8. ;
  9. ; notes:
  10. ;    This code originated from ARCV 1.15d - Verbose ARC directory display
  11. ;    written by V.Buerg and was modified to run as a called routine under
  12. ;    Microsoft QuickBasic. It was further modified to allow PAK files by
  13. ;    Robert J. Simoneau.
  14. ;
  15. ;    Change 9/14/86 to dis-allow wildcards
  16. ;    Change 1/1/87 to recognize squash format
  17. ;    Change 2/18/87 to support network usage - - - - Jon Martin   ' CPC151A
  18. ;    Change 1/7/89 to support Pak files -------------Bob Simoneau
  19. ;    Change 890320 to support ZIP files    David Kirschbaum, Toad Hall
  20. ;    - Question:  Why do we "have to look for the damned thing" when it
  21. ;      comes to finding ARC/PAK headers?  All comments are at file ends,
  22. ;      so the header should be EXACTLY where it should be .. at the end of
  23. ;      the file's compressed code.  Hacked severely to reflect this,
  24. ;      and vastly cleaning up the code.
  25. ;    - Replaced old SDIR Binary to Ascii conversion with a hacked version
  26. ;      from JMODEM .. about 10 times faster, plus offers integer conversion
  27. ;      as well as long integers.
  28.  
  29.  
  30. STDOUT    equ    1            ;Standard Output        v1.3
  31. STDERR    equ    2            ;Std Error (console)        v1.3
  32.  
  33. Print    macro    name            ; display a field
  34.     mov    dx,offset name
  35.     call    PrintS
  36.     endm
  37.  
  38. header  struc                ; archive header
  39. mbrflag    db    1AH            ;unique ARC/PAK flag        v1.3
  40. mbrcode db    0            ;  compression code
  41. mbrname db    13 dup (0)        ;  file name
  42. mbrsize dw    0,0            ;  file size in archive
  43. mbrdate dw    0            ;  creation date
  44. mbrtime dw    0            ;  creation time
  45. mbrcrc  dw    0            ;  cyclic redundancy check
  46. mbrlen  dw    0,0            ;  true file size, bytes
  47. header  ends
  48. ARCHDRLEN    equ    29        ;size of ARC/PAK header.    v1.3
  49.  
  50. ;v1.3    ZIP Local file header structure:
  51.  
  52. zLocalEntry    STRUC
  53.   
  54. zdig0    db    50H,4BH,03H,04H    ;local file header signature    4 bytes
  55.                 ;(0x04034b50)
  56. zVerMade    dw    ?    ;version needed to extract    2 bytes
  57. zBitflag    dw    ?    ;general purpose bit flag    2 bytes
  58. zCmpMeth    dw    ?    ;compression method        2 bytes
  59. zModTime    dw    ?    ;last mod file time         2 bytes
  60. zModDate    dw    ?    ;last mod file date        2 bytes
  61. zCrc32        dw    ?,?    ;crc-32               4 bytes
  62. zCmpSiz        dw    ?,?    ;compressed size        4 bytes
  63. zUncmpSiz    dw    ?,?    ;uncompressed size        4 bytes
  64. zNameLen    dw    ?    ;filename length        2 bytes
  65. zExtraLen    dw    ?    ;extra field length        2 bytes
  66. zFilename    db    ?    ;filename (variable size)
  67.                 ;extra field (variable size)
  68. ZLocalEntry    ENDS
  69.  
  70. ZIPHDRLEN    equ    30        ;length of initial ZIP hdr read    v1.3
  71.  
  72.  
  73.  
  74. CSEG    segment public para 'CODE'
  75.     assume    CS:CSEG,DS:CSEG,ES:CSEG
  76.  
  77.     public  ArcV
  78.  
  79. ArcV    proc    far
  80.  
  81.     push    bp            ; save BASIC reg
  82.     mov    bp,sp            ; get parameter list pointer
  83.     mov    CS:stkptr,sp        ; save stack ptr
  84.     mov    CS:saveds,DS        ; save QB seg reg
  85.     mov    CS:savees,ES        ; save QB seg reg
  86.     call    Start            ; do our thing            v1.3
  87.  
  88. ;    set DOS error level and exit
  89.  
  90. Exit:    mov    sp,stkptr        ; restore entry stack value
  91.  
  92.     push    ax            ;save error value        v1.3
  93.  
  94. ;v1.3    Numerous errors could be returned
  95.  
  96.     jnb    Exit_NoErr        ;ok, no errors
  97.     xor    bx,bx            ;'Usage:...'
  98.     cmp    al,1            ;command line parm error
  99.     jz    Exit_ErrOut        ;yep
  100.     inc    bl            ;'Archive file not found'
  101.     cmp    al,6            ;2..6 are file-related errors
  102.     jz    Exit_ErrOut        ;yep
  103.     inc    bl            ;'Archive header error'
  104.     cmp    al,0BH
  105.     jz    Exit_ErrOut        ;yep
  106.     inc    bl            ;'Archive format error'
  107.     cmp    al,0EH
  108.     jz    Exit_ErrOut        ;yep
  109.     inc    bl            ;'Unknown error'
  110. Exit_ErrOut:
  111.     shl    bx,1            ;*2 for words
  112.     add    bx,offset errtbl    ;table of addresses
  113.     mov    dx,[bx]            ;ptr to string
  114.     call    PrintS            ;output error msg
  115.         
  116. Exit_NoErr:
  117.  
  118.     mov    bx,word ptr outhdl    ; close listing file
  119.     cmp    bl,STDERR        ;never opened or STDERR?    v1.3
  120.     jna    Exit1            ;not a real handle        v1.3
  121.      mov    ah,3eh            ;close file handle
  122.      int    21h
  123. Exit1:
  124.     mov    bx,word ptr archdl    ;close ARC/PAK/ZIP file        v1.3
  125.     or    bx,bx            ; if it was opened        v1.3
  126.     jz    Exit2            ; nope                v1.3
  127.      mov    ah,3EH            ;close file handle        v1.3
  128.      int    21H            ;                v1.3
  129. Exit2:                    ;                v1.3
  130.  
  131. ;v1.3    Adding a test to insure we switched DTAs
  132. ;    (so we don't blow away the caller's DTA with a vector 0:0!)
  133.  
  134.     lds    dx,dword ptr savedta    ;get orig DTA vector
  135.     or    dx,dx            ;did we ever get it?
  136.     jz    Exit_NoDTA        ;nope
  137.     mov    ax,DS            ;check out seg
  138.     or    ax,ax
  139.     jz    Exit_NoDTA        ;nope
  140.      mov    ah,1ah            ;set DTA
  141.      int    21h
  142. Exit_NoDTA:
  143.  
  144.     lds    ax,dword ptr CS:saveds    ;recover calling seg regs    v1.3
  145.                     ;(low word is orig ES)        v1.3
  146.     mov    ES,ax
  147.     ASSUME    DS:NOTHING,ES:NOTHING    ;a reminder
  148.  
  149.     pop    ax            ;restore error level        v1.3
  150.     cbw
  151.     mov    bp,sp            ; parm ptr from entry
  152.     mov    6[bp],ax        ;return retcd variable        v1.3
  153.     pop    bp
  154.     ret    6            ; clear parms from stack     ' CPC151A
  155.  
  156.     subttl    '--- constants, equates and work areas'
  157.     page
  158.  
  159. CR    equ    13
  160. LF    equ    10
  161. BEL    equ    7
  162. TAB    equ    9
  163.  
  164. STOPPER equ    0        ; end of display line indicator
  165. ARCMARK equ    26        ; special archive marker
  166. ARCVER  equ    10        ; highest compression code used
  167.  
  168. stkptr  dw    0        ; stack pointer upon entry
  169.  
  170. arctitl db    CR,LF,'Archive:  '
  171. saveds  dw    0        ; QB seg reg
  172. savees  dw    0        ; QB seg reg
  173.  
  174.     subttl    '--- i/o control variables'
  175.     page
  176.  
  177. INBUFSZ equ    128    ;512    ; size of input buffer            v1.3
  178.  
  179. ;v1.3    Completely reordered these runtime variables
  180. ;    so we can purge them with one fell swoop
  181.  
  182. PURGESTART    equ    $    ;                    v1.3
  183.  
  184. inptr    dw    0        ; offset to current byte
  185. inlen    dw    0        ; bytes left in buffer
  186. incurh  dw    0        ; current file offset
  187. incurl  dw    0        ;  low word
  188.  
  189. totsf    dw    0,0        ; average stowage factor
  190. totlen  dw    0,0        ; total of file lengths
  191. totsize dw    0,0        ; total of file sizes
  192. totmbrs dw    0        ; total number of files
  193.  
  194. archdl  dw    0        ; file handle
  195. fileptr dw    0        ; ptr to filename part of arcname
  196. arclen    dw    0        ;full archive filename length        v1.3
  197. arcname db    76 dup (0)
  198.  
  199. outhdl  dw    0        ; handle for output listing        v1.3
  200. templen    dw    0        ;output filename length            v1.3
  201. temp    db    76 dup (0)    ; and temporary file name
  202.  
  203. savedta dw    0,0        ; addr of QB dta
  204. dta    db    48 dup (0)    ; data transfer area
  205.  
  206.     even            ;                    v1.3
  207.  
  208. PURGELEN    EQU    ($ - PURGESTART) SHR 1    ;amount to purge each run v1.3
  209.  
  210. usage    db    CR,LF
  211.  db 'QBARCV3 - Verbose ARC/PAK/ZIP directory display for QuickBasic'    ;v1.3
  212.  db CR,LF,LF,'  Usage:  call arcv (workname$,filename.[ARC][PAK][ZIP],'    ;v1.3
  213.  db 'result%',CR,LF,STOPPER                        ;v1.3
  214.  
  215. ;    display lines for verbose
  216.  
  217. vhdr    db    CR,LF
  218.  db CR,LF,'Name          Length    Stowage    SF   Size now  Date       Time    CRC '
  219.  db CR,LF,'============  ========  ========  ====  ========  =========  ======  ===='
  220.  db STOPPER
  221.  
  222. vline    db    CR,LF
  223. vname    db    14 dup (' ')
  224. vlength db    '          '    ; length in archive            v1.3
  225. vstyle  db    '          '    ; compression method
  226. vfactor db    ' xx%  '    ; compression factor
  227. vsize    db    10 dup (' ')    ; actual file bytes
  228. vdate    db    'dd '        ; creation date
  229.  vmonth db    'mmm '
  230.  vyear  db    'yy  '
  231.  vtime  db    'hh:mm   '    ; creation time
  232.  vcrc    db    'xxxx'        ; crc in hex
  233.     db    STOPPER
  234.  
  235. hundred dw    100        ; for computing percentages
  236.  
  237. ;    final totals line
  238.  
  239. vthdr    db    CR,LF,LF,'*Total    ' ;                   ' CPC151A
  240.  vtmbrs db    '    '
  241.  vtlen  db    8 dup (' '),'  '
  242.     db    10 dup (' ')
  243.  vtsf    db    '   %  '
  244.  vtsize db    8 dup (' ')
  245.     db    CR,LF        ; for tom
  246.     db    STOPPER
  247.  sign    db    ' '
  248.  
  249. styles  db    '  ----- '    ; 1 = old, no compression
  250.     db    '  ----- '    ; 2 = new, no compression
  251.     db    ' Packed '    ; 3 = dle for repeat chars
  252.     db    'Squeezed'    ; 4 = huffman encoding
  253.     db    'crunched'    ; 5 = lz, no dle
  254.     db    'crunched'    ; 6 = lz with dle
  255.     db    'Crunched'    ; 7 = lz with readjust
  256.     db    'Crunched'    ; 8 = lz with readjust and dle
  257.     db    'Squashed'    ; 9 = 13-bit lz with no dle
  258.     db    ' Crushed'    ;10 = Pak10 file ---------Bob Simoneau
  259.  
  260. ;v1.3    ZIP compression types:
  261.  
  262. zstyles    label    byte
  263.     db    '  Stored'    ;0 - The file is stored (no compression)
  264.     db    '  Shrunk'    ;1 - The file is Shrunk
  265.     db    'Reduced1'    ;2 - Reduced with compression factor 1
  266.     db    'Reduced2'    ;3 - Reduced with compression factor 2
  267.     db    'Reduced3'    ;4 - Reduced with compression factor 3
  268.     db    'Reduced4'    ;5 - Reduced with compression factor 4
  269.  
  270. months  db    'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
  271.  
  272. ARCPAK    =    0            ;                v1.3
  273. ZIP    =    0FFH            ;                v1.3
  274. ftype    db    ARCPAK            ;flag which type file        v1.3
  275.  
  276. arctype    db    'ARC'            ;3 types of archive file    v1.3
  277. paktype    db    'PAK'
  278. ziptype    db    'ZIP'
  279.  
  280. zfilesig db    50H,4BH,03H,04H        ;local file header signature    v1.3
  281. zdirsig    db    50H,4BH,01H,02H        ;central file header signature    v1.3
  282.  
  283. ;v1.3    Centralizing errors at the exit point
  284.  
  285. errtbl    dw    usage,msg1,msg2,msg3,msg4    ;error msg ptrs
  286.  
  287. msg1    db    'Archive file not found',0
  288. msg2    db    'Archive header error',0
  289. msg3    db    'Archive format error',0
  290. msg4    db    'Unknown error',0
  291.  
  292.  
  293.     subttl    '--- mainline processing'
  294.     page
  295. ;
  296. Start    proc    near            ;                v1.3
  297.  
  298.     mov    ax,CS            ;just set ES for now        v1.3
  299.     mov    ES,ax
  300.     ASSUME    ES:CSEG            ;a reminder            v1.3
  301.  
  302. ;v1.3    Insure all variables are cleared
  303.     cld
  304.     mov    di,offset PURGESTART
  305.     xor    ax,ax            ;clear all the variables    v1.3
  306.     mov    cx,PURGELEN        ;nr words to clear        v1.3
  307.     rep    stosw            ;                v1.3
  308.  
  309. ;v1.3    Move first parameter (output filename) into code space
  310.  
  311.     mov    si,word ptr 10[bp]    ; ptr to parameter vector    ' CPC151A
  312.     lodsw                ; get string length         ' CPC151A
  313.     mov    cx,ax            ;                 ' CPC151A
  314.     jcxz    Copy_Parm2        ;empty, forget it        v1.3
  315.      mov    di,offset templen    ;str length            v1.3
  316.      stosw                ;save length            v1.3
  317.      mov    si,word ptr [si]    ; get string offset         ' CPC151A
  318.      rep    movsb            ;copy in the string        v1.3
  319.  
  320. Copy_Parm2:
  321.  
  322. ;v1.3    Now copy 2d parameter (target archive filename)
  323.  
  324.     mov    si,word ptr 8[bp]    ; ptr to parameter vector
  325.     lodsw                ; get string length
  326.     mov    cx,ax            ;                v1.3
  327.     jcxz    Parm2_Done        ;forget it            v1.3
  328.      mov    di,offset arclen    ;archive name length        v1.3
  329.      stosw                ;save length            v1.3
  330.      mov    si,word ptr [si]    ; get string offset        v1.3
  331.      mov    ah,'a'            ;constant for uppercasing    v1.3
  332. Parm2_Upper:                ;                v1.3
  333.      lodsb                ;snarf char            v1.3
  334.      cmp    al,ah            ;need uppercasing?        v1.3
  335.      jb    Parm2_NoU        ;nope                v1.3
  336.       sub    al,20H            ;uppercase it            v1.3
  337. Parm2_NoU:                ;                v1.3
  338.      stosb                ;                v1.3
  339.      loop    Parm2_Upper        ;                v1.3
  340.  
  341. Parm2_Done:
  342.  
  343. ;v1.3    All done with DS
  344.  
  345.     mov    ax,CS            ;                v1.3
  346.     mov    DS,ax            ;                v1.3
  347.     ASSUME    DS:CSEG            ;a reminder            v1.3
  348.  
  349.     cmp    temp,0            ;any output filename?        v1.3
  350.     jnz    Got_Temp        ;yep                v1.3
  351.  
  352. ;v1.3    Forcing output file to STDERR for debugging.
  353. ;v1.3     mov    al,1            ; will show usage        v1.3
  354. ;v1.3     ret                ;back to Exit            v1.3
  355.  
  356.      mov    ax,STDERR        ;force to STDERR        v1.3
  357.      jmp    short Temp_Opened    ;continue            v1.3
  358.  
  359. Got_Temp:
  360.     mov    dx,offset temp        ; open temporary file for output
  361.     xor    cx,cx            ;no special attributes        v1.3
  362.     mov    ah,3ch            ;create file
  363.     int    21h
  364.     jnb    Temp_Opened        ;fine                v1.3
  365.      ret                ;back to Exit, AL=error code    v1.3
  366.  
  367. Temp_Opened:
  368.     mov    outhdl,ax        ;save handle
  369.  
  370. ;v1.3    Parse the target archive name
  371. ;    Separate path from name
  372. ;    Insure it's an ARC, PAK or ZIP type.
  373.  
  374.  
  375.     mov    di,offset arclen    ;archive name length        v1.3
  376.     lodsw                ;snarf length, bump to name    v1.3
  377.     mov    dx,ax            ;save in DX for later        v1.3
  378.     xor    al,al            ;will scan for AsciiZ terminator v1.3
  379.     cmp    [di],al            ;no name at all?        v1.3
  380.     jnz    Got_TgtName        ;yep                v1.3
  381.      mov    al,2            ;'file not found'        v1.3
  382.      ret                ;back to Exit            v1.3
  383.  
  384. Got_TgtName:
  385.  
  386. ;v1.3    We have some sort of target name.
  387. ;    But is it a legal type?
  388. ;    DX = filename length
  389. ;    DI -> archive filename (arcname)
  390.  
  391.     add    di,dx            ;+ length -> last char+1    v1.3
  392.     dec    di            ;back up to last char        v1.3
  393.     mov    bx,di            ;BX -> last char        v1.3
  394.  
  395.     mov    al,'\'            ;look for normal path delimiter    v1.3
  396.     mov    cx,dx            ;length for scan        v1.3
  397.     std                ;backwards scanning now        v1.3
  398.     repne    scasb            ;                v1.3
  399.     jz    Got_Start        ;found one            v1.3
  400.  
  401. ;Ugh .. tired of typing in v1.3's!
  402.  
  403.     mov    di,bx            ;back to end
  404.     mov    cx,dx            ;restore length
  405.     mov    al,'/'            ;funny path delimiter
  406.     repne    scasb
  407.     jz    Got_Start        ;found one
  408.  
  409.     mov    di,bx            ;back to end .. sigh ..
  410.     mov    cx,dx            ;restore length
  411.     mov    al,':'            ;ok, how about a drive?
  412.     repne    scasb
  413.  
  414. Got_Start:
  415.     inc    di            ;adjust DI from last scasb
  416.     cld                ;forward again
  417.     mov    fileptr,di        ;remember real filename start
  418.  
  419. ;v1.3    You MUST specify the type .. .ARC, .PAK, or .ZIP.
  420. ;    If .ARC or .PAK, we'll use the old code to display ARC-type
  421. ;    files.
  422. ;    Else if ZIP, it's a totally new format!
  423. ;    We remember the type archiving format in 'ftype'.
  424.  
  425. ;v1.3    DS:SI -> filename's first char.
  426.  
  427.     mov    al,'.'            ;find the separator        v1.3
  428.     mov    cx,word ptr 12        ;max of 12 chars        v1.3
  429.     repne    scasb            ;find it            v1.3
  430.     jnz    BadType            ;forget it            v1.3
  431.  
  432. Parm3:
  433.     mov    dx,di            ;save pointer to file type    v1.3
  434.                     ;(just past the separator)    v1.3
  435.     mov    si,offset arctype    ;is it an ARC?            v1.3
  436.     mov    ax,3            ;3 chars constant
  437.     mov    cx,ax            ;3 chars
  438.     repz    cmpsb            ;compare
  439.     jz    Got_Type        ;a match
  440.  
  441.     mov    si,offset paktype    ;is it a PAK?
  442.     mov    di,dx            ;back to filename type
  443.     mov    cx,ax            ;3 chars
  444.     repz    cmpsb            ;compare
  445.     jz    Got_Type        ;a match
  446.  
  447.     mov    ftype,ZIP        ;assume ZIP
  448.     mov    si,offset ziptype    ;is it a ZIP?
  449.     mov    di,dx            ;back to filename type
  450.     mov    cx,ax            ;3 chars
  451.     repz    cmpsb            ;compare
  452.     jz    Got_Type        ;a match
  453.  
  454. BadType:
  455.      mov    al,1            ;prints usage            v1.3
  456.      ret                ;back to Exit            v1.3
  457.  
  458. Got_Type:                ;v1.3
  459.  
  460. ;    find first matching file
  461.  
  462.     push    ES
  463.     mov    ah,2fh            ; get current dta ptr
  464.     int    21h            ; returned in ES:bx
  465.     mov    savedta,ES
  466.     mov    savedta[2],bx
  467.     pop    ES
  468.  
  469.     mov    dx,offset dta        ; set local dta for murkers
  470.     mov    ah,1ah
  471.     int    21h
  472.  
  473.     call    OpenArc            ; see if archive exists
  474.     jb    ArcV_X            ;nope, return, AL = error    v1.3
  475.  
  476. ;    process next archive header entry
  477.  
  478. ; ArcV1:  Print   arctitl   ' removed for security reasons in CPC16-1A
  479.  
  480. ArcV1:  Print    vhdr
  481.     jb    ArcV_X            ;output failed            v1.3
  482.  
  483. ArcVNext:
  484.     call    GetHdr            ; load next header
  485.     jb    ArcV_NoHdr        ;failed somehow            v1.3
  486.  
  487.     call    ArcVgo            ;format, write out file report
  488.     jb    Arcv_NoHdr        ;something failed        v1.3
  489.     call    Bump_ArcPtrs        ;bump to next archive file    v1.3
  490.     jnb    ArcVNext        ;loop if ok            v1.3
  491.  
  492.  
  493. ArcV_NoHdr:
  494.     cmp    archdr.mbrcode,0    ; archive eof?
  495.     jnz    ArcV_X            ;nope, something else happened    v1.3
  496.  
  497.     cmp    totmbrs,0        ;any totals?            v1.3
  498.     jz    ArcV_X            ;nope                v1.3
  499.      push    ax            ;save previous error value    v1.3
  500.      call    Format_Totals        ;yep, format and output        v1.3
  501.      pop    ax            ;restore prev err value        v1.3
  502.  
  503. ArcV_X:    ret                ;                v1.3
  504.  
  505. Start    endp                ;                v1.3
  506.  
  507.  
  508. ;v1.3    Format, display single line for each member
  509. ;    Returns CF set if failure (because of output write fail)
  510.  
  511. ArcVgo    proc    near
  512.     mov    di,offset vname        ; copy file name
  513.     mov    si,offset archdr.mbrname
  514.     mov    cx,word ptr 13
  515. ArcV3:
  516.     lodsb
  517.     or    al,al            ; end of name?            v1.3
  518.     je    ArcV4
  519.      stosb
  520.      loop    ArcV3
  521.      jmp    short ArcV5
  522.  
  523. ArcV4:
  524.     mov    al,' '            ; pad with blanks
  525.     rep    stosb
  526. ArcV5:
  527. ; reduce the size/length to word values
  528.  
  529.     mov    bx,archdr.mbrlen    ; get actual file size
  530.     mov    ax,archdr.mbrlen[2]
  531.  
  532.     mov    cx,archdr.mbrsize    ; length of file in archive
  533.     mov    dx,archdr.mbrsize[2]
  534.  
  535. ArcV51: or    ax,ax            ; big number?
  536.     jz    ArcV52            ; nope, can use it
  537.      shr    ax,1            ; yup, divide by two
  538.      rcr    bx,1
  539.      shr    dx,1
  540.      rcr    cx,1
  541.      jmp    short ArcV51
  542.  
  543. ArcV52:
  544. ;v1.5    mov    si,offset vfactor-5    ; format stowage factor
  545.     mov    ax,bx            ; low word of actual size
  546.     mov    sign,' '
  547.     cmp    ax,cx            ; arc member is larger?
  548.     jb    ArcV520
  549.      sub    ax,cx            ; amount saved
  550.      jmp    short ArcV56
  551.  
  552. ArcV520:
  553.     sub    ax,cx
  554.     neg    ax
  555.     mov    sign,'-'
  556.  
  557. ArcV56:
  558.     mul    hundred            ; to percentage
  559.     add    ax,50
  560.     adc    dx,0            ; round up percent
  561.     or    bx,bx            ; empty file?
  562.     jnz    ArcV53
  563.      mov    ax,100
  564.      jmp    short ArcV54
  565.  
  566. ArcV53: div    bx
  567. ArcV54:
  568. ;v1.3    sub    dx,dx
  569.     cmp    ax,100            ; archive fouled?
  570.     jbe    ArcV55
  571.      sub    ax,ax
  572. ArcV55:
  573.     mov    di,offset vfactor-2    ;format stowage factor        v1.3
  574.     call    Asciify            ;display AX
  575.  
  576.     mov    al,sign
  577.     mov    vfactor,al
  578.  
  579.     mov    si,offset zstyles    ;assume ZIP            v1.3
  580.     cmp    ftype,ZIP        ;ZIP file?            v1.3
  581.     jz    ArcV55A            ;yep                v1.3
  582.      mov    si,offset styles    ;ARC or PAK            v1.3
  583. ArcV55A:                ;                v1.3
  584.  
  585.     sub    bx,bx            ; determine style
  586.     mov    bl,archdr.mbrcode
  587.     dec    bl            ;adjust for table offset    v1.3
  588.     mov    cl,3            ; eight bytes each entry
  589.     shl    bx,cl
  590.  
  591.     add    si,bx            ;point into style table        v1.3
  592.     mov    di,offset vstyle
  593.     mov    cx,word ptr 4        ;move as words (8 bytes)    v1.3
  594.     rep    movsw            ;                v1.3
  595.  
  596.     mov    dx,archdr.mbrsize[2]
  597.     mov    ax,archdr.mbrsize
  598.     add    totsize,ax
  599.     adc    totsize[2],dx
  600.     mov    di,offset vsize        ;format file size        v1.3
  601.     call    Asciify_Long        ;                v1.3
  602.  
  603. ;v1.3    mov    si,offset vlength    ; format file length
  604.     mov    dx,archdr.mbrlen[2]
  605.     mov    ax,archdr.mbrlen
  606.     add    totlen,ax
  607.     adc    totlen[2],dx
  608.     mov    di,offset vlength    ;format file length        v1.3
  609.     call    Asciify_Long        ;                v1.3
  610.  
  611.     mov    ax,archdr.mbrdate    ; format file date
  612.     call    GetDate
  613.  
  614.     mov    ax,archdr.mbrtime    ; format file time
  615.     call    GetTime
  616.  
  617.     mov    ax,archdr.mbrcrc    ; format crc in hex
  618.     mov    di,offset vcrc
  619.     call    Cvh
  620.  
  621.     Print    vline            ; display this file info
  622.     inc    totmbrs            ;NOW bump total count        v1.3
  623.     ret
  624.  
  625. ArcVgo    endp
  626.  
  627.  
  628.     subttl    '--- load next archive header'
  629.     page
  630.  
  631. ;v1.3    Adding ZIP file searching
  632.  
  633. GetHdr  proc    near
  634.  
  635.     cmp    ftype,ZIP        ;doing ZIP files?        v1.3
  636.     jz    Get_ZipHdr        ;yep, find a zip header        v1.3
  637.  
  638. ;v1.3    New code
  639. Comment    ~    ARC/PAK headers look like this:
  640. mbrflag    db    1AH            ;unique header flag
  641. mbrcode db    0            ;  compression code
  642. mbrname db    13 dup (0)        ;  file name
  643. mbrsize dw    0,0            ;  file size in archive
  644. mbrdate dw    0            ;  creation date
  645. mbrtime dw    0            ;  creation time
  646. mbrcrc  dw    0            ;  cyclic redundancy check
  647. mbrlen  dw    0,0            ;  true file size, bytes
  648. Comment    ends    ~
  649.  
  650.     mov    dx,offset archdr    ;read into here
  651.     mov    cx,ARCHDRLEN        ;nr bytes to read
  652.     mov    bx,archdl        ;archive file handle
  653.     mov    ah,3FH            ;read from file/device
  654.     int    21H
  655.     jb    Hdr_RetCF        ;read failed, return CF set
  656.  
  657.     mov    bx,dx            ;structure start
  658.     cmp    [bx].mbrflag,ARCMARK    ;start of header?
  659.     jne    Hdr_InvalFmt        ;'invalid format', exit CF set
  660.  
  661.     mov    al,[bx].mbrcode        ;type compression
  662.     cmp    al,ARCVER        ;reasonable code?
  663.     ja    Hdr_InvalFmt        ;nope, funny stuff
  664.  
  665.     or    al,al            ; archive eof?
  666.     je    Hdr_RetCF        ;yep, done, return CF set
  667.  
  668.     cmp    al,1            ; old format?
  669.     jne    GetHdrX            ; if so, it's short
  670.      mov    si,offset archdr.mbrsize            ; CPC15-1C
  671.      mov    di,offset archdr.mbrlen                ; CPC15-1C
  672.      movsw
  673.      movsw
  674. GetHdrX:
  675.     clc
  676.     ret
  677.  
  678. Hdr_InvalFmt:
  679.     mov    al,0BH            ;'invalid format'
  680.     mov    [bx].mbrcode,0        ;signal EOF
  681. Hdr_RetCF:
  682.     stc                ;return CF set
  683.     ret
  684.  
  685.  
  686. Get_ZipHdr:
  687. ;v1.3    Reads in file entry.
  688. ;    Then scans for the unique file entry signature.
  689. ;    On success:
  690. ;     DS:BX -> file entry directory structure
  691. ;     CF clear
  692. ;    Else CF set for failure
  693.  
  694.     mov    archdr.mbrcode,0        ;assume end
  695.     call    Read_Zip_Entry
  696.     jb    Get_ZHdrX            ;failed, AL=ERRORLEVEL
  697.  
  698. ZH_RdOk:
  699.     mov    bx,offset inbuf            ;use for field base
  700.     mov    di,offset archdr.mbrcode    ;moving into this structure
  701.  
  702. ;v1.3    Remember, the record we'll be formatting from
  703. ;    looks like this:
  704. ;mbrflag db    1AH
  705. ;mbrcode db    0            ;  compression code
  706. ;mbrname db    13 dup (0)        ;  file name
  707. ;mbrsize dw    0,0            ;  file size in archive
  708. ;mbrdate dw    0            ;  creation date
  709. ;mbrtime dw    0            ;  creation time
  710. ;mbrcrc  dw    0            ;  cyclic redunancy check
  711. ;mbrlen  dw    0,0            ;  true file size, bytes
  712.  
  713.     mov    ax,[bx].zCmpMeth        ;compression method
  714.     inc    al                ;bump to be non-0
  715.     stosb                    ;->  mbrcode
  716.  
  717. ;For now, assuming a normal file name (no paths)
  718.  
  719.     mov    ax,[bx].zNameLen        ;filename length
  720.     and    ax,15                ;constrain to max 12 chars
  721.     mov    cx,ax                ;into CX for move
  722.     lea    si,[bx].zFileName        ;pointer to actual filename
  723.     rep    movsb                ;do the move
  724.     xor    al,al                ;terminating 0
  725.     stosb
  726.  
  727.     mov    di,offset archdr.mbrsize    ;bump past name
  728.  
  729.     mov    ax,[bx].zCmpSiz            ;compressed size.lo
  730.     stosw                    ; -> mbrsize
  731.     mov    ax,[bx].zCmpSiz[2]        ;compressed size.hi
  732.     stosw                    ; -> mbrsize[2]
  733.     mov    ax,[bx].zModDate        ;last mod date
  734.     stosw                    ; -> mbrdate
  735.     mov    ax,[bx].zModTime        ;last mod time
  736.     stosw                    ; -> mbrtime
  737.     mov    ax,[bx].zCrc32            ;CRC-32 value.lo
  738.     stosw                    ; -> mbrcrc
  739.     mov    ax,[bx].zUncmpSiz        ;uncompressed size.lo
  740.     stosw                    ; -> mbrlen
  741.     mov    ax,[bx].zUncmpSiz[2]        ;uncompressed size.hi
  742.     stosw                    ; -> mbrlen[2]
  743.  
  744.     clc                    ;return CF clear
  745. Get_ZHdrX:
  746.     ret
  747.  
  748. GetHdr    endp
  749.  
  750.  
  751. Read_Zip_Entry    proc    near
  752.  
  753.     mov    bx,archdl            ;file handle
  754.     mov    dx,offset inbuf            ;read into here
  755.     mov    cx,ZIPHDRLEN            ;entry structure size
  756.                         ;(does NOT include filename or
  757.                         ; Extra fields, which are
  758.                         ;dynamic)
  759.     call    ReadZ_It            ;try to read in header
  760.                         ;(up to filename)
  761.     jb    ReadZ_ItX            ;failed, AL=error
  762.  
  763.     mov    si,offset zfilesig        ;expected file signature
  764.     mov    di,dx                ;structure signature
  765.     mov    cx,word ptr 4            ;4 bytes
  766.     repz    cmpsb                ;compare
  767.     jz    ReadZ_Ok1            ;fine, a member signature
  768.      xor    al,al                ;assume 0 error (last entry)
  769.      mov    si,offset zdirsig        ;Central directory signature
  770.      mov    di,dx                ;back to structure signature
  771.      mov    cl,4                ;4 bytes
  772.      repz    cmpsb                ;compare
  773.      jz    ReadZ_Last_Fail            ;yep, last entry, return CF set
  774.      mov    al,0DH                ;force to 'invalid data'
  775.      jmp    short ReadZ_Last_Fail        ;return CF set
  776.  
  777. ReadZ_Ok1:
  778. ;    add    dx,ax                ;move to zFilename psn
  779.     mov    dx,offset inbuf.zFileName    ;move to zFilename psn
  780.     mov    cx,inbuf.zNameLen        ;length of member filename
  781.     call    ReadZ_It            ;read in filename
  782.     jb    ReadZ_ItX            ;failed, AL = ERRORLEVEL
  783.      clc                    ;CF clear for success
  784.      ret
  785.  
  786. ;Common subroutine for ReadZ
  787.  
  788. ReadZ_It:
  789.     mov    ah,3FH                ;read from file/device
  790.     int    21H
  791.     jb    ReadZ_Last_Fail            ;failed, error in AX
  792.      cmp    ax,cx                ;read all we expected?
  793.      mov    al,0BH                ;assume unexpected EOF
  794.                         ;('invalid format')
  795.      jnz    ReadZ_Last_Fail            ;did NOT read it all
  796.       mov    ax,cx                ;return AX=bytes read
  797.       ret                    ;and CF clear
  798.  
  799. ReadZ_Last_Fail:
  800.     stc                    ;return CF set for failure
  801. ReadZ_ItX:
  802.     ret                    ;errorlevel in AL
  803.  
  804. Read_Zip_Entry    endp
  805.  
  806.  
  807. ;v1.3    Common subroutine
  808. ;    Bumps archive file pointers to next entry
  809.  
  810. Bump_ArcPtrs    proc    near
  811.  
  812.     cmp    ftype,ZIP        ;ZIP file?            v1.3
  813.     jz    Next_ZEntry        ;bump file ptr to next entry    v1.3
  814.  
  815. ;v1.3    Entirely new code
  816.  
  817.     mov    cx,archdr.mbrsize[2]    ;pick up encoded file length
  818.     mov    dx,archdr.mbrsize    ; of current file
  819.     jmp    short Bump_Common    ;common code
  820.  
  821.  
  822. ;v1.3    Positions ZIP file pointer to next local entry.
  823. ;    We've already read in the entire header, plus the filename,
  824. ;    so the file pointer should be just beyond the filename
  825. ;    (at the Extra field).
  826. ;    Move file pointers beyond the Extra field, and then past
  827. ;    the actual entry data (the compressed size).
  828.  
  829. Next_ZEntry:
  830.  
  831.     mov    bx,offset inbuf            ;point back to structure
  832.     mov    dx,[bx].zCmpSiz            ;size.lo
  833.     mov    cx,[bx].zCmpSiz[2]        ;size.hi
  834.     add    dx,[bx].zExtraLen        ;add in extra field length
  835.     adc    cx,0                ;in case of carry
  836. Bump_Common:
  837.     mov    bx,archdl            ;file handle
  838.     mov    ax,4201H            ;move pointer from current loc
  839.     int    21H
  840.     ret
  841.  
  842. Bump_ArcPtrs    endp
  843.  
  844.  
  845. ;v1.3    Formats, displays totals
  846.  
  847. Format_Totals    proc    near
  848.     mov    ax,totmbrs        ;total members            v1.3
  849.     mov    di,offset vtmbrs-2    ;format total members        v1.3
  850.     call    Asciify            ;                v1.3
  851.  
  852.     mov    dx,totlen[2]        ; total actual file size
  853.     mov    ax,totlen
  854.     mov    di,offset vtlen        ;format total actual file size    v1.3
  855.     call    Asciify_Long        ;                v1.3
  856.  
  857.     mov    dx,totsize[2]        ; total achive file size
  858.     mov    ax,totsize
  859.     mov    di,offset vtsize    ;format total archive file size    v1.3
  860.     call    Asciify_Long        ;                v1.3
  861.  
  862. ; reduce the total size/length to word values
  863.  
  864.     mov    bx,totlen        ; get actual file size
  865.     mov    ax,totlen[2]
  866.     mov    cx,totsize        ; length of file in archive
  867.     mov    dx,totsize[2]
  868.  
  869. ArcV2b: or    ax,ax            ; big number?
  870.     jz    ArcV2c            ; nope, can use it
  871.      shr    ax,1            ; yup, divide by two
  872.      rcr    bx,1
  873.      shr    dx,1
  874.      rcr    cx,1
  875.      jmp    short ArcV2b
  876.  
  877. ArcV2c:
  878.     mov    ax,bx
  879.     mov    sign,' '        ; whata kludge
  880.     cmp    ax,cx            ; arc is bigger than orig?
  881.     jb    ArcV2c1
  882.      sub    ax,cx            ; amount saved
  883.      jmp    short ArcV2f
  884.  
  885. ArcV2c1:
  886.     sub    ax,cx
  887.     neg    ax
  888.     mov    sign,'-'
  889.  
  890. ArcV2f:
  891.     mul    hundred            ; to percentage
  892.     add    ax,50
  893.     adc    dx,0            ; round up percent
  894.     or    bx,bx            ; empty file?
  895.     jnz    ArcV2d
  896.      mov    ax,100
  897.      jmp    short ArcV2e
  898.  
  899. ArcV2d: div    bx
  900. ArcV2e:
  901.     mov    di,offset vtsf-2    ;format stowage factor        v1.3
  902.     call    Asciify            ;AX                v1.3
  903.  
  904.     mov    al,sign
  905.     mov    vtsf,al
  906.     Print    vthdr            ; display totals
  907.     ret
  908.  
  909. Format_Totals    endp
  910.  
  911.     subttl    ' - miscellaneous subroutines'
  912.     page
  913.  
  914.  
  915. OpenArc proc    near            ; open new archive
  916.  
  917.     mov    dx,offset arcname
  918.     mov    ax,3d00h        ; for input
  919.     int    21h
  920.     jc    OpenArcX        ;AL=error            v1.3
  921.      mov    archdl,ax        ; save file handle
  922. OpenArcX:
  923.     ret                ;return CF clear        v1.3
  924.  
  925. OpenArc endp
  926.  
  927.  
  928. ClosArc proc    near
  929.     mov    bx,archdl        ; previous handle
  930.     or    bx,bx            ; already open?
  931.     jz    Closed
  932.      mov    ah,3eh            ; yes, so close it
  933.      int    21h
  934. Closed:    mov    archdl,0
  935.     ret
  936. ClosArc endp
  937.  
  938. ;
  939. ;    print null-terminated (AsciiZ) string like int 21h function 9
  940. ;    Enter with DS:DX -> AsciiZ string
  941. ;    destroys AX
  942.  
  943. PrintS  proc    near
  944.  
  945.     push    di            ;v1.3
  946.     push    bx
  947.     push    cx
  948.  
  949.     mov    cx,0FFFFH        ;max scan            v1.3
  950.     xor    al,al            ;handy 0            v1.3
  951.     mov    di,dx            ;string start            v1.3
  952.     repne    scasb            ;find the terminator        v1.3
  953.     inc    cx            ;adjust                v1.3
  954.     not    cx            ;CX=length            v1.3
  955.  
  956.     mov    bx,outhdl        ; using std out or temp file
  957.     or    bx,bx            ;never opened?            v1.3
  958.     jnz    Print_S1        ;nope, we got a handle        v1.3
  959.      inc    bx            ;make it StdErr            v1.3
  960.      inc    bx
  961. Print_S1:                ;                v1.3
  962.     mov    ah,40h            ; write to file
  963.     int    21h
  964.     jnb    PrintS_Done        ;fine                v1.3
  965.  
  966. ;v1.3    What happens if we're trying to write to an output file
  967. ;    and THAT fails?  Even error msgs can't get out.
  968. ;    We switch to StdErr, that's what!
  969.     mov    outhdl,STDERR        ;force to StdErr        v1.3
  970.     jmp    Print_S1        ;and display            v1.3
  971.  
  972. PrintS_Done:
  973.     pop    cx            ; recover registers
  974.     pop    bx
  975.     pop    di
  976.     ret
  977.  
  978. PrintS  endp
  979.  
  980.     page
  981. ;
  982. ;    format the time (in AX)
  983.  
  984. time    record  hour:5,min:6,sec:5    ;packed time
  985.  
  986. GetTime proc    near            ;format the date
  987.     mov    di,offset vtime
  988.     or    ax,ax            ;it is zero?
  989.     jz    GotTime
  990.  
  991.     push    ax            ;save date
  992.     and    ax,mask hour        ;get hour part
  993.     mov    cl,hour            ;bits to shift
  994.     shr    ax,cl
  995.     call    Cnvrt1
  996.     stosw
  997.     mov    al,':'
  998.     stosb
  999.  
  1000. GT3:    pop    ax            ;get the time back
  1001.     and    ax,mask min        ;get min part
  1002.     mov    cl,min            ;bits to shift
  1003.     call    Cnvrt
  1004.     stosw
  1005. GotTime:ret
  1006. GetTime endp
  1007.  
  1008.  
  1009. Cnvrt2  proc    near            ;convert to ascii
  1010.     call    Cnvrt
  1011.     cmp    al,'0'            ;suppress leading zero
  1012.     jne    Cnvrtd
  1013.      mov    al,' '
  1014.      ret
  1015.  
  1016. Cnvrt:  shr    ax,cl
  1017. Cnvrt1: aam                ;make al into bcd
  1018.     or    ax,'00'            ; and to ascii
  1019.     xchg    al,ah
  1020. Cnvrtd: ret
  1021. Cnvrt2  endp
  1022.  
  1023.     page
  1024. ;
  1025. ;    format the date (in AX)
  1026.  
  1027. date    record  yr:7,mo:4,dy:5        ;packed date
  1028.  
  1029. GetDate proc    near            ;format the date
  1030.     or    ax,ax            ;is it zero?
  1031.     jz    GotDate
  1032.  
  1033.     push    ax            ;save date
  1034.     and    ax,mask yr        ;get year part
  1035.     mov    cl,yr            ;bits to shift
  1036.     call    Cnvrt
  1037.     mov    di,offset vyear
  1038.     or    al,'8'            ;adjust for base year
  1039.     stosw
  1040.  
  1041.     pop    bx            ;get the date back
  1042.     push    bx            ;save it
  1043.     and    bx,mask mo        ;get month part
  1044.     mov    cl,mo            ;bits to shift
  1045.     shr    bx,cl
  1046.     add    bx,bx            ; form month table index
  1047.     add    bx,bx
  1048.     lea    si,word ptr months-4[bx]
  1049.     mov    cx,word ptr 3
  1050.     mov    di,offset vmonth
  1051.     rep    movsb
  1052.  
  1053.     pop    ax            ;get the date back
  1054.     and    ax,mask dy        ;get day part
  1055.     mov    cl,dy            ;bits to shift
  1056.     call    Cnvrt
  1057.     mov    di,offset vdate
  1058.     stosw
  1059. GotDate:ret
  1060. GetDate endp
  1061.  
  1062.     page
  1063. ;
  1064. ;v1.3    A severely hacked single/double precision number conversion function.
  1065. ;    Originally from JMODEM, but severely hacked by Toad Hall.
  1066. ;    ES:DI -> string
  1067. ;    Destroys everything almost.
  1068.  
  1069. ;Enter here if integer in AX
  1070. Asciify    proc    near
  1071.  
  1072.     xor    dx,dx            ; clear fake long.hi
  1073.     mov    si,ax            ;move integer into SI
  1074.     xor    ah,ah            ;clear msb (flag)
  1075.     jmp    short Ascii_Ax        ;jump into the code
  1076.  
  1077. ;Enter here if long integer in DX:AX.
  1078. Asciify_Long:
  1079.  
  1080.     mov    si,ax            ;move long.lo into SI
  1081.     xor    ah,ah            ;clear msb (flag)
  1082. Comment    ~
  1083.     MOV    CX,3B9AH        ; Get billions
  1084.     MOV    BX,0CA00H
  1085.     CALL    Subtr            ; Subtract them out
  1086.  
  1087.     MOV    CX,05F5H        ; Get hundred-millions
  1088.     MOV    BX,0E100H
  1089.     CALL    Subtr            ; Subtract them out
  1090. Comment    ends    ~
  1091.  
  1092.     and    dx,4FFH            ;seems likely            v1.3
  1093.     MOV    CX,word ptr 0098H    ; Get ten-millions
  1094.     MOV    BX,9680H
  1095.     CALL    Subtr            ; Subtract them out
  1096.  
  1097.     MOV    CX,word ptr 000FH    ; Get millions
  1098.     MOV    BX,4240H
  1099.     CALL    Subtr            ; Subtract them out
  1100.  
  1101.     MOV    CX,word ptr 1        ; Get hundred-thousands
  1102.     MOV    BX,86A0H
  1103.     CALL    Subtr            ; Subtract them out
  1104.  
  1105. Ascii_Ax:
  1106.     xor    cx,cx            ; Get ten-thousands
  1107.     MOV    BX,2710H
  1108.     CALL    Subtr            ; Subtract them out
  1109.     MOV    BX,03E8H
  1110.     CALL    Subtr            ; Subtract them out
  1111.  
  1112.     MOV    BX,word ptr 0064H
  1113.     CALL    Subtr            ; Subtract them out
  1114.     MOV    BX,word ptr 10
  1115.     CALL    Subtr            ; Subtract them out
  1116.     mov    ax,si            ;residual in SI
  1117.     add    AL,'0'            ; Add bias to residual
  1118.     stosb                ; Put in the string
  1119.     RET
  1120.  
  1121. ;Common subroutine for Asciify
  1122.  
  1123. Subtr:    mov    al,'0'-1
  1124.  
  1125. Subtr1:    INC    al            ; Bump the digit character
  1126.     SUB    si,BX            ; Dword subtraction
  1127.     SBB    DX,CX
  1128.     JNB    Subtr1            ; Continue until a carry
  1129.  
  1130.     ADD    si,BX            ; One too many, add back
  1131.     ADC    DX,CX            ;   and the remainder
  1132.  
  1133.     cmp    al,'0'
  1134.     jnz    Subtr2            ;nope, turn off leading flag, stuff
  1135.      or    ah,ah            ;no more leading spaces?
  1136.      jnz    Sub_Stuff        ;right, stuff the '0'
  1137.       mov    al,' '            ;make it neat with leading spaces
  1138. Sub_Stuff:
  1139.     stosb                ;stuff the char
  1140.     RET
  1141.  
  1142. Subtr2:    inc    ah            ;turn off leading space flag
  1143.     stosb
  1144.     ret
  1145. Asciify    ENDP
  1146.  
  1147. hexchar db    '0123456789ABCDEF'
  1148.  
  1149. Cvh    proc    near        ; convert 16-bit binary word in ax
  1150.     push    di        ; to hex ASCII string at ds:di
  1151.     push    bx        ; save registers
  1152.     push    cx
  1153.     push    dx
  1154.  
  1155.     mov    dx,ax        ; save 16-bits
  1156.  
  1157.     mov    bl,dh        ; third nibble
  1158.     mov    cl,4
  1159.     shr    bl,cl
  1160.     mov    al,hexchar[bx]
  1161.     stosb
  1162.  
  1163.     mov    bl,dh        ; last nibble
  1164.     and    bl,0fh
  1165.     mov    al,hexchar[bx]
  1166.     stosb
  1167.  
  1168.     mov    bl,dl        ; first nibble
  1169.     mov    cl,4
  1170.     sub    bh,bh
  1171.     shr    bl,cl        ; isolate
  1172.     mov    al,hexchar[bx]
  1173.     stosb
  1174.  
  1175.     mov    bl,dl        ; second nibble
  1176.     and    bl,0fh        ; isolate
  1177.     mov    al,hexchar[bx]
  1178.     stosb
  1179.     pop    dx        ; restore registers
  1180.     pop    cx
  1181.     pop    bx
  1182.     pop    di
  1183.     ret            ; return
  1184.  
  1185.  
  1186. Cvh    endp
  1187.  
  1188.     subttl    ' - i/o subroutines'
  1189.     page
  1190.  
  1191. GetC    proc    near            ; return next byte in al
  1192.     push    si            ;  or cf=1 for eof
  1193. GetC1:
  1194.     dec    inlen            ; any left in buffer
  1195.     jge    GetC2            ; yes, pick it up
  1196.      call    GetBlk
  1197.      jb    GetCX            ;EOF or read error, return    v1.3
  1198.                     ;(AL=error if any)        v1.3
  1199. GetC2:
  1200.     mov    si,inptr        ; offset to next byte
  1201.     lodsb
  1202.     mov    inptr,si
  1203.     add    incurl,1        ; bump file offset
  1204.     adc    incurh,0
  1205.     clc                ;insure CF clear        v1.3
  1206. GetCX:                    ;v1.3
  1207.     pop    si
  1208.     ret
  1209. GetC    endp
  1210.  
  1211.  
  1212. GetBlk  proc    near            ; read next block
  1213.     push    bx
  1214.     push    cx
  1215.     push    dx
  1216.     mov    ah,3fh            ; read from handle
  1217.     mov    bx,archdl        ; arc file handle
  1218.     mov    cx,INBUFSZ        ; input buffer size
  1219.     mov    dx,offset inbuf        ; offset to input buffer
  1220.     mov    inptr,dx
  1221.     int    21h
  1222.     jb    GetBlkX            ;read error, exit, AL=error    v1.3
  1223.     or    ax,ax            ; anything read?
  1224.     jnz    GetBlkA
  1225.      stc                ; no, set cf=1 for eof,
  1226.                     ;AL=ERRORLEVEL 0 (EOF)        v1.3
  1227.      jmp    short GetBlkX        ; and exit
  1228.  
  1229. GetBlkA:
  1230.     mov    inlen,ax        ; return count of bytes read
  1231. GetBlkX:
  1232.     pop    dx
  1233.     pop    cx
  1234.     pop    bx
  1235.     ret
  1236.  
  1237. GetBlk  endp
  1238.  
  1239.     subttl    '--- i/o data areas'
  1240.     page
  1241.  
  1242. ArcV    endp
  1243.  
  1244. archdr  db    64 dup (0)        ; i/o area for a header
  1245.  
  1246. inbuf    db    INBUFSZ dup (0)
  1247.  
  1248. CSEG    ends
  1249.     end
  1250.