Category : Utilities for DOS and Windows Machines
Archive   : PKLXTRA.ZIP
Filename : PKLXTRA.ASM

Output of file : PKLXTRA.ASM contained in archive : PKLXTRA.ZIP
; File: PKLXTRA.ASM System: Utility Version: 1.00 Date: 12-15-91 ;

; PKLXTRA.COM reduces size of COM files that have already been compressed by
; Phil Katz's PKLITE. Tested with non-commercial version 1.12 and earlier.
ASSUME CS:Code_Seg,DS:Code_Seg,ES:Code_Seg,SS:Code_Seg

MOVE EQU xchg ; Use for some AX register-register moves
EOL EQU <13,10>
STACKSIZE EQU 200h ; Matches PKLITE-reserved size
PKSIZE EQU 1C0h ; Length of PKLITE header in COM file
BUFLEN EQU 0F000h ; Sufficient for PKLITE-compressed COM files

ORG 100h
Start: jmp Ahead

Info = $
DB "Syntax: PKLXTRA [filename.COM]" ,EOL
DB "Utility further compresses PKLITE-compressed COM files, disabling" ,EOL
DB "-X option. This overwrites file, so back it up first. Beep means",EOL
DB "error, e.g., read-only file, wrong PK signature, etc. Saves 200+" ,EOL
DB "bytes at cost of slower in-RAM expansion. Also preserves initial" ,EOL
DB "register values passed from DOS, which may enable some compressed" ,EOL
DB "COM files to run that previously did not. Result COM file beeps" ,EOL
DB "(instead of message) if not enough memory at runtime." ,EOL
DB "CRH/15 Dec 91" ,EOL,"$"

InfoExit: mov dx,OFFSET Info
mov ah,9
int 21h
toret: ret

Int21h: int 21h
jnc toret
toabort: jmp Abort ; To beep exit in Stub area

Ahead: cmp sp,0FF00h ; Need about 64K
jc toabort ; No room? Abort

mov ax,3000h
int 21h ; Get DOS version
test al,al
je toabort ; DOS 1.xx? Abort

mov di,81h
mov cl,[di-1]
mov ch,0
jcxz InfoExit ; No argument? Display syntax

mov al,' '
repe scasb
mov dx,di
dec dx ; Filename offset
add di,cx
mov [di],ch ; Make ASCIIZ
mov ax,3D02h
call Int21h ; Open read/write
MOVE bx,ax ; Handle fixed here for duration
mov dx,OFFSET Buffer
mov cx,BUFLEN
mov ah,3Fh
call Int21h ; Read
cmp ax,cx ; Insure read-size smaller than buffer
jnb toabort ; No? Abort

mov di,dx ; In case odd length file, append 0 byte
add di,ax
xor dx,dx
mov BYTE PTR [di],dl
shr ax,1 ; Convert odd AX to next larger even number
adc ax,dx
shl ax,1
sub ax,PKSIZE ; Insure packed data size matches that
cmp ax,Buffer+4 ; indicated in PK startup stub
jne toabort ; No? Abort

cmp Buffer+44,10Ch ; Insure proper compression code (?)
jne toabort ; No? Abort

cmp Buffer+46,'KP' ; Insure PK signature present
jne toabort ; No? Abort

xor cx,cx ; DX still zero
mov ax,4200h
call Int21h ; Rewind
call FixUp ; Ready buffer image, returning DX/AX
MOVE cx,ax
mov ah,40h
call Int21h ; Write
xor cx,cx
mov ah,40h
jmp Int21h ; Truncate and close on exit
; Fix up Stub and Decoder, then copy to Buffer. Return offset/length DX/AX.
FixUp: mov ax,Buffer+1 ; Fetch minimum SP from startup code
sub ax,STACKSIZE ; Now matches EndDcdr offset after move
add WORD PTR FixSP+2,ax
add WORD PTR FixDI+1,ax
add WORD PTR FixLo+2,ax
add WORD PTR FixHi+2,ax
sub ax,OFFSET EndDcdr + 200h - OFFSET Stub
add WORD PTR FixJmp1+1,ax
sub WORD PTR FixJmp2+1,ax
mov ax,Buffer+4 ; Fetch data byte count from startup code
add WORD PTR FixSI+1,ax
shr ax,1
add WORD PTR FixCX+1,ax
shl ax,1
mov di,OFFSET Buffer + PKSIZE
mov si,OFFSET Stub
mov cx,OFFSET Decoder - OFFSET Stub
sub di,cx
mov dx,di ; Save offset for return
rep movsb ; Copy Stub before packed data
add di,ax ; Still data byte count in AX
mov cx,OFFSET EndDcdr - OFFSET Decoder
rep movsb ; Copy decoder after packed data
add ax,OFFSET EndDcdr - OFFSET Stub
; Stub and Decoder are just data, except for beep exit shared with program.
EVEN ; Like eventual 100h offset
Stub: pushf ; Save registers, preserving, e.g., AH/AL
push ax ; drive existence info--PKLITE does not
push bx
push cx
push dx
push bp
push si
push di
FixSP: cmp sp,STACKSIZE - 16
jb Abort ; Beep and exit on room error

FixDI: mov di,-2
FixSI: mov si,OFFSET EndDcdr + 100h - OFFSET Stub - 2
FixCX: mov cx,(OFFSET EndDcdr - OFFSET Decoder) / 2
rep movsw ; Move decoder and data high

scasw ; Bump DI twice--CX is zero from above
mov si,di ; Start of packed data
mov di,100h ; Unpack destination
xor bp,bp ; No reliance on DOS defaults
lodsw ; Fetch first code word, zero AH/DH,
xchg bp,ax ; and set DL to BP bit count
mov dx,10h
FixJmp1: jmp Enter + 100h ; Extra 100h insures near jump before fix

Abort: mov ax,0E07h ; Beep exit instead of message exit
int 10h
int 20h

Decoder: call GetBit
GetBit2: call GetBit
GetBit: shr bp,1 ; Short routine to roll next code bit from
dec dx ; BP into BX--code words are interspersed
jne gbup ; with data words in packed data

lodsw ; Load next code word, if necessary
xchg bp,ax ; Also rezeroes AH
mov dl,10h ; DH zero throughout
gbup: rcl bx,1

hi1: call GetBit ; Top of loop
cmp bl,8
jc hi5

call GetBit
cmp bl,17h
jc hi5

call GetBit
and bx,0DFh
xchg bl,bh
jmp SHORT hi6

hi2: movsb
Enter: call GetBit ; Loop entry point
rcr bx,1
jnc hi2

xor bx,bx ; CX also zero
call GetBit2
test bx,bx
je hi3

call GetBit
cmp bl,6
jc hi3

call GetBit
hi3: mov cl,(OFFSET LoTbl - OFFSET EndDcdr)[bx]
cmp cl,0Ah
je hi7

hi4: xor bx,bx
cmp cx,2
je hi6

call GetBit
rcr bx,1
jc hi6

call Decoder
cmp bl,2
jnc hi1
hi5: mov bh,(OFFSET HiTbl - OFFSET EndDcdr)[bx]
hi6: lodsb
mov bl,al
push si
mov si,di
sub si,bx
rep movsb
pop si
jmp Enter

hi7: lodsb
add cx,ax ; AH is zero
cmp al,255
jne hi4 ; Bottom of loop

pop di ; Restore COM start environment
pop si
pop bp
pop dx
pop cx
pop bx
pop ax
FixJmp2: jmp Stub - 100h ; Extra 100h insures near jump before fix

LoTbl: DB 03h, 00h, 02h, 0Ah, 04h, 05h, 00h, 00h
DB 00h, 00h, 00h, 00h, 06h, 07h, 08h, 09h
HiTbl: DB 01h, 02h, 00h, 00h, 03h, 04h, 05h, 06h
DB 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h
DB 07h, 08h, 09h, 0Ah, 0Bh, 0Ch, 0Dh

Buffer LABEL WORD ; File I/O buffer

Code_Seg ENDS
END Start

  3 Responses to “Category : Utilities for DOS and Windows Machines
Archive   : PKLXTRA.ZIP
Filename : PKLXTRA.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: