home *** CD-ROM | disk | FTP | other *** search
- page 74,132
- title ARCV - Verbose ARC directory listing
-
- ; Special version of ARCV to be called by QB program
- ; usage:
- ;
- ; CALL ARCV (Workname$,"filename[.PAK]", RETCD%) ' CPC151AC
- ;
- ; notes:
- ; This code originated from ARCV 1.15d - Verbose ARC directory display
- ; written by V.Buerg and was modified to run as a called routine under
- ; Microsoft QuickBasic. It was further modified to allow PAK files by
- ; Robert J. Simoneau.
- ;
- ; Change 9/14/86 to dis-allow wildcards
- ; Change 1/1/87 to recognize squash format
- ; Change 2/18/87 to support network usage - - - - Jon Martin ' CPC151A
- ; Change 1/7/89 to support Pak files -------------Bob Simoneau
- ; Change 890320 to support ZIP files David Kirschbaum, Toad Hall
- ; - Question: Why do we "have to look for the damned thing" when it
- ; comes to finding ARC/PAK headers? All comments are at file ends,
- ; so the header should be EXACTLY where it should be .. at the end of
- ; the file's compressed code. Hacked severely to reflect this,
- ; and vastly cleaning up the code.
- ; - Replaced old SDIR Binary to Ascii conversion with a hacked version
- ; from JMODEM .. about 10 times faster, plus offers integer conversion
- ; as well as long integers.
-
-
- STDOUT equ 1 ;Standard Output v1.3
- STDERR equ 2 ;Std Error (console) v1.3
-
- Print macro name ; display a field
- mov dx,offset name
- call PrintS
- endm
-
- header struc ; archive header
- mbrflag db 1AH ;unique ARC/PAK flag v1.3
- mbrcode db 0 ; compression code
- mbrname db 13 dup (0) ; file name
- mbrsize dw 0,0 ; file size in archive
- mbrdate dw 0 ; creation date
- mbrtime dw 0 ; creation time
- mbrcrc dw 0 ; cyclic redundancy check
- mbrlen dw 0,0 ; true file size, bytes
- header ends
- ARCHDRLEN equ 29 ;size of ARC/PAK header. v1.3
-
- ;v1.3 ZIP Local file header structure:
-
- zLocalEntry STRUC
-
- zdig0 db 50H,4BH,03H,04H ;local file header signature 4 bytes
- ;(0x04034b50)
- zVerMade dw ? ;version needed to extract 2 bytes
- zBitflag dw ? ;general purpose bit flag 2 bytes
- zCmpMeth dw ? ;compression method 2 bytes
- zModTime dw ? ;last mod file time 2 bytes
- zModDate dw ? ;last mod file date 2 bytes
- zCrc32 dw ?,? ;crc-32 4 bytes
- zCmpSiz dw ?,? ;compressed size 4 bytes
- zUncmpSiz dw ?,? ;uncompressed size 4 bytes
- zNameLen dw ? ;filename length 2 bytes
- zExtraLen dw ? ;extra field length 2 bytes
- zFilename db ? ;filename (variable size)
- ;extra field (variable size)
- ZLocalEntry ENDS
-
- ZIPHDRLEN equ 30 ;length of initial ZIP hdr read v1.3
-
-
-
- CSEG segment public para 'CODE'
- assume CS:CSEG,DS:CSEG,ES:CSEG
-
- public ArcV
-
- ArcV proc far
-
- push bp ; save BASIC reg
- mov bp,sp ; get parameter list pointer
- mov CS:stkptr,sp ; save stack ptr
- mov CS:saveds,DS ; save QB seg reg
- mov CS:savees,ES ; save QB seg reg
- call Start ; do our thing v1.3
-
- ; set DOS error level and exit
-
- Exit: mov sp,stkptr ; restore entry stack value
-
- push ax ;save error value v1.3
-
- ;v1.3 Numerous errors could be returned
-
- jnb Exit_NoErr ;ok, no errors
- xor bx,bx ;'Usage:...'
- cmp al,1 ;command line parm error
- jz Exit_ErrOut ;yep
- inc bl ;'Archive file not found'
- cmp al,6 ;2..6 are file-related errors
- jz Exit_ErrOut ;yep
- inc bl ;'Archive header error'
- cmp al,0BH
- jz Exit_ErrOut ;yep
- inc bl ;'Archive format error'
- cmp al,0EH
- jz Exit_ErrOut ;yep
- inc bl ;'Unknown error'
- Exit_ErrOut:
- shl bx,1 ;*2 for words
- add bx,offset errtbl ;table of addresses
- mov dx,[bx] ;ptr to string
- call PrintS ;output error msg
-
- Exit_NoErr:
-
- mov bx,word ptr outhdl ; close listing file
- cmp bl,STDERR ;never opened or STDERR? v1.3
- jna Exit1 ;not a real handle v1.3
- mov ah,3eh ;close file handle
- int 21h
- Exit1:
- mov bx,word ptr archdl ;close ARC/PAK/ZIP file v1.3
- or bx,bx ; if it was opened v1.3
- jz Exit2 ; nope v1.3
- mov ah,3EH ;close file handle v1.3
- int 21H ; v1.3
- Exit2: ; v1.3
-
- ;v1.3 Adding a test to insure we switched DTAs
- ; (so we don't blow away the caller's DTA with a vector 0:0!)
-
- lds dx,dword ptr savedta ;get orig DTA vector
- or dx,dx ;did we ever get it?
- jz Exit_NoDTA ;nope
- mov ax,DS ;check out seg
- or ax,ax
- jz Exit_NoDTA ;nope
- mov ah,1ah ;set DTA
- int 21h
- Exit_NoDTA:
-
- lds ax,dword ptr CS:saveds ;recover calling seg regs v1.3
- ;(low word is orig ES) v1.3
- mov ES,ax
- ASSUME DS:NOTHING,ES:NOTHING ;a reminder
-
- pop ax ;restore error level v1.3
- cbw
- mov bp,sp ; parm ptr from entry
- mov 6[bp],ax ;return retcd variable v1.3
- pop bp
- ret 6 ; clear parms from stack ' CPC151A
-
- subttl '--- constants, equates and work areas'
- page
-
- CR equ 13
- LF equ 10
- BEL equ 7
- TAB equ 9
-
- STOPPER equ 0 ; end of display line indicator
- ARCMARK equ 26 ; special archive marker
- ARCVER equ 10 ; highest compression code used
-
- stkptr dw 0 ; stack pointer upon entry
-
- arctitl db CR,LF,'Archive: '
- saveds dw 0 ; QB seg reg
- savees dw 0 ; QB seg reg
-
- subttl '--- i/o control variables'
- page
-
- INBUFSZ equ 128 ;512 ; size of input buffer v1.3
-
- ;v1.3 Completely reordered these runtime variables
- ; so we can purge them with one fell swoop
-
- PURGESTART equ $ ; v1.3
-
- inptr dw 0 ; offset to current byte
- inlen dw 0 ; bytes left in buffer
- incurh dw 0 ; current file offset
- incurl dw 0 ; low word
-
- totsf dw 0,0 ; average stowage factor
- totlen dw 0,0 ; total of file lengths
- totsize dw 0,0 ; total of file sizes
- totmbrs dw 0 ; total number of files
-
- archdl dw 0 ; file handle
- fileptr dw 0 ; ptr to filename part of arcname
- arclen dw 0 ;full archive filename length v1.3
- arcname db 76 dup (0)
-
- outhdl dw 0 ; handle for output listing v1.3
- templen dw 0 ;output filename length v1.3
- temp db 76 dup (0) ; and temporary file name
-
- savedta dw 0,0 ; addr of QB dta
- dta db 48 dup (0) ; data transfer area
-
- even ; v1.3
-
- PURGELEN EQU ($ - PURGESTART) SHR 1 ;amount to purge each run v1.3
-
- usage db CR,LF
- db 'QBARCV3 - Verbose ARC/PAK/ZIP directory display for QuickBasic' ;v1.3
- db CR,LF,LF,' Usage: call arcv (workname$,filename.[ARC][PAK][ZIP],' ;v1.3
- db 'result%',CR,LF,STOPPER ;v1.3
-
- ; display lines for verbose
-
- vhdr db CR,LF
- db CR,LF,'Name Length Stowage SF Size now Date Time CRC '
- db CR,LF,'============ ======== ======== ==== ======== ========= ====== ===='
- db STOPPER
-
- vline db CR,LF
- vname db 14 dup (' ')
- vlength db ' ' ; length in archive v1.3
- vstyle db ' ' ; compression method
- vfactor db ' xx% ' ; compression factor
- vsize db 10 dup (' ') ; actual file bytes
- vdate db 'dd ' ; creation date
- vmonth db 'mmm '
- vyear db 'yy '
- vtime db 'hh:mm ' ; creation time
- vcrc db 'xxxx' ; crc in hex
- db STOPPER
-
- hundred dw 100 ; for computing percentages
-
- ; final totals line
-
- vthdr db CR,LF,LF,'*Total ' ; ' CPC151A
- vtmbrs db ' '
- vtlen db 8 dup (' '),' '
- db 10 dup (' ')
- vtsf db ' % '
- vtsize db 8 dup (' ')
- db CR,LF ; for tom
- db STOPPER
- sign db ' '
-
- styles db ' ----- ' ; 1 = old, no compression
- db ' ----- ' ; 2 = new, no compression
- db ' Packed ' ; 3 = dle for repeat chars
- db 'Squeezed' ; 4 = huffman encoding
- db 'crunched' ; 5 = lz, no dle
- db 'crunched' ; 6 = lz with dle
- db 'Crunched' ; 7 = lz with readjust
- db 'Crunched' ; 8 = lz with readjust and dle
- db 'Squashed' ; 9 = 13-bit lz with no dle
- db ' Crushed' ;10 = Pak10 file ---------Bob Simoneau
-
- ;v1.3 ZIP compression types:
-
- zstyles label byte
- db ' Stored' ;0 - The file is stored (no compression)
- db ' Shrunk' ;1 - The file is Shrunk
- db 'Reduced1' ;2 - Reduced with compression factor 1
- db 'Reduced2' ;3 - Reduced with compression factor 2
- db 'Reduced3' ;4 - Reduced with compression factor 3
- db 'Reduced4' ;5 - Reduced with compression factor 4
-
- months db 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
-
- ARCPAK = 0 ; v1.3
- ZIP = 0FFH ; v1.3
- ftype db ARCPAK ;flag which type file v1.3
-
- arctype db 'ARC' ;3 types of archive file v1.3
- paktype db 'PAK'
- ziptype db 'ZIP'
-
- zfilesig db 50H,4BH,03H,04H ;local file header signature v1.3
- zdirsig db 50H,4BH,01H,02H ;central file header signature v1.3
-
- ;v1.3 Centralizing errors at the exit point
-
- errtbl dw usage,msg1,msg2,msg3,msg4 ;error msg ptrs
-
- msg1 db 'Archive file not found',0
- msg2 db 'Archive header error',0
- msg3 db 'Archive format error',0
- msg4 db 'Unknown error',0
-
-
- subttl '--- mainline processing'
- page
- ;
- Start proc near ; v1.3
-
- mov ax,CS ;just set ES for now v1.3
- mov ES,ax
- ASSUME ES:CSEG ;a reminder v1.3
-
- ;v1.3 Insure all variables are cleared
- cld
- mov di,offset PURGESTART
- xor ax,ax ;clear all the variables v1.3
- mov cx,PURGELEN ;nr words to clear v1.3
- rep stosw ; v1.3
-
- ;v1.3 Move first parameter (output filename) into code space
-
- mov si,word ptr 10[bp] ; ptr to parameter vector ' CPC151A
- lodsw ; get string length ' CPC151A
- mov cx,ax ; ' CPC151A
- jcxz Copy_Parm2 ;empty, forget it v1.3
- mov di,offset templen ;str length v1.3
- stosw ;save length v1.3
- mov si,word ptr [si] ; get string offset ' CPC151A
- rep movsb ;copy in the string v1.3
-
- Copy_Parm2:
-
- ;v1.3 Now copy 2d parameter (target archive filename)
-
- mov si,word ptr 8[bp] ; ptr to parameter vector
- lodsw ; get string length
- mov cx,ax ; v1.3
- jcxz Parm2_Done ;forget it v1.3
- mov di,offset arclen ;archive name length v1.3
- stosw ;save length v1.3
- mov si,word ptr [si] ; get string offset v1.3
- mov ah,'a' ;constant for uppercasing v1.3
- Parm2_Upper: ; v1.3
- lodsb ;snarf char v1.3
- cmp al,ah ;need uppercasing? v1.3
- jb Parm2_NoU ;nope v1.3
- sub al,20H ;uppercase it v1.3
- Parm2_NoU: ; v1.3
- stosb ; v1.3
- loop Parm2_Upper ; v1.3
-
- Parm2_Done:
-
- ;v1.3 All done with DS
-
- mov ax,CS ; v1.3
- mov DS,ax ; v1.3
- ASSUME DS:CSEG ;a reminder v1.3
-
- cmp temp,0 ;any output filename? v1.3
- jnz Got_Temp ;yep v1.3
-
- ;v1.3 Forcing output file to STDERR for debugging.
- ;v1.3 mov al,1 ; will show usage v1.3
- ;v1.3 ret ;back to Exit v1.3
-
- mov ax,STDERR ;force to STDERR v1.3
- jmp short Temp_Opened ;continue v1.3
-
- Got_Temp:
- mov dx,offset temp ; open temporary file for output
- xor cx,cx ;no special attributes v1.3
- mov ah,3ch ;create file
- int 21h
- jnb Temp_Opened ;fine v1.3
- ret ;back to Exit, AL=error code v1.3
-
- Temp_Opened:
- mov outhdl,ax ;save handle
-
- ;v1.3 Parse the target archive name
- ; Separate path from name
- ; Insure it's an ARC, PAK or ZIP type.
-
-
- mov di,offset arclen ;archive name length v1.3
- lodsw ;snarf length, bump to name v1.3
- mov dx,ax ;save in DX for later v1.3
- xor al,al ;will scan for AsciiZ terminator v1.3
- cmp [di],al ;no name at all? v1.3
- jnz Got_TgtName ;yep v1.3
- mov al,2 ;'file not found' v1.3
- ret ;back to Exit v1.3
-
- Got_TgtName:
-
- ;v1.3 We have some sort of target name.
- ; But is it a legal type?
- ; DX = filename length
- ; DI -> archive filename (arcname)
-
- add di,dx ;+ length -> last char+1 v1.3
- dec di ;back up to last char v1.3
- mov bx,di ;BX -> last char v1.3
-
- mov al,'\' ;look for normal path delimiter v1.3
- mov cx,dx ;length for scan v1.3
- std ;backwards scanning now v1.3
- repne scasb ; v1.3
- jz Got_Start ;found one v1.3
-
- ;Ugh .. tired of typing in v1.3's!
-
- mov di,bx ;back to end
- mov cx,dx ;restore length
- mov al,'/' ;funny path delimiter
- repne scasb
- jz Got_Start ;found one
-
- mov di,bx ;back to end .. sigh ..
- mov cx,dx ;restore length
- mov al,':' ;ok, how about a drive?
- repne scasb
-
- Got_Start:
- inc di ;adjust DI from last scasb
- cld ;forward again
- mov fileptr,di ;remember real filename start
-
- ;v1.3 You MUST specify the type .. .ARC, .PAK, or .ZIP.
- ; If .ARC or .PAK, we'll use the old code to display ARC-type
- ; files.
- ; Else if ZIP, it's a totally new format!
- ; We remember the type archiving format in 'ftype'.
-
- ;v1.3 DS:SI -> filename's first char.
-
- mov al,'.' ;find the separator v1.3
- mov cx,word ptr 12 ;max of 12 chars v1.3
- repne scasb ;find it v1.3
- jnz BadType ;forget it v1.3
-
- Parm3:
- mov dx,di ;save pointer to file type v1.3
- ;(just past the separator) v1.3
- mov si,offset arctype ;is it an ARC? v1.3
- mov ax,3 ;3 chars constant
- mov cx,ax ;3 chars
- repz cmpsb ;compare
- jz Got_Type ;a match
-
- mov si,offset paktype ;is it a PAK?
- mov di,dx ;back to filename type
- mov cx,ax ;3 chars
- repz cmpsb ;compare
- jz Got_Type ;a match
-
- mov ftype,ZIP ;assume ZIP
- mov si,offset ziptype ;is it a ZIP?
- mov di,dx ;back to filename type
- mov cx,ax ;3 chars
- repz cmpsb ;compare
- jz Got_Type ;a match
-
- BadType:
- mov al,1 ;prints usage v1.3
- ret ;back to Exit v1.3
-
- Got_Type: ;v1.3
-
- ; find first matching file
-
- push ES
- mov ah,2fh ; get current dta ptr
- int 21h ; returned in ES:bx
- mov savedta,ES
- mov savedta[2],bx
- pop ES
-
- mov dx,offset dta ; set local dta for murkers
- mov ah,1ah
- int 21h
-
- call OpenArc ; see if archive exists
- jb ArcV_X ;nope, return, AL = error v1.3
-
- ; process next archive header entry
-
- ; ArcV1: Print arctitl ' removed for security reasons in CPC16-1A
-
- ArcV1: Print vhdr
- jb ArcV_X ;output failed v1.3
-
- ArcVNext:
- call GetHdr ; load next header
- jb ArcV_NoHdr ;failed somehow v1.3
-
- call ArcVgo ;format, write out file report
- jb Arcv_NoHdr ;something failed v1.3
- call Bump_ArcPtrs ;bump to next archive file v1.3
- jnb ArcVNext ;loop if ok v1.3
-
-
- ArcV_NoHdr:
- cmp archdr.mbrcode,0 ; archive eof?
- jnz ArcV_X ;nope, something else happened v1.3
-
- cmp totmbrs,0 ;any totals? v1.3
- jz ArcV_X ;nope v1.3
- push ax ;save previous error value v1.3
- call Format_Totals ;yep, format and output v1.3
- pop ax ;restore prev err value v1.3
-
- ArcV_X: ret ; v1.3
-
- Start endp ; v1.3
-
-
- ;v1.3 Format, display single line for each member
- ; Returns CF set if failure (because of output write fail)
-
- ArcVgo proc near
- mov di,offset vname ; copy file name
- mov si,offset archdr.mbrname
- mov cx,word ptr 13
- ArcV3:
- lodsb
- or al,al ; end of name? v1.3
- je ArcV4
- stosb
- loop ArcV3
- jmp short ArcV5
-
- ArcV4:
- mov al,' ' ; pad with blanks
- rep stosb
- ArcV5:
- ; reduce the size/length to word values
-
- mov bx,archdr.mbrlen ; get actual file size
- mov ax,archdr.mbrlen[2]
-
- mov cx,archdr.mbrsize ; length of file in archive
- mov dx,archdr.mbrsize[2]
-
- ArcV51: or ax,ax ; big number?
- jz ArcV52 ; nope, can use it
- shr ax,1 ; yup, divide by two
- rcr bx,1
- shr dx,1
- rcr cx,1
- jmp short ArcV51
-
- ArcV52:
- ;v1.5 mov si,offset vfactor-5 ; format stowage factor
- mov ax,bx ; low word of actual size
- mov sign,' '
- cmp ax,cx ; arc member is larger?
- jb ArcV520
- sub ax,cx ; amount saved
- jmp short ArcV56
-
- ArcV520:
- sub ax,cx
- neg ax
- mov sign,'-'
-
- ArcV56:
- mul hundred ; to percentage
- add ax,50
- adc dx,0 ; round up percent
- or bx,bx ; empty file?
- jnz ArcV53
- mov ax,100
- jmp short ArcV54
-
- ArcV53: div bx
- ArcV54:
- ;v1.3 sub dx,dx
- cmp ax,100 ; archive fouled?
- jbe ArcV55
- sub ax,ax
- ArcV55:
- mov di,offset vfactor-2 ;format stowage factor v1.3
- call Asciify ;display AX
-
- mov al,sign
- mov vfactor,al
-
- mov si,offset zstyles ;assume ZIP v1.3
- cmp ftype,ZIP ;ZIP file? v1.3
- jz ArcV55A ;yep v1.3
- mov si,offset styles ;ARC or PAK v1.3
- ArcV55A: ; v1.3
-
- sub bx,bx ; determine style
- mov bl,archdr.mbrcode
- dec bl ;adjust for table offset v1.3
- mov cl,3 ; eight bytes each entry
- shl bx,cl
-
- add si,bx ;point into style table v1.3
- mov di,offset vstyle
- mov cx,word ptr 4 ;move as words (8 bytes) v1.3
- rep movsw ; v1.3
-
- mov dx,archdr.mbrsize[2]
- mov ax,archdr.mbrsize
- add totsize,ax
- adc totsize[2],dx
- mov di,offset vsize ;format file size v1.3
- call Asciify_Long ; v1.3
-
- ;v1.3 mov si,offset vlength ; format file length
- mov dx,archdr.mbrlen[2]
- mov ax,archdr.mbrlen
- add totlen,ax
- adc totlen[2],dx
- mov di,offset vlength ;format file length v1.3
- call Asciify_Long ; v1.3
-
- mov ax,archdr.mbrdate ; format file date
- call GetDate
-
- mov ax,archdr.mbrtime ; format file time
- call GetTime
-
- mov ax,archdr.mbrcrc ; format crc in hex
- mov di,offset vcrc
- call Cvh
-
- Print vline ; display this file info
- inc totmbrs ;NOW bump total count v1.3
- ret
-
- ArcVgo endp
-
-
- subttl '--- load next archive header'
- page
-
- ;v1.3 Adding ZIP file searching
-
- GetHdr proc near
-
- cmp ftype,ZIP ;doing ZIP files? v1.3
- jz Get_ZipHdr ;yep, find a zip header v1.3
-
- ;v1.3 New code
- Comment ~ ARC/PAK headers look like this:
- mbrflag db 1AH ;unique header flag
- mbrcode db 0 ; compression code
- mbrname db 13 dup (0) ; file name
- mbrsize dw 0,0 ; file size in archive
- mbrdate dw 0 ; creation date
- mbrtime dw 0 ; creation time
- mbrcrc dw 0 ; cyclic redundancy check
- mbrlen dw 0,0 ; true file size, bytes
- Comment ends ~
-
- mov dx,offset archdr ;read into here
- mov cx,ARCHDRLEN ;nr bytes to read
- mov bx,archdl ;archive file handle
- mov ah,3FH ;read from file/device
- int 21H
- jb Hdr_RetCF ;read failed, return CF set
-
- mov bx,dx ;structure start
- cmp [bx].mbrflag,ARCMARK ;start of header?
- jne Hdr_InvalFmt ;'invalid format', exit CF set
-
- mov al,[bx].mbrcode ;type compression
- cmp al,ARCVER ;reasonable code?
- ja Hdr_InvalFmt ;nope, funny stuff
-
- or al,al ; archive eof?
- je Hdr_RetCF ;yep, done, return CF set
-
- cmp al,1 ; old format?
- jne GetHdrX ; if so, it's short
- mov si,offset archdr.mbrsize ; CPC15-1C
- mov di,offset archdr.mbrlen ; CPC15-1C
- movsw
- movsw
- GetHdrX:
- clc
- ret
-
- Hdr_InvalFmt:
- mov al,0BH ;'invalid format'
- mov [bx].mbrcode,0 ;signal EOF
- Hdr_RetCF:
- stc ;return CF set
- ret
-
-
- Get_ZipHdr:
- ;v1.3 Reads in file entry.
- ; Then scans for the unique file entry signature.
- ; On success:
- ; DS:BX -> file entry directory structure
- ; CF clear
- ; Else CF set for failure
-
- mov archdr.mbrcode,0 ;assume end
- call Read_Zip_Entry
- jb Get_ZHdrX ;failed, AL=ERRORLEVEL
-
- ZH_RdOk:
- mov bx,offset inbuf ;use for field base
- mov di,offset archdr.mbrcode ;moving into this structure
-
- ;v1.3 Remember, the record we'll be formatting from
- ; looks like this:
- ;mbrflag db 1AH
- ;mbrcode db 0 ; compression code
- ;mbrname db 13 dup (0) ; file name
- ;mbrsize dw 0,0 ; file size in archive
- ;mbrdate dw 0 ; creation date
- ;mbrtime dw 0 ; creation time
- ;mbrcrc dw 0 ; cyclic redunancy check
- ;mbrlen dw 0,0 ; true file size, bytes
-
- mov ax,[bx].zCmpMeth ;compression method
- inc al ;bump to be non-0
- stosb ;-> mbrcode
-
- ;For now, assuming a normal file name (no paths)
-
- mov ax,[bx].zNameLen ;filename length
- and ax,15 ;constrain to max 12 chars
- mov cx,ax ;into CX for move
- lea si,[bx].zFileName ;pointer to actual filename
- rep movsb ;do the move
- xor al,al ;terminating 0
- stosb
-
- mov di,offset archdr.mbrsize ;bump past name
-
- mov ax,[bx].zCmpSiz ;compressed size.lo
- stosw ; -> mbrsize
- mov ax,[bx].zCmpSiz[2] ;compressed size.hi
- stosw ; -> mbrsize[2]
- mov ax,[bx].zModDate ;last mod date
- stosw ; -> mbrdate
- mov ax,[bx].zModTime ;last mod time
- stosw ; -> mbrtime
- mov ax,[bx].zCrc32 ;CRC-32 value.lo
- stosw ; -> mbrcrc
- mov ax,[bx].zUncmpSiz ;uncompressed size.lo
- stosw ; -> mbrlen
- mov ax,[bx].zUncmpSiz[2] ;uncompressed size.hi
- stosw ; -> mbrlen[2]
-
- clc ;return CF clear
- Get_ZHdrX:
- ret
-
- GetHdr endp
-
-
- Read_Zip_Entry proc near
-
- mov bx,archdl ;file handle
- mov dx,offset inbuf ;read into here
- mov cx,ZIPHDRLEN ;entry structure size
- ;(does NOT include filename or
- ; Extra fields, which are
- ;dynamic)
- call ReadZ_It ;try to read in header
- ;(up to filename)
- jb ReadZ_ItX ;failed, AL=error
-
- mov si,offset zfilesig ;expected file signature
- mov di,dx ;structure signature
- mov cx,word ptr 4 ;4 bytes
- repz cmpsb ;compare
- jz ReadZ_Ok1 ;fine, a member signature
- xor al,al ;assume 0 error (last entry)
- mov si,offset zdirsig ;Central directory signature
- mov di,dx ;back to structure signature
- mov cl,4 ;4 bytes
- repz cmpsb ;compare
- jz ReadZ_Last_Fail ;yep, last entry, return CF set
- mov al,0DH ;force to 'invalid data'
- jmp short ReadZ_Last_Fail ;return CF set
-
- ReadZ_Ok1:
- ; add dx,ax ;move to zFilename psn
- mov dx,offset inbuf.zFileName ;move to zFilename psn
- mov cx,inbuf.zNameLen ;length of member filename
- call ReadZ_It ;read in filename
- jb ReadZ_ItX ;failed, AL = ERRORLEVEL
- clc ;CF clear for success
- ret
-
- ;Common subroutine for ReadZ
-
- ReadZ_It:
- mov ah,3FH ;read from file/device
- int 21H
- jb ReadZ_Last_Fail ;failed, error in AX
- cmp ax,cx ;read all we expected?
- mov al,0BH ;assume unexpected EOF
- ;('invalid format')
- jnz ReadZ_Last_Fail ;did NOT read it all
- mov ax,cx ;return AX=bytes read
- ret ;and CF clear
-
- ReadZ_Last_Fail:
- stc ;return CF set for failure
- ReadZ_ItX:
- ret ;errorlevel in AL
-
- Read_Zip_Entry endp
-
-
- ;v1.3 Common subroutine
- ; Bumps archive file pointers to next entry
-
- Bump_ArcPtrs proc near
-
- cmp ftype,ZIP ;ZIP file? v1.3
- jz Next_ZEntry ;bump file ptr to next entry v1.3
-
- ;v1.3 Entirely new code
-
- mov cx,archdr.mbrsize[2] ;pick up encoded file length
- mov dx,archdr.mbrsize ; of current file
- jmp short Bump_Common ;common code
-
-
- ;v1.3 Positions ZIP file pointer to next local entry.
- ; We've already read in the entire header, plus the filename,
- ; so the file pointer should be just beyond the filename
- ; (at the Extra field).
- ; Move file pointers beyond the Extra field, and then past
- ; the actual entry data (the compressed size).
-
- Next_ZEntry:
-
- mov bx,offset inbuf ;point back to structure
- mov dx,[bx].zCmpSiz ;size.lo
- mov cx,[bx].zCmpSiz[2] ;size.hi
- add dx,[bx].zExtraLen ;add in extra field length
- adc cx,0 ;in case of carry
- Bump_Common:
- mov bx,archdl ;file handle
- mov ax,4201H ;move pointer from current loc
- int 21H
- ret
-
- Bump_ArcPtrs endp
-
-
- ;v1.3 Formats, displays totals
-
- Format_Totals proc near
- mov ax,totmbrs ;total members v1.3
- mov di,offset vtmbrs-2 ;format total members v1.3
- call Asciify ; v1.3
-
- mov dx,totlen[2] ; total actual file size
- mov ax,totlen
- mov di,offset vtlen ;format total actual file size v1.3
- call Asciify_Long ; v1.3
-
- mov dx,totsize[2] ; total achive file size
- mov ax,totsize
- mov di,offset vtsize ;format total archive file size v1.3
- call Asciify_Long ; v1.3
-
- ; reduce the total size/length to word values
-
- mov bx,totlen ; get actual file size
- mov ax,totlen[2]
- mov cx,totsize ; length of file in archive
- mov dx,totsize[2]
-
- ArcV2b: or ax,ax ; big number?
- jz ArcV2c ; nope, can use it
- shr ax,1 ; yup, divide by two
- rcr bx,1
- shr dx,1
- rcr cx,1
- jmp short ArcV2b
-
- ArcV2c:
- mov ax,bx
- mov sign,' ' ; whata kludge
- cmp ax,cx ; arc is bigger than orig?
- jb ArcV2c1
- sub ax,cx ; amount saved
- jmp short ArcV2f
-
- ArcV2c1:
- sub ax,cx
- neg ax
- mov sign,'-'
-
- ArcV2f:
- mul hundred ; to percentage
- add ax,50
- adc dx,0 ; round up percent
- or bx,bx ; empty file?
- jnz ArcV2d
- mov ax,100
- jmp short ArcV2e
-
- ArcV2d: div bx
- ArcV2e:
- mov di,offset vtsf-2 ;format stowage factor v1.3
- call Asciify ;AX v1.3
-
- mov al,sign
- mov vtsf,al
- Print vthdr ; display totals
- ret
-
- Format_Totals endp
-
- subttl ' - miscellaneous subroutines'
- page
-
-
- OpenArc proc near ; open new archive
-
- mov dx,offset arcname
- mov ax,3d00h ; for input
- int 21h
- jc OpenArcX ;AL=error v1.3
- mov archdl,ax ; save file handle
- OpenArcX:
- ret ;return CF clear v1.3
-
- OpenArc endp
-
-
- ClosArc proc near
- mov bx,archdl ; previous handle
- or bx,bx ; already open?
- jz Closed
- mov ah,3eh ; yes, so close it
- int 21h
- Closed: mov archdl,0
- ret
- ClosArc endp
-
- ;
- ; print null-terminated (AsciiZ) string like int 21h function 9
- ; Enter with DS:DX -> AsciiZ string
- ; destroys AX
-
- PrintS proc near
-
- push di ;v1.3
- push bx
- push cx
-
- mov cx,0FFFFH ;max scan v1.3
- xor al,al ;handy 0 v1.3
- mov di,dx ;string start v1.3
- repne scasb ;find the terminator v1.3
- inc cx ;adjust v1.3
- not cx ;CX=length v1.3
-
- mov bx,outhdl ; using std out or temp file
- or bx,bx ;never opened? v1.3
- jnz Print_S1 ;nope, we got a handle v1.3
- inc bx ;make it StdErr v1.3
- inc bx
- Print_S1: ; v1.3
- mov ah,40h ; write to file
- int 21h
- jnb PrintS_Done ;fine v1.3
-
- ;v1.3 What happens if we're trying to write to an output file
- ; and THAT fails? Even error msgs can't get out.
- ; We switch to StdErr, that's what!
- mov outhdl,STDERR ;force to StdErr v1.3
- jmp Print_S1 ;and display v1.3
-
- PrintS_Done:
- pop cx ; recover registers
- pop bx
- pop di
- ret
-
- PrintS endp
-
- page
- ;
- ; format the time (in AX)
-
- time record hour:5,min:6,sec:5 ;packed time
-
- GetTime proc near ;format the date
- mov di,offset vtime
- or ax,ax ;it is zero?
- jz GotTime
-
- push ax ;save date
- and ax,mask hour ;get hour part
- mov cl,hour ;bits to shift
- shr ax,cl
- call Cnvrt1
- stosw
- mov al,':'
- stosb
-
- GT3: pop ax ;get the time back
- and ax,mask min ;get min part
- mov cl,min ;bits to shift
- call Cnvrt
- stosw
- GotTime:ret
- GetTime endp
-
-
- Cnvrt2 proc near ;convert to ascii
- call Cnvrt
- cmp al,'0' ;suppress leading zero
- jne Cnvrtd
- mov al,' '
- ret
-
- Cnvrt: shr ax,cl
- Cnvrt1: aam ;make al into bcd
- or ax,'00' ; and to ascii
- xchg al,ah
- Cnvrtd: ret
- Cnvrt2 endp
-
- page
- ;
- ; format the date (in AX)
-
- date record yr:7,mo:4,dy:5 ;packed date
-
- GetDate proc near ;format the date
- or ax,ax ;is it zero?
- jz GotDate
-
- push ax ;save date
- and ax,mask yr ;get year part
- mov cl,yr ;bits to shift
- call Cnvrt
- mov di,offset vyear
- or al,'8' ;adjust for base year
- stosw
-
- pop bx ;get the date back
- push bx ;save it
- and bx,mask mo ;get month part
- mov cl,mo ;bits to shift
- shr bx,cl
- add bx,bx ; form month table index
- add bx,bx
- lea si,word ptr months-4[bx]
- mov cx,word ptr 3
- mov di,offset vmonth
- rep movsb
-
- pop ax ;get the date back
- and ax,mask dy ;get day part
- mov cl,dy ;bits to shift
- call Cnvrt
- mov di,offset vdate
- stosw
- GotDate:ret
- GetDate endp
-
- page
- ;
- ;v1.3 A severely hacked single/double precision number conversion function.
- ; Originally from JMODEM, but severely hacked by Toad Hall.
- ; ES:DI -> string
- ; Destroys everything almost.
-
- ;Enter here if integer in AX
- Asciify proc near
-
- xor dx,dx ; clear fake long.hi
- mov si,ax ;move integer into SI
- xor ah,ah ;clear msb (flag)
- jmp short Ascii_Ax ;jump into the code
-
- ;Enter here if long integer in DX:AX.
- Asciify_Long:
-
- mov si,ax ;move long.lo into SI
- xor ah,ah ;clear msb (flag)
- Comment ~
- MOV CX,3B9AH ; Get billions
- MOV BX,0CA00H
- CALL Subtr ; Subtract them out
-
- MOV CX,05F5H ; Get hundred-millions
- MOV BX,0E100H
- CALL Subtr ; Subtract them out
- Comment ends ~
-
- and dx,4FFH ;seems likely v1.3
- MOV CX,word ptr 0098H ; Get ten-millions
- MOV BX,9680H
- CALL Subtr ; Subtract them out
-
- MOV CX,word ptr 000FH ; Get millions
- MOV BX,4240H
- CALL Subtr ; Subtract them out
-
- MOV CX,word ptr 1 ; Get hundred-thousands
- MOV BX,86A0H
- CALL Subtr ; Subtract them out
-
- Ascii_Ax:
- xor cx,cx ; Get ten-thousands
- MOV BX,2710H
- CALL Subtr ; Subtract them out
- MOV BX,03E8H
- CALL Subtr ; Subtract them out
-
- MOV BX,word ptr 0064H
- CALL Subtr ; Subtract them out
- MOV BX,word ptr 10
- CALL Subtr ; Subtract them out
- mov ax,si ;residual in SI
- add AL,'0' ; Add bias to residual
- stosb ; Put in the string
- RET
-
- ;Common subroutine for Asciify
-
- Subtr: mov al,'0'-1
-
- Subtr1: INC al ; Bump the digit character
- SUB si,BX ; Dword subtraction
- SBB DX,CX
- JNB Subtr1 ; Continue until a carry
-
- ADD si,BX ; One too many, add back
- ADC DX,CX ; and the remainder
-
- cmp al,'0'
- jnz Subtr2 ;nope, turn off leading flag, stuff
- or ah,ah ;no more leading spaces?
- jnz Sub_Stuff ;right, stuff the '0'
- mov al,' ' ;make it neat with leading spaces
- Sub_Stuff:
- stosb ;stuff the char
- RET
-
- Subtr2: inc ah ;turn off leading space flag
- stosb
- ret
- Asciify ENDP
-
- hexchar db '0123456789ABCDEF'
-
- Cvh proc near ; convert 16-bit binary word in ax
- push di ; to hex ASCII string at ds:di
- push bx ; save registers
- push cx
- push dx
-
- mov dx,ax ; save 16-bits
-
- mov bl,dh ; third nibble
- mov cl,4
- shr bl,cl
- mov al,hexchar[bx]
- stosb
-
- mov bl,dh ; last nibble
- and bl,0fh
- mov al,hexchar[bx]
- stosb
-
- mov bl,dl ; first nibble
- mov cl,4
- sub bh,bh
- shr bl,cl ; isolate
- mov al,hexchar[bx]
- stosb
-
- mov bl,dl ; second nibble
- and bl,0fh ; isolate
- mov al,hexchar[bx]
- stosb
- pop dx ; restore registers
- pop cx
- pop bx
- pop di
- ret ; return
-
-
- Cvh endp
-
- subttl ' - i/o subroutines'
- page
-
- GetC proc near ; return next byte in al
- push si ; or cf=1 for eof
- GetC1:
- dec inlen ; any left in buffer
- jge GetC2 ; yes, pick it up
- call GetBlk
- jb GetCX ;EOF or read error, return v1.3
- ;(AL=error if any) v1.3
- GetC2:
- mov si,inptr ; offset to next byte
- lodsb
- mov inptr,si
- add incurl,1 ; bump file offset
- adc incurh,0
- clc ;insure CF clear v1.3
- GetCX: ;v1.3
- pop si
- ret
- GetC endp
-
-
- GetBlk proc near ; read next block
- push bx
- push cx
- push dx
- mov ah,3fh ; read from handle
- mov bx,archdl ; arc file handle
- mov cx,INBUFSZ ; input buffer size
- mov dx,offset inbuf ; offset to input buffer
- mov inptr,dx
- int 21h
- jb GetBlkX ;read error, exit, AL=error v1.3
- or ax,ax ; anything read?
- jnz GetBlkA
- stc ; no, set cf=1 for eof,
- ;AL=ERRORLEVEL 0 (EOF) v1.3
- jmp short GetBlkX ; and exit
-
- GetBlkA:
- mov inlen,ax ; return count of bytes read
- GetBlkX:
- pop dx
- pop cx
- pop bx
- ret
-
- GetBlk endp
-
- subttl '--- i/o data areas'
- page
-
- ArcV endp
-
- archdr db 64 dup (0) ; i/o area for a header
-
- inbuf db INBUFSZ dup (0)
-
- CSEG ends
- end