home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
qbasic
/
qbarcv3.arc
/
QBARCV3.ASM
next >
Wrap
Assembly Source File
|
1989-03-21
|
31KB
|
1,250 lines
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