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.
- ;v1.3 - FAAR RBBS reports this sucker runs once and then just returns
- ; a usage message (in the output file).
- ; Trying to find out why. Found it .. dumb mistake, not clearing
- ; variables between runs.
- ; - Adding true EOF testing for file pointer bumps.
- ; ZIP files have a good way to find EOF (e.g., the central directory),
- ; but PAK and ARC files don't.
- ; - Added some more error msgs.
- ; - Tightened hex output (CvH).
- ; - Reduced buffer sizes to minimum (archdr and inbuf).
- ;
- ;v1.4 - Adding the new Japanese .LHZ capability. Toad Hall
- ; See LHARC10E.ZIP (available on GEnie and BBS's) for details.
- ; - Neatening up total line.
- ; - Found some bugs in trying to predetermine ARC/PAK EOF.
- ; Fixed (hopefully).
- ; - Added a bunch of [bx] references .. saved 100 bytes!
- ; - Credits for LHARC (.LHZ) file header structure to:
- ; Daniel Durbin
- ; SysOp: Cygnus X-1 BBS | CIS: 73447,1744
- ; (805) 541-8505 (data) | GEnie: D.DURBIN
- ; EL major at PolySlo | ddurbin@polyslo.CalPoly.EDU
- ; from his LVIEW.C code.
- ;
- ;Fix - Correct bug that kept version 1.4 from functioning when linked
- ;08/23/89 with RBBS-PC that had been compiled using QB4.5 compiler.
- ; As it turned out it was an out and out bug that just did not
- ; happen to crash when RBBS-PC was compiled using QB3.0.
- ;
- ; Jon Martin AIRCOMM (415) 689-2090
- ;
- ;Fix - Correct bug that did not support Implode as valid ZIP compression
- ;09/02/89 type.
- ;
- ; Jon Martin AIRCOMM (415) 689-2090
- ;
- STDOUT equ 1 ;Standard Output v1.3
- STDERR equ 2 ;Std Error (console) v1.3
- FALSE equ 0
- TRUE equ NOT FALSE
- DEBUG equ FALSE
-
- Print macro name ; display a field
- mov dx,offset name
- call PrintS
- endm
-
- header struc ; archive header
- aMbrflag db 1AH ;unique ARC/PAK flag v1.3
- aCmpMeth db 0 ; compression code
- aMbrName db 13 dup (0) ; file name
- aCmpSiz dw 0,0 ; file size in archive
- aModDate dw 0 ; creation date
- aModTime dw 0 ; creation time
- aCrc16 dw 0 ; cyclic redundancy check
- aUncmpSiz 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
- zMbrName db ? ;filename (variable size)
- ;extra field (variable size)
- ZLocalEntry ENDS
-
- ZIPHDRLEN equ 30 ;length of initial ZIP hdr read v1.3
-
- ;v1.4 LZH header structure
-
- lzhlfh STRUC ;Local file header
- lUnk1 db ?,? ;char unknown1[2]; ;?
- lCmpMeth db 5 dup(?) ;char method[5]; ;compression method
- lCmpSiz dw ?,? ;long csize; ;compressed size
- lUncmpSiz dw ?,? ;long fsize; ;uncompressed size
- lModTime dw ? ;int ftime; ;last mod file time
- lModDate dw ? ;int fdate; ;last mod file date
- lFAttr db ? ;char fattr; ;file attributes
- lUnk2 db ? ;char unknown2; ;?
- lNameLen db ? ;char namelen; ;filename length
- lMbrName db ? ;char *fname; ;filename
- ;lCrc16 dw ? ;int crc; ;crc-16
- lzhlfh ENDS
-
- LZHHDRLEN equ 22 ;not including lMbrName or lCrc16
-
-
- 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
- ;v1.3a We aren't relying on the CF flag anymore to indicate errors.
- ; Instead, check AL.
- ; 0 = success
- ; 1 = command line parm error
- ; 2..6 are file-related (not found, etc.)
- ; 11 = Invalid format (probably didn't find a member header)
- ; 13 = invalid data (probably a bad file header structure)
- ; 18 = Unexpected EOF ('no further files to be found')
-
- Exit: mov sp,stkptr ; restore entry stack value
-
- push ax ;save error value v1.3
-
- ;v1.3 Numerous errors could be returned
-
- or al,al ;no errors?
- jz Exit_NoErr ;yep, ok
-
- mov bx,offset errtbl ;assume unknown error
- mov di,bx ;various error values
- mov cx,ERRTBLLEN ;table length
- repne scasb ;find the offset
- jnz Err_TblDone ;unknown, BX has table start
-
- dec di ;back up to actual error
- sub di,bx ;current psn - start = relative nr
- mov bx,di ;into BX for msg offset
-
- Err_TblDone:
- shl bx,1 ;*2 for words
- Err_Unk:
- add bx,offset errmsgtbl ;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:
-
- les ax,dword ptr CS:saveds ;recover calling seg regs 08/23/89
- ;(low word is orig DS) 08/23/89
- mov ds,ax ; 08/23/89
- ASSUME DS:NOTHING,ES:NOTHING ;a reminder
-
- pop ax ;restore error level v1.3
- xor ah,ah ;insure msb clear v1.3a
-
- 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
-
- even ;v1.3a
-
- stkptr dw 0 ; stack pointer upon entry
-
- arctitl db CR,LF,'Archive: ' ;keep this even v1.3a
- 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
-
- 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
-
- filelen dw 0,0 ;absolute archive file length v1.3a
- curpsn dw 0,0 ;remember current file pointer psn v1.3a
-
- 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
-
- ; display lines for verbose
-
- vhdr db CR,LF
- db CR,LF,'Name Length Stowage SF Size now Date Time CRC '
- db CR,LF,'============ ======== ======== ==== ======== ========= ====== ===='
- db CR,LF ;v1.4
- db STOPPER
-
- ;vline db CR,LF
- vline label byte ;v1.4
- 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 CR,LF ;v1.4
- db STOPPER
-
- hundred dw 100 ; for computing percentages
-
- ; final totals line
-
- vthdr db '------ --- -------- ---- --------',CR,LF ;v1.4
- db '*Total ' ;v1.4
- 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
- db 'Imploded' ;6 - New don't know format v1.6
-
- ;v1.4 LZH compression types are already coded as 5 chars of text
- ; in the compressed file.
- ; All we need to do is pad them out to the correct width.
-
- months db 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec '
-
- ARCPAK = 0 ; v1.3
- ZIP = 1 ; v1.4
- LZH = 2 ; v1.4
- ftype db ZIP ;flag which type file v1.3
-
- ;v1.4 4 types of archive file
-
- ziptype db 'ZIP'
- arctype db 'ARC'
- paktype db 'PAK'
- lzhtype db 'LZH' ;v1.4
- larctype db 'LZS' ;v1.4 not enabled for now
-
- ;zfilesig db 50H,4BH,03H,04H ;local file header signature v1.3
- ;zdirsig db 50H,4BH,01H,02H ;central file header signature v1.3
-
- ZSIG equ 4B50H ;unique ZIP signature v1.4
- ZFILESIG equ 0403H ;file member signature v1.4
- ZDIRSIG equ 0201H ;central file header signature v1.4
-
- ;v1.3 Centralizing errors at the exit point
-
- ; 1 = command line parm error
- ; 2..6 are file-related (not found, etc.)
- ; 11 = Invalid format (probably didn't find a member header)
- ; 12 = Invalid file type (not an ARC, PAK, ZIP)
- ; 13 = invalid data (probably a bad file header structure)
- ; 18 = Unexpected EOF ('no further files to be found')
-
- errtbl db 0,1,2,3,4,5,6,11,12,13,18,25,27,29,30 ;v1.3a
- ERRTBLLEN equ $ - errtbl
-
- errmsgtbl dw msg0,msg1,msg2,msg3 ;v1.3a
- dw msg4,msg5,msg6,msg11
- dw msg12,msg13,msg18,msg25
- dw msg27,msg29,msg30
-
- msg0 db 'Unknown error',0
-
- msg1 db 'Invalid function number',0
- msg2 db 'Archive file not found',0
- msg3 db 'Path not found',0
- msg4 db 'No handle available',0
- msg5 db 'Access denied',0
- msg6 db 'Invalid handle',0
- msg11 db 'Archive header error',0
- msg12 db 'Invalid file type',0
- msg13 db 'Archive format error',0
- msg18 db 'No further files to be found',0
- msg25 db 'Disk seek error',0
- msg27 db 'Disk sector not found',0
- msg29 db 'Write error',0
- msg30 db 'Read 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 DS:NOTHING,ES:CSEG ;a reminder v1.3a
-
- ;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,[si] ; get string offset v1.3a
- 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,[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,ES:CSEG ;a reminder v1.3a
-
- mov ax,STDERR ;assume no output filename v1.3a
- cmp temp,0 ;any output filename? v1.3
- jz Temp_Opened ;nope, use STDERR v1.3a
-
- ;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
-
- ;v1.3a mov ax,STDERR ;force to STDERR v1.3
- ;v1.3a 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
- ;CF set v1.3a
- 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
- mov ax,[di] ;snarf length v1.3a
- inc di ;bump to name proper v1.3a
- inc di ; v1.3a
- mov cx,ax ;into CX for scans to come v1.3a
- jcxz No_ArcName ;no length, ergo no name v1.3a
-
- 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_ArcName ;yep v1.3
-
- No_ArcName:
- mov al,2 ;'Archive file not found' v1.3
- ret ;back to Exit v1.3
-
- Got_ArcName:
-
- ;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
- jnz No_Paths ;nope, DI -> name start
-
- Got_Start:
- inc di ;bump up to the separator
- No_Paths:
- inc di ;bump to the first name char
- cld ;forward again
- mov fileptr,di ;remember real filename start
-
- ;v1.4 You MUST specify the type .. .ARC, .PAK, .ZIP, or .LZH.
- ; If .ARC or .PAK, we'll use the old code to display ARC-type
- ; files.
- ;v1.4 Else if ZIP or LZH, 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
-
- mov dx,di ;save pointer to file type v1.3
- ;(just past the separator) v1.3
- mov ax,3 ;3 chars constant
-
- 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
-
- mov ftype,ARCPAK ;ok, assume ARC or PAK v1.3a
-
- mov si,offset arctype ;is it an ARC? v1.3
- mov di,dx ;back to filename type
- 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
-
- ;v1.4 Adding .LZH types
- mov ftype,LZH ;ok, assume .LZH file v1.4
-
- mov si,offset lzhtype ;is it an LZH?
- mov di,dx ;back to filename type
- mov cx,ax ;3 chars
- repz cmpsb ;compare
- jz Got_Type ;a match
-
- BadType:
- mov al,12 ;'Invalid file type' v1.3a
- 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
- jnb ArcV1 ;ok
- jmp ArcV_X ;nope, return, AL=error v1.4
-
- ;v1.3a Display archive filename, header,
- ; then into a loop for each archive member.
-
- ArcV1: mov dx,fileptr ;pointer to filename v1.3a
- call PrintS ;display, CR/LF v1.3a
- jb ArcV_X ;output failed v1.3a
-
- Print vhdr
- jb ArcV_X ;output failed, AL = error v1.3
-
- ArcVNext:
- IF DEBUG
- Print debug1
- jmp short debugj1
- debug1 db 'Calling GetHdr',CR,LF,0
- debugj1:
- ENDIF
- call GetHdr ; load next header
- jb ArcV_NoHdr ;failed somehow, AL=error v1.3a
- ;(could be EOF, which is ok) v1.3a
- IF DEBUG
- Print debug2
- jmp short debugj2
- debug2 db 'Calling ArcVgo',CR,LF,0
- debugj2:
- ENDIF
- call ArcVgo ;format, write out file report
- jb Arcv_NoHdr ;something failed, AL=error v1.3a
-
- IF DEBUG
- Print debug3
- jmp short debugj3
- debug3 db 'Calling Bump_ArcPtrs',CR,LF,0
- debugj3:
- ENDIF
- call Bump_ArcPtrs ;bump to next archive file v1.3
- jnb ArcVNext ;loop if ok, else AL=error v1.3a
- ;(could be EOF) v1.3a
-
- ArcV_NoHdr:
- cmp archdr.aCmpMeth,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 ;AL=error v1.3a
-
- Start endp ; v1.3
-
-
- ;v1.3 Format, display single line for each member
- ; On success, return:
- ; CF clear
- ; AL = 0
- ; On error, return:
- ; CF set (because of output write fail)
- ; AL = error code
-
- ArcVgo proc near
- mov di,offset vname ; copy file name
- mov si,offset archdr.aMbrName
- mov cx,word ptr 13 ;up to 12 chars long, AsciiZ 0
- 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,offset archdr.aCmpSiz ;-> compressed size v1.4
- mov cx,[bx] ;.lo v1.4
- mov dx,2[bx] ;.hi v1.4
- mov bx,offset archdr.aUncmpSiz ;-> uncompressed size v1.4
- mov ax,2[bx] ;.hi v1.4
- mov bx,[bx] ;.lo v1.4
-
- 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:
- 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:
- 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 cx,word ptr 3 ;gonna need it in a sec v1.4
- cmp ftype,LZH ;LZH type? (compression method v1.4
- ; is already text) v1.4
- jnz ArcV_GetStyles ;nope v1.4
-
- ;v1.4 The LZH compression method (5 chars) is still in inbuf.
-
- mov si,offset inbuf.lCmpMeth ;-> 5-char compression v1.4
- ; method string v1.4
- mov di,si
- add di,5 ;point to beyond chars v1.4
- mov ax,' ' ;need 3 trailing blanks v1.4
- stosw
- stosb
- mov di,offset vstyle+1 ;indent to be neat v1.4
- jmp short ArcV_GotStyle ;skip v1.4
-
- ArcV_GetStyles: ; v1.4
-
- 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.aCmpMeth
- dec bl ;adjust for table offset v1.3
- ;v1.4 mov cl,3 ; eight bytes each entry
- ;v1.4 CX = 3 (eight bytes each entry)
- shl bx,cl ;*8
-
- add si,bx ;point into style table v1.3
- mov di,offset vstyle
-
- ArcV_GotStyle: ; v1.4
- inc cx ;CX=4=words to move v1.4
- rep movsw ; v1.3
-
- mov bx,offset archdr.aCmpSiz ;-> compressed size v1.4
- mov ax,[bx] ;.lo v1.4
- mov dx,2[bx] ;.hi v1.4
- mov bx,offset totsize ;-> accumulated compressed size v1.4
- add [bx],ax ;.lo v1.4
- adc 2[bx],dx ;.hi v1.4
-
- mov di,offset vsize ;format file size v1.3
- call Asciify_Long ; v1.3
-
- mov bx,offset archdr.aUncmpSiz ;-> uncompressed size v1.4
- mov ax,[bx] ;.lo v1.4
- mov dx,2[bx] ;.hi v1.4
- mov bx,offset totlen ;-> total length accumulator v1.4
- add [bx],ax ;.lo v1.4
- adc 2[bx],dx ;.hi v1.4
-
- mov di,offset vlength ;format file length v1.3
- call Asciify_Long ; v1.3
-
- mov ax,archdr.aModDate ; format file date
- call GetDate
-
- mov ax,archdr.aModTime ; format file time
- call GetTime
-
- mov ax,archdr.aCrc16 ; format crc in hex
- mov di,offset vcrc
- call Cvh
-
- inc totmbrs ;NOW bump total count v1.3a
- Print vline ; display this file info
- ;(may return error) v1.3a
- ret
-
- ArcVgo endp
-
-
- subttl '--- load next archive header'
- page
-
- ;v1.3 Adding ZIP file searching
- ;v1.3a For ARC/PAK files, now testing to see if we're at the archive
- ; file end. If so (a proper file), return with EOF (CF set
- ; but AL=0).
- ; Archive files may have picked up some garbage on the end
- ; (from XMODEM xfers, whatever). We'll see if we at LEAST have
- ; enough data for an archive header.
- ; If not, assume EOF, ignoring garbage.
- ; If there's more than 29 bytes of garbage .. the header will be
- ; garbage and we're gonna report a format error .. but that's ok for now.
- ; Zip files have a definite ending (the central directory,
- ; and they'll look out for their own endings.
- ;
- ; Also returning CF and AL per any errors.
-
- GetHdr proc near
-
- xor ax,ax ;handy 0
- mov archdr.aCmpMeth,al ;assume archive EOF
-
- cmp ftype,ZIP ;doing ZIP files?
- jnz GH_NotZip ;nope v1.4
- jmp Get_ZipHdr ;yep, they look out for themselves
-
- GH_NotZip:
- cmp ftype,LZH ;doing an LZH file? v1.4
- jnz GH_ArcPak_Hdr ;nope v1.4
- jmp Get_LZHHdr ;yep v1.4
-
- GH_ArcPak_Hdr: ; v1.4
-
- ;v1.3 New code
- ; ARC/PAK headers look like this:
- ;aMbrFlag db 1AH ;unique header flag
- ;aCmpMeth db 0 ; compression code
- ;aMbrName db 13 dup (0) ; file name
- ;aCmpSiz dw 0,0 ; file size in archive
- ;aModDate dw 0 ; creation date
- ;aModTime dw 0 ; creation time
- ;aCrc16 dw 0 ; cyclic redundancy check
- ;aUncmpSiz dw 0,0 ; true file size, bytes
-
- 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
- jnb GH_ChkHdr ;read ok v1.3a
- ret ;return CF set, AL=error v1.3a
-
- GH_ChkHdr:
- mov bx,dx ;DS:BX -> structure start v1.3a
-
- cmp [bx].aMbrFlag,ARCMARK ;start of header?
- jne Hdr_InvalFmt ;'invalid format', exit CF set
-
- mov al,[bx].aCmpMeth ;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
- ;but AL=0 = not a REAL error v1.3a
- cmp al,1 ; old format?
- jne GetHdrX ; if so, it's short
- mov si,offset archdr.aCmpSiz ; CPC15-1C
- mov di,offset archdr.aUncmpSiz ; CPC15-1C
- movsw ; v1.3
- movsw ; v1.3
- GetHdrX:
- xor al,al ;return AL=0, success v1.3a
- clc
- ret
-
- Hdr_InvalFmt:
- mov al,0BH ;'invalid format'
- Hdr_EarlyEOF: ; ;v1.4
- mov [bx].aCmpMeth,al ;signal EOF or invalid format v1.4
- Hdr_RetCF:
- stc ;return CF set, AL=error
- ret
-
- GetHdr endp
-
-
- Get_ZipHdr proc near
- ;v1.4 GetHdr Subroutine for ZIP files
- ;v1.3 Reads in ZIP 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
-
- call Read_Zip_Entry
- jb Get_ZHdrX ;failed, AL=ERRORLEVEL
-
- mov bx,offset inbuf ;use for field base
- mov di,offset archdr.aCmpMeth ;moving into this structure
-
- ;v1.4 Remember, the ZIP header we'll be snarfing data from
- ; looks like this:
- ;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
- ;zMbrName db ? ;filename (variable size)
- ;extra field (variable size)
- ;
- ; and the ARC/PAK record we'll be formatting to
- ; looks like this:
- ;aMbrFlag db 1AH
- ;aCmpMeth db 0 ; compression code
- ;aMbrName db 13 dup (0) ; file name
- ;aCmpSiz dw 0,0 ; file size in archive
- ;aModDate dw 0 ; creation date
- ;aModTime dw 0 ; creation time
- ;aCrc16 dw 0 ; cyclic redunancy check
- ;aUncmpSiz dw 0,0 ; true file size, bytes
-
- mov ax,[bx].zCmpMeth ;compression method
- inc al ;bump to be non-0
- stosb ;-> aCmpMeth
-
- ;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].zMbrName ;pointer to actual filename
- rep movsb ;do the move
- xor al,al ;terminating 0
- stosb
-
- mov di,offset archdr.aCmpSiz ;bump past name
-
- ; mov ax,[bx].zCmpSiz ;compressed size.lo
- ; stosw ; -> aCmpSiz
- ; mov ax,[bx].zCmpSiz[2] ;compressed size.hi
- ; stosw ; -> aCmpSiz[2]
- mov si,offset inbuf.zCmpSiz ;-> compressed size
- movsw ;aCmpSiz.lo
- movsw ;aCmpSiz.hi
-
- mov ax,[bx].zModDate ;last mod date
- stosw ; -> aModDate
- mov ax,[bx].zModTime ;last mod time
- stosw ; -> aModTime
- mov ax,[bx].zCrc32 ;CRC-32 value.lo
- stosw ; -> aCrc16
-
- ; mov ax,[bx].zUncmpSiz ;uncompressed size.lo
- ; stosw ; -> aUncmpSiz
- ; mov ax,[bx].zUncmpSiz[2] ;uncompressed size.hi
- ; stosw ; -> aUncmpSiz[2]
- mov si,offset inbuf.zUncmpSiz ;-> uncompressed size
- movsw ;aUncmpSiz.lo
- movsw ;aUncmpSiz.hi
-
- xor ax,ax ;return AX 0
- clc ;return CF clear
- Get_ZHdrX:
- ret
-
- Get_ZipHdr endp ;GetHdr subroutine
-
-
-
- Get_LZHHdr proc near
- ;v1.4 GetHdr Subroutine for LZH headers
- ; LZH file header has already been read in to inbuf.
- ;
- ; If all is ok, we move the appropriate LZH fields into the
- ; standard ARC/PAK structure (archdr) (so far as we can).
- ;
- ; Gleaning from the LHARCDOC documentation, the 'laCmpMeth' field
- ; (5 characters) can be:
- ; '-lh0-' stored as is (no compression)
- ; '-lh1-' compressed by LZHuf coding
- ; There appear to be at least two more possible compression codes
- ; that may appear: "LARC type 4 and type 5" (whatever they may be!).
- ;
- ; Assuming this field will ALWAYS be text, we are NOT gonna try to
- ; snarf some magic code number out of the field, but will just
- ; protect the field (in inbuf) and move the text directly into our
- ; formatted display line later.
- ;
- ; The only way we can test this as an LZH header is to look
- ; for a '-%%%-' starting at the 2d header byte (the laCmpMeth
- ; field).
- ;
- ; On success:
- ; DS:BX -> file entry directory structure
- ; CF clear
- ; Else CF set for failure
-
- ;v1.4 LZH files don't have a decent, clean EOF header.
- ; We have to test for near-EOF the hard way.
-
- mov di,offset archdr.aMbrFlag ;moving into this structure
- mov ax,001AH ;fake ARC/PAK flag
- stosw ; and EOF compression code
-
- xor ax,ax ;handy 0
- mov bx,offset filelen ;-> file length
- mov dx,[bx] ;file length.lo
- mov cx,2[bx] ;file length.hi
-
- mov bx,offset curpsn ;for fast access
- cmp cx,2[bx] ;length.hi = psn.hi?
- jnz GL_AddHdr ;nope
- cmp dx,[bx] ;length.lo = psn.lo?
- jz GL_TrueEof ;yep, we're exactly at EOF
-
- GL_AddHdr:
- sub dx,LZHHDRLEN ;sub header length
- sbb cx,ax ;0 ;handle the borrow
- jb GL_Eof ;<0, beyond EOF
- sub dx,[bx] ;- file psn.lo
- sbb cx,2[bx] ;- file psn.hi, minus any borrows
- jnb GL_NotEof ;not near end .. ok
-
- ;There must've been junk on the file end.
- ;However .. there ALWAYS seems to be junk on the end.
- ; So .. we'll return no message at all (AL=0)
- ;If we ever figure out how to detect a TRUE LZH EOF,
- ;we can enable this ERRORLEVEL=18 business.
-
- GL_Eof:
- ; mov al,18 ;'No further files to be found'
- GL_TrueEof:
- stc ;CF set for EOF v1.4
- ret
-
- GL_NotEof:
-
- push di ;save ptr -> archdr.aMbrName
- call Read_LZH_Entry
- pop di
- jb Get_LHdrX ;failed, AL=ERRORLEVEL
-
- mov bx,offset inbuf ;use for field base
-
- ;v1.4 Remember, the LZH header we'll be snarfing data from
- ; looks like this:
- ;lUnk1 db ?,? ;char unknown1[2]; ;?
- ;lCmpMeth db 5 dup(?) ;char method[5]; ;compression method
- ;lCmpSiz dw ?,? ;long csize; ;compressed size
- ;lUncmpSiz dw ?,? ;long fsize; ;uncompressed size
- ;lModTime dw ? ;int ftime; ;last mod file time
- ; ; (msdos format)
- ;lModDate dw ? ;int fdate; ;last mod file date
- ;lfAttr db ? ;char fattr; ;file attributes
- ;unknown2 db ? ;char unknown2; ;?
- ;lNameLen db ? ;char namelen; ;filename length
- ;
- ;lMbrName db ? ;char *fname; ;filename
- ;;lCrc16 dw ? ;int crc; ;crc-16
- ;
- ; and the ARC/PAK record we'll be formatting to
- ; looks like this:
- ;aMbrFlag db 1AH
- ;aCmpMeth db 0 ; compression code
- ;aMbrName db 13 dup (0) ; file name
- ;aCmpSiz dw 0,0 ; file size in archive
- ;aModDate dw 0 ; creation date
- ;aModTime dw 0 ; creation time
- ;aCrc16 dw 0 ; cyclic redundancy check
- ;aUncmpSiz dw 0,0 ; true file size, bytes
-
- mov al,[bx].lNameLen ;filename length
- and ax,15 ;constrain to max 12 chars
- mov cx,ax ;into CX for move
- mov si,offset inbuf.lMbrName ;-> actual filename
- rep movsb ;do the move
- xor al,al ;terminating 0
- stosb
-
- ;In LZH headers, the 2-byte CRC16 word lies immediately
- ;after the filename.
- ;Snarf it now and stuff in the ARC header.
-
- lodsw ;lCrc16
- push ax ;save a sec
-
- mov di,offset archdr.aCmpSiz ;bump past name
-
- ; mov ax,[bx].lCmpSiz ;compressed size.lo
- ; stosw ; -> aCmpSiz
- ; mov ax,[bx].lCmpSiz[2] ;compressed size.hi
- ; stosw ; -> aCmpSiz[2]
- mov si,offset inbuf.lCmpSiz ;-> compressed size
- movsw ;aCmpSiz.lo
- movsw ;aCmpSiz.hi
-
- mov ax,[bx].lModDate ;last mod date
- stosw ; -> aModDate
- mov ax,[bx].lModTime ;last mod time
- stosw ; -> aModTime
- pop ax ;CRC-16 value
- stosw ; -> aCrc16
- ; mov ax,[bx].lUncmpSiz ;uncompressed size.lo
- ; stosw ; -> aUncmpSiz
- ; mov ax,[bx].lUncmpSiz[2] ;uncompressed size.hi
- ; stosw ; -> aUncmpSiz[2]
- mov si,offset inbuf.lUncmpSiz ;-> uncompressed size
- movsw ;aUncmpSiz.lo
- movsw ;aUncmpSiz.hi
-
- xor ax,ax ;return AX 0
- clc ;return CF clear
- Get_LHdrX:
- ret
-
- Get_LZHHdr endp ;GetHdr Subroutine v1.4
-
-
- Read_LZH_Entry proc near ;GetHdr Subroutine v1.4
-
- mov dx,offset inbuf ;read into here
- mov cx,LZHHDRLEN ;entry structure size
- ;(does NOT include variable
- ; length filename, and the
- ;two CRC bytes following the
- ;filename)
- mov bx,archdl ;file handle
- call ReadZ_It ;try to read in header
- ;(up to filename)
- jb ReadL_Eof ;failed, AL=error
-
- mov si,dx ;structure start
- mov al,'-' ;test for '-l%-' or whatever
- cmp [si].lCmpMeth,al ;first part of compression
- ;method string?
- jnz ReadL_InvalDat ;bogus, failed
- cmp [si].lCmpMeth+4,al ;how about last char?
- jz ReadL_Ok1 ;yep, fine
- ReadL_InvalDat:
- mov al,0DH ;force to 'invalid data'
- ReadL_Eof:
- mov archdr.aCmpMeth,al ;set per EOF or error
- stc ;return CF set
- ret
-
- ReadL_Ok1:
- mov dx,offset inbuf.lMbrName ;-> lMbrName psn
- mov cl,inbuf.lNameLen ;length of member filename
- xor ch,ch ;clear msb
- call ReadZ_It ;read in the name
- jb ReadL_Eof ;failed
- add dx,cx ;bump buff ptr past name
- mov cx,2 ;LZH CRC is a word
- call ReadZ_It ;read in the CRC word
- jb ReadL_Eof ;failed
- ret ;success
-
- Read_LZH_Entry endp ;GetHdr Subroutine v1.4
-
-
- Read_Zip_Entry proc near ;GetHdr Subroutine
-
- mov dx,offset inbuf ;read into here
- mov cx,ZIPHDRLEN ;entry structure size
- ;(does NOT include filename or
- ; Extra fields, which are
- ;dynamic)
- mov bx,archdl ;file handle
- call ReadZ_It ;try to read in header
- ;(up to filename)
- jb ReadZ_Eof ;failed, AL=error v1.3a
-
- mov si,dx ;->file signature v1.4
- lodsw ;snarf first 2 chars v1.4
- cmp ax,ZSIG ;ZIP header? v1.4
- jnz ReadZ_InvalDat ;nope, bogus v1.4
- lodsw ;file or central sig v1.4
- cmp ax,ZFILESIG ;next member? v1.4
- jz ReadZ_Ok1 ;yep, fine v1.4
- cmp ax,ZDIRSIG ;central directory? v1.4
- ;(means we're done) v1.4
- mov al,0 ;assume yes, EOF v1.4
- jz ReadZ_Eof ;yep v1.4
-
- ReadZ_InvalDat:
- mov al,0DH ;'Invalid data' v1.4
- ReadZ_Eof: ; v1.3a
- mov archdr.aCmpMeth,al ;set per EOF or error v1.3a
- stc ;return CF set v1.3a
- ret
-
- ReadZ_Ok1:
- mov dx,offset inbuf.zMbrName ;move to zFilename psn
- mov cx,inbuf.zNameLen ;length of member filename
- ;fall thru to ... v1.3a
-
- ;v1.4 Common subroutine for ReadZ and Read_LZH
- ; DX -> buffer
- ; CX = bytes to read
- ; BX MUST have archdl .. so protect BX!
-
- ReadZ_It:
- mov ah,3FH ;read from file/device
- int 21H
- jb ReadZ_ItX ;failed, error in AX v1.3a
-
- ;v1.4 We'll update our curpsn file pointers later
- ; when we try to read past compressed file contents.
-
- ;v1.4 add curpsn,ax ;bump current file ptr v1.3a
- ;by amount read v1.3a
- ;v1.4 adc word ptr curpsn[2],0 ;bump psn.hi if carry v1.3a
-
- cmp ax,cx ;read all we expected?
- mov ax,0 ;clear AX v1.3a
- jz ReadZ_ItX ;yep, return CF clear v1.3a
- mov al,0BH ;assume unexpected EOF
- ;('invalid format')
- stc
- ReadZ_ItX:
- ret ;CF, AL set per error v1.3a
-
- Read_Zip_Entry endp ;GetHdr subroutine
-
-
- ;v1.3 Common subroutine
- ; Bumps archive file pointers to next entry
- ; On success, return:
- ; CF clear
- ; AL = 0
- ; On failure (e.g., couldn't move ptrs), return:
- ; CF set
- ; AL = error
-
- 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 bx,offset archdr.aCmpSiz ;-> encoded file length v1.4
- mov dx,[bx] ;.lo v1.4
- mov cx,2[bx] ;.hi
- 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
- jb Bump_X ;seek error v1.3a
- ;return CF set, AL=error v1.3a
-
- ;v1.4 Updating curpsn variables now
- ; so the NEXT GetHdr call will have current data.
- mov bx,offset curpsn
- mov [bx],ax
- mov 2[bx],dx
- xor ax,ax ;AX,CF clear v1.3a
- Bump_X:
- 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 bx,offset totlen ;-> total actual file size v1.4
- mov ax,[bx] ;.lo v1.4
- mov dx,2[bx] ;.hi v1.4
-
- push ax ;save totlen.lo v1.4
- push dx ; and totlen.hi v1.4
-
- mov di,offset vtlen ;format total actual file size v1.3
- call Asciify_Long ; v1.3
-
- mov bx,offset totsize ;-> total compressed file sizes v1.4
- mov ax,[bx] ;.lo v1.4
- mov dx,2[bx] ;.hi v1.4
-
- push ax ;save totsize.lo v1.4
- push dx ; and totsize.hi v1.4
-
- mov di,offset vtsize ;format total archive file size v1.3
- call Asciify_Long ; v1.3
-
- ; reduce the total size/length to word values
-
- pop dx ;totsize.hi v1.4
- pop cx ;totsize.lo v1.4
- pop ax ;totlen.hi v1.4
- pop bx ;totlen.lo v1.4
-
- 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
-
-
- OpenArc proc near ; open new archive
-
- mov dx,offset arcname
- mov ax,3d00h ; for input
- int 21h
- jnb Open_GetSize ;opened ok v1.3a
- ret ;return CF set, AL=error v1.3a
-
- Open_GetSize:
- mov bx,ax ;handle into BX v1.3a
- mov archdl,ax ; save file handle
-
- ;v1.3a We get the total file size now for later EOF testing.
- xor dx,dx ;0 offset
- xor cx,cx
- mov ax,4202H ;from file end
- int 21H
- mov filelen,ax ;length.low
- mov filelen[2],dx ;length.hi
- xor cx,cx ;back to start
- xor dx,dx
- mov ax,4200H ;psn file pointer from start
- int 21H
- ret ;CF should be clear
-
- 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 ;flag as closed
- ret
-
- ClosArc endp
-
- ;
- ; print null-terminated (AsciiZ) string like int 21h function 9
- ; Enter with DS:DX -> AsciiZ string
- ; destroys AX
- ; On success, return:
- ; CF clear
- ; AL = 0
- ; On failure (write fail), return:
- ; CF set
- ; AL = error
-
- 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 di,ax ;save error level v1.3a
- mov bx,STDERR ;force to STdErr v1.3a
- mov outhdl,bx ;and for future output v1.3a
- mov ah,40H ;write to STDOUT v1.3a
- int 21H ;(CX,DX unchanged) v1.3a
- mov ax,di ;restore orig error v1.3a
- stc ;return CF set v1.3a
-
- 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
-
-
- ;v1.3a Convert 16-bit binary word in AX
- ; to hex ASCII string at ES:DI
- ; (No need to save any registers)
-
- hexchar db '0123456789ABCDEF'
-
- Cvh proc near
-
- mov si,offset hexchar ;for faster access v1.3a
- mov dx,ax ; save 16-bits
-
- mov bl,dh ; third nibble
- mov cx,0F04H ;CL=4 for shifting, v1.3a
- ;CH=0FH for masking v1.3a
- shr bl,cl
- mov al,[si][bx] ;snarf hex char v1.3a
- stosb
-
- mov bl,dh ; last nibble
- and bl,ch ;0fh ; v1.3a
- mov al,[si][bx] ;snarf hex char v1.3a
- stosb
-
- mov bl,dl ; first nibble
- sub bh,bh
- shr bl,cl ; isolate (CL still 4) v1.3a
- mov al,[si][bx] ;snarf hex char v1.3a
- stosb
-
- mov bl,dl ; second nibble
- and bl,ch ;0fh ; isolate v1.3a
- mov al,[si][bx] ;snarf hex char v1.3a
- stosb
- ret
-
- Cvh endp
-
- subttl '--- i/o data areas'
-
- ArcV endp
-
- archdr db 30 dup (0) ; i/o area for a header v1.3a
-
- inbuf db INBUFSZ dup (0) ;just big enough for ZIP
- ;directories and filenames v1.3a
-
- CSEG ENDS
- END