Category : C Source Code
Archive   : LHA211S.ZIP
Filename : SFX_.ASM
; sfx_.asm -- self-extract module
;***********************************************
page 0, 128
include amscls.inc
$_init GEN
_TEXT segment byte public 'CODE'
_TEXT ends
DGROUP group _BSS
assume cs:_TEXT, ds:DGROUP
CRC16 equ 0a001h
BufSiz equ 04000h
NC = (200h - 2)
NP = 14
NT = 19
NPT = 080h
CBIT = 9
PBIT = 4
TBIT = 5
DSIZ = 2000h
DSIZ2 = DSIZ * 2
LzHead struc
HeadSiz db ?
HeadChk db ?
HeadID db 3 dup (?)
Method db ?
db ?
PacSiz dw 2 dup (?)
OrgSiz dw 2 dup (?)
FTime dw ?
FDate dw ?
FAttr dw ?
FnLen db ?
Fname db 80h dup (?)
LzHead ends
_BSS segment para public 'BSS'
public crctbl
public cpyhdr, infile, outfile
public inpptr, inpbuf, text_
public curcrc, orgcrc
public myname
public pathname, fnnext, swchar
public blocksize_
text_ db DSIZ2 dup (?)
inpbuf db BufSiz dup (?)
crctbl dw 100h dup (?)
cpyhdr LzHead 1 dup ()
inpptr dw 1 dup (?)
infile dw 1 dup (?)
outfile dw 1 dup (?)
orgcrc dw 1 dup (?)
curcrc dw 1 dup (?)
blocksize_ dw 1 dup (?)
len_cnt dw 17 dup (?)
start dw 17 dup (?)
weight dw 17 dup (?)
public len_cnt
public start
public weight
left_ dw 2 * NC - 1 dup (?)
right_ dw 2 * NC - 1 dup (?)
c_table_ dw 4096 dup (?)
pt_table_ dw 256 dup (?)
c_len_ db NC dup (?)
pt_len_ db NPT dup (?)
public left_
public right_
public c_table_
public pt_table_
public c_len_
public pt_len_
bitbuf_ dw 1 dup (?)
subbitbuf_ db 1 dup (?)
bitcount_ db 1 dup (?)
myname db 80h dup (?)
pathname db 80h dup (?)
fnnext dw 1 dup (?)
fnptr dw 1 dup (?)
swchar db 1 dup (?)
endBBS label byte
_BSS ends
_TEXT segment byte public 'CODE'
assume cs:_TEXT
org 0100h
public start, main
public BSSseg
public #cright, crlf, space
public absent, #myself, broken, extend
public #subver
top:
jmp main
BSSseg = (#endofcode - top + 10fh) / 10h
mes_yn equ space - 1
space db ' ', 0
#cright db "LHA's SFX 2.11"
#subver db "L (c) Yoshi, 1991"
crlf db 13, 10, 0
absent db 'Rename to '
#myself db 'FILENAME.EXT', 0
overwt db 'Overwrite ', 0
yesno db '[Y/N] ', 0
broken db 'Broken file ', 0
write db 'Write', 0
header db 'Header', 0
crcmes db 'CRC'
error db ' Error', 0
auto db 1, '!'
autoflg db '.' shr 1
db 'BAT'
extend db 0ffh
attrib db 0
envseg = 002ch
cmdcnt = 0080h
cmdline = 0081h
;-----------------------------------------------
; C[`
;-----------------------------------------------
main:
cld
mov sp, offset top
mov ax, cs
add ax, BSSseg
mov es, ax
assume es:DGROUP
call @getopt
public #getopt
#getopt:
mov bx, offset #cright
call mesout
push es
pop ds
assume ds:DGROUP
;-----------------------------------------------
; Get my name
;-----------------------------------------------
mov ah, 30h
int 21h ; get DOS ver.
mov bx, ax
push ds
$_if
mov es, ss:[envseg]
xor ax, ax
mov di, ax
mov cx, -1
$_do
repne scasb
scasb
$_until , E
inc ax
scasw
push es
pop ds
mov dx, di
$_if , E
call openme
$_endif
$_endif
brknenv:
push cs
pop ds
mov dx, offset #myself
call openme
$_if
mov ax, ss:[0002h] ; get pathname from trash
sub ax, 38h ; of command.com
mov ds, ax
mov dx, 0009h
call openme
$_endif
mov bx, offset absent
jmp errout1
openme:
mov ax, 3d00h
int 21h ; Open Myself
$_if , C
ret
$_endif
pop cx ; pop old ip
pop ds
mov infile, ax
mov bx, ax
xor cx, cx
ifndef COM
exehdr = 20h
else
exehdr = 0h
endif
mov dx, (#endofcode - top) + exehdr
public #seeksize
#seeksize:
mov ax, 4200h
int 21h ; Move a File Pointer
$_if , C
brokenerr:
mov bx, offset broken ; Broken file
jmp errout
$_endif
push ds
pop es
;---------------------------------------
; make CRC table
;---------------------------------------
mov di, offset crctbl
xor dx, dx
$_do
mov ax, dx
mov cx, 8
$_do
$_if
xor ax, CRC16
$_endif
$_until
stosw
$_until
;---------------------------------------
public mainloop
mainloop:
$_while
call crlfout
; Get Header ---------------------------
mov si, offset DGROUP:cpyhdr.HeadSiz
mov dx, si
mov cx, 1
mov [si], ch
mov bx, infile
mov ah, 3fh
int 21h ; Read header size
dec cx ; cx = 0
add cl, [si]
$_if , Z
jmp exit
$_endif
inc dx
inc si
inc cx
mov ah, 3fh
int 21h ; Read header
; Test Header Sum ----------------------
lodsb
push si ; cpyhdr.HeadID
dec cx
dec si
$_do
inc si
sub al, [si]
$_until
jne errhdr
pop si
; Test Header ID -----------------------
lodsw
$_if
lodsw
xchg al, ah
sub ax, 'h0'
mov bp, ax ; bp = method
$_c , NZ, AND
$_c , NE, AND
$_c
lodsb
$_c , NZ
errhdr:
mov bx, offset header
jmp errout
$_endif
; Get original CRC ---------------------
mov bx, offset DGROUP:cpyhdr.Fname
mov dx, bx
mov cx, [bx - 1]
add bl, cl ; doesn't carry up
xchg ax, [bx] ; ax = 0, [bx] = CRC
mov orgcrc, ax
; Test Special File ? ------------------
mov fnptr, dx
cmp cx, 2101h ; 01h, '!'
$_if , E
mov ax, 1
jmp mn7
$_endif
call @extended
public #extended
#extended:
; Display File name --------------------
mov word ptr [bx], 0 * 256 + ' '
mov bx, dx
call disp ; output file name
mov byte ptr [bx - 1], 0
jcxz mn9 ; !.BAT ?
; Check Existence of File --------------
mov ax, 4300h ; get file attr
int 21h ; (for MS-DOS 3.3)
jc mn1
; Overwrite ? --------------------------
mov bx, offset overwt ; prompt
call mesout
call getyn
je mn1
; Skip to next File --------------------
mov dx, DGROUP:cpyhdr.PacSiz ; skip file
mov cx, DGROUP:cpyhdr.PacSiz + 2
mov bx, infile
mov ax, 4201h
int 21h ; Move a File Pointer
jmp mn6
mn9:
mov cs:autoflg, 0dh
; Create a New File --------------------
mn1:
mov cx, 0020h
mov ah, 3ch
int 21h ; Create a File
$_if , C
jmp errwrite
$_endif
; Decode -------------------------------
mn7:
mov outfile, ax
xor ax, ax
mov curcrc, ax
dec ax
mov inpptr, ax
push dx
$_if
call decode
$_else
call copyall
$_endif
pop si
; Set Time-Stamp -----------------------
mov bx, outfile
cmp bx, 1 ; file '!' ?
je mn8
mov dx, DGROUP:cpyhdr.FDate
mov cx, DGROUP:cpyhdr.FTime
mov ax, 5701h ; set date
int 21h
call close
; Check CRC ----------------------------
mov ax, curcrc
cmp ax, orgcrc
jne errcrc
call @setattr
public #setattr
#setattr:
jmp mn6
mn8:
call getyn
jne exit1
mn6:
$_enddo
mov bx, infile
call close
public exit
exit:
call @autoexec
public #autoexec
#autoexec:
exit1:
xor al, al
exit2:
mov ah, 4ch
int 21h
;-----------------------------------------------
; G[
;-----------------------------------------------
public errhdr, errwrite, errout
errcrc:
call unlink
mov bx, offset crcmes
jmp short errout1
errwrite:
mov bx, outfile
call close
call unlink
mov bx, offset write
errout:
call mesout
mov bx, offset error
errout1:
call mesout
mov al, 1
jmp exit2
;-----------------------------------------------
; get 'Y' or 'N'
;-----------------------------------------------
public getyn
getyn proc near
mov bx, offset yesno ; prompt
call mesout
$_do
mov ah, 08h
int 21h
and al, 0dfh
$_until
$_c
mov bx, offset mes_yn
mov cs:[bx], al
call mesout
cmp al, 'Y'
ret
getyn endp
;-----------------------------------------------
; obt@ÌoÍ
;-----------------------------------------------
public putbuf
public putbuf2
putbuf proc near
xor dx, dx ; mov dx, offset DGROUP:text_
mov cx, di
sub cx, dx
putbuf2:
jcxz return
mov bx, outfile
mov ah, 40h
int 21h
$_if , NE
cmp bx, 1
jne errwrite
$_endif
calccrc:
mov si, dx
mov bx, curcrc
; xor ah, ah ; ah = 0
; cld
$_do
lodsb
xor bl, al
mov al, bh
mov bh, ah
shl bx, 1
mov bx, crctbl[bx]
xor bx, ax
$_until
mov curcrc, bx
mov di, dx
cmp outfile, 1
je return
mov ah, 02h
mov dl, '.'
jmp short int21_ret ; int 21h
; ret
putbuf endp
;-----------------------------------------------
; »ÌÜÜoÍ
;-----------------------------------------------
public copyall
copyall proc near
xor di, di
$_while
mov bx, offset DGROUP:cpyhdr.OrgSiz
sub [bx], di
sbb word ptr 2[bx], 0
mov cx, DSIZ2
$_if , Z, AND
mov ax, [bx]
or ax, ax
jz cpyend
$_c
mov cx, ax
$_endif
xor dx, dx ; mov dx, offset DGROUP:text_
mov bx, infile
mov ah, 3fh
int 21h
push cx
call putbuf2
pop di
$_enddo
cpyend:
ret
copyall endp
;-----------------------------------------------
; t@CÌ close
;-----------------------------------------------
public close
close proc near
mov ah, 3eh
jmp short int21_ret ; int 21h
; ret
close endp
;-----------------------------------------------
; t@CÌí
;-----------------------------------------------
public unlink
unlink proc near
mov dx, fnptr
mov ah, 41h ; unlink
int21_ret:
int 21h
return:
ret
unlink endp
;-----------------------------------------------
; CR, LF ÌoÍ
;-----------------------------------------------
crlfout proc near
mov bx, offset crlf
crlfout endp
;-----------------------------------------------
; bZ[WÌoÍ
;-----------------------------------------------
public mesout
mesout proc near
push ds
push cs
pop ds
call disp
pop ds
ret
mesout endp
;-----------------------------------------------
; display ASCIZ char
;-----------------------------------------------
public disp
disp proc near
push ax
push dx
$_do
mov dl, [bx]
inc bx
mov ah, 02h
int 21h
$_until
pop dx
pop ax
ret
disp endp
;-----------------------------------------------
; getc
; ax: 1 byte (return)
;-----------------------------------------------
public getc
getc proc near
mov bx, inpptr
$_if
;-----------------------------------------------
; buffer üÍ
;-----------------------------------------------
public getbuf
getbuf proc near
push cx
push dx
mov dx, offset DGROUP:inpbuf
mov cx, BufSiz
mov bx, offset DGROUP:cpyhdr.PacSiz
sub [bx], cx
sbb word ptr 2[bx], 0
$_if , C
add cx, [bx]
$_endif
mov bx, infile
mov ah, 3fh
int 21h ; Read from an Archive
mov bx, dx
pop dx
pop cx
getbuf endp
;-----------------------------------------------
$_endif
mov al, [bx]
inc bx
mov inpptr, bx
ret
getc endp
;-----------------------------------------------
; extract routines
;-----------------------------------------------
public decode
decode proc near
xor ax, ax
mov blocksize_, ax
mov bitbuf_, ax
mov subbitbuf_, al
mov bitcount_, al
mov al,16
call fillbuf_
xor di, di ; mov di, offset DGROUP:text_
jmp $entry
$loop:
call decode_c_st1_
$_if
stosb
$_if
call putbuf
$_endif
$entry:
sub word ptr cpyhdr.OrgSiz, 1
jnc $loop
$_else
mov cx, ax
sub cx, 100h - 3
call decode_p_st1_
mov si, di
stc
sbb si, ax
push cx
$_do
and si, DSIZ2 - 1
movsb
test di, DSIZ2
$_if , NZ
push cx
push si
call putbuf
pop si
pop cx
$_endif
$_until
pop cx
sub word ptr cpyhdr.OrgSiz, cx
jnc $loop
$_endif
sbb word ptr cpyhdr.OrgSiz + 2, 0
jnc $loop
$endloop:
jmp putbuf
decode endp
; static void read_pt_len(short nn, short nbit, short i_special)
;public read_pt_len_
read_pt_len_ proc near
push si
mov al, dl
call getbits_
$_if
jmp brokenerr
$_endif
mov di, offset DGROUP:pt_len_
$_if
pop cx
rep stosb
mov al, dl
call getbits_
mov cx, 256
mov di, offset DGROUP:pt_table_
rep stosw
ret
$_else
mov dx, cx ; dl = i_special
add dx, di
mov si, di
add si, ax ; ax = n
$_do
mov al, 3
call getbits_
$_if
mov bx, bitbuf_
$_while
inc ax
$_enddo
push ax
sub al, 6
call fillbuf_
pop ax
$_endif
stosb
$_if
mov al, 2
call getbits_
mov cx, ax
xor al, al
rep stosb
$_endif
$_until
pop si ; nn
mov bp, offset DGROUP:pt_len_
lea cx, [bp + si] ; lea cx, DGROUP:pt_len_[si]
sub cx, di
xor al, al
rep stosb
mov ax, si
mov cx, 8
mov di, offset DGROUP:pt_table_
jmp make_table_
$_endif
read_pt_len_ endp
; static void read_c_len(void)
;public read_c_len_
read_c_len_ proc near
mov al, CBIT
call getbits_
$_if
jmp brokenerr
$_endif
mov di, offset DGROUP:c_len_
$_if
mov cx, NC
rep stosb
mov al, CBIT
call getbits_
mov cx, 4096
mov di, offset DGROUP:c_table_
rep stosw
ret
$_else
mov dx, di
add dx, ax ; ax = n
push di
$_do
mov ax, bitbuf_
mov bl, ah
xor bh, bh
shl bx, 1
mov bx, pt_table_[bx]
mov si, offset read_c_len_1
mov cx, NT
jmp tree1
if 0
$_while
$_if
mov bx, right_[bx]
$_else
mov bx, left_[bx]
$_endif
$_enddo
endif
read_c_len_1:
push bx
mov al, pt_len_[bx]
call fillbuf_
pop ax
$_if , BE
$_if , Z
mov al, CBIT
call getbits_
add ax, 20
mov cx, ax
$_else
$_if
mov al, 4
call getbits_
add ax, 3
mov cx, ax
$_else
mov cx, 1
$_endif
$_endif
xor al, al
rep stosb
$_else
stosb
$_endif
$_until
mov cx, offset DGROUP:c_len_ + NC
sub cx, di
xor al, al
rep stosb
mov ax, NC
pop bp
mov cx, 12
mov di, offset DGROUP:c_table_
jmp make_table_
$_endif
read_c_len_ endp
; ushort decode_c_st1(void)
decode_c proc near
; not entry here
decode_c_st1_2:
push di
mov al, 16
call getbits_
dec ax
mov blocksize_, ax
mov si, NT
mov dl, TBIT
mov cx, 3
call read_pt_len_
call read_c_len_
mov si, NP
mov dl, PBIT
mov cx, -1
call read_pt_len_
pop di
jmp decode_c_st1_3
;
; entry here
;
public decode_c_st1_
decode_c_st1_:
sub blocksize_, 1
jc decode_c_st1_2
decode_c_st1_3:
mov bx, bitbuf_
mov cl, 4
shr bx, cl
shl bx, 1
mov bx, c_table_[bx]
$_if
decode_c_st1_1:
push bx
mov al, c_len_[bx]
call fillbuf_
pop ax
ret
$_endif
mov ax, bitbuf_
shl al, cl
mov si, offset decode_c_st1_1
mov cx, NC
tree0:
$_do
$_if
mov bx, right_[bx]
$_else
mov bx, left_[bx]
$_endif
tree1:
$_until
jmp si
decode_c endp
; ushort decode_p_st1(void)
public decode_p_st1_
decode_p_st1_ proc near
;---------------------------------------------------------------
; ushort decode_p_st1(void)
;---------------------------------------------------------------
push cx
xor bh, bh
mov bl, byte ptr bitbuf_ + 1
shl bx, 1
mov bx, pt_table_[bx]
$_if
decode_p_st1_1:
push bx
mov al, pt_len_[bx]
call fillbuf_
pop ax
$_if
dec ax
mov cx, ax
call getbits_
mov bx, 1
shl bx, cl
or ax, bx
$_endif
pop cx
ret
$_endif
mov al, byte ptr bitbuf_
mov si, offset decode_p_st1_1
mov cx, NP
jmp tree0
if 0
$_do
$_if
mov bx, right_[bx]
$_else
mov bx, left_[bx]
$_endif
$_until
jmp decode_p_st1_1
endif
decode_p_st1_ endp
;---------------------------------------------------------------
; void make_table(short nchar, uchar bitlen[],
; ax bp
; short tablebits, ushort table[])
; cx di
;---------------------------------------------------------------
_BSS segment para public 'BSS'
avail_mt dw 1 dup (?)
nchar dw 1 dup (?)
bitlen dw 1 dup (?)
tablebits dw 1 dup (?)
table dw 1 dup (?)
restbits db 1 dup (?)
public avail_mt
public nchar
public bitlen
public tablebits
public table
public restbits
_BSS ends
public make_table_
make_table_ proc near
mov nchar, ax
shl ax, 1
mov avail_mt, ax
mov tablebits, cx
mov table, di
mov al, 16
sub al, cl
mov restbits, al
mov ax, 1
shl ax, cl
mov cx, ax
xor ax, ax
rep stosw
xor si, si
mov bx, 8000h
mov dx, 1
$_do
mov di, bp
mov cx, nchar
$_do
mov al, dl
repne scasb
jne mt1
mov ax, di
sub ax, bp
dec ax
push cx
push di
; ; bx = weight
; ; si = code
; ; dx = len
mov cl, restbits
mov di, si
shr di, cl
shl di, 1
add di, table
push bx
$_if
shr bx, cl
mov cx, bx
rep stosw
$_else
; /* ³ n Ì tree ðìé */
; ; di = taddr
; ; si =
; ; cx =
; ; ax = char
push si
mov cx, tablebits
shl si, cl
neg cx
add cx, dx
$_do
$_if
; /* }ªÜ¾ÑĢȯêÎìé */
mov bx, avail_mt
mov right_[bx], 0
mov left_[bx], 0
mov [di], bx
add avail_mt, 2
$_endif
mov di, [di]
$_if
add di, offset DGROUP:right_
$_else
add di, offset DGROUP:left_
$_endif
$_until
mov [di], ax
pop si
$_endif
pop bx
pop di
pop cx
add si, bx
jc mt2
$_until
mt1:
inc dx
shr bx, 1
$_until , C
public mt2
mt2:
ret
make_table_ endp
;-----------------------------------------------
; üÍ©çrbgð¾é
;-----------------------------------------------
;
;ushort getbits(uchar n)
;{
public getbits_
getbits_:
push cx
mov cl, 16
sub cl, al
push bitbuf_
call fillbuf_
pop ax
shr ax, cl
pop cx
ret
;
;void fillbuf(uchar n) /* Shift bitbuf n bits left, read n bits */
;{
public fillbuf_
fillbuf_:
push cx
push dx
mov ch, al
mov cl, bitcount_
mov dx, bitbuf_
mov al, subbitbuf_
$_if
sub ch, cl
shl dx, cl
rol al, cl
add dl, al
mov cl, 8
fb1:
call getc
$_if
sub ch, cl
mov dh, dl
mov dl, al
jmp fb1
$_endif
$_endif
sub cl, ch
mov bitcount_, cl
mov cl, ch
xor ah, ah
shl dx, cl
shl ax, cl
add dl, ah
mov bitbuf_, dx
mov subbitbuf_, al
pop dx
pop cx
ret
public #endofshort
#endofshort:
public @autoexec
@autoexec:
$_if
push cs
pop es
mov bx, (offset resident - top + 100h + 15) / 16
mov ah, 4ah
int 21h
push cs
pop ds
mov si, offset auto
int 2eh ; execute
$_endif
jmp #autoexec
resident:
;-----------------------------------------------
; Get options
;-----------------------------------------------
public @getopt
@getopt:
mov ax, 3700h
int 21h ; get switch char
mov si, cmdline
mov es:swchar, dl
mov es:fnnext, offset DGROUP:pathname
$_do
lodsb
$_if
$_if
$_c
lp0:
lodsb
cmp al, ' '
jbe lp1
or al, 20h
$_switch
$_case
shl cs:autoflg, 1
$_case
inc cs:extend
$_case
inc cs:attrib
$_default
cmp al, 'e'
jne lp0
lodsb
$_endswitch
$_endif
dec si
mov di, offset DGROUP:pathname
push si
call convert
pop si
push ax
mov al, '/'
call trans
mov al, '/'
$_if
$_c
stosb
$_endif
mov es:fnnext, di
pop ax
lp1:
$_endif
$_until
ret
public @extended
@extended:
mov si, dx
mov di, offset auto + 1 ; !.BAT ?
cmp cl, 5
jne mn5
push es
push cs
pop es
xor ch, ch
rep cmpsb
pop es
je mn2
; -x switch ----------------------------
mn5:
mov si, dx
mov cx, si
call convert
$_if
mov dx, cx ; last delim
$_endif
; -eDIRECTORY --------------------------
mov si, dx
mov al, [si]
$_if
mov di, fnnext
call trans
mov bx, di
mov dx, offset DGROUP:pathname
$_else
mov ax, word ptr DGROUP:pathname
$_if
dec dx
dec dx
mov di, dx
mov [di], ax ; brakes FnLen and
$_endif ; upper byte of FAttr
$_endif
; Make Directories ---------------------
mov si, dx
$_do
lodsb
$_if
mov byte ptr [si - 1], 0
mov ah, 39h ; make dir
int 21h
mov byte ptr [si - 1], '/'
$_endif
$_until
mov fnptr, dx
mov cx, 1
mn2:
ret
; Set File Attributes ------------------
public @setattr
@setattr:
$_if
mov dx, si
mov cl, byte ptr DGROUP:cpyhdr.FAttr
xor ch, ch
mov ax, 4301h
int 21h ; Set File Attributes
$_endif
ret
;-----------------------------------------------
; convert '\' to '/' & terminater
;-----------------------------------------------
conv proc near
$_do
$_if
$_c
mov byte ptr -1[si], '/'
mov cx, si
$_endif
; is kanji ---------------------
and al, 0e0h
shl al, 1
$_if , C, AND
$_c , PE
inc si
$_endif
; ------------------------------
convert:
lodsb
$_until
dec si
mov byte ptr [si], 0
ret
conv endp
;-----------------------------------------------
; transfer string
;-----------------------------------------------
trans proc near
$_do
mov ah, al
lodsb
stosb
$_until
dec di
ret
trans endp
public #endofcode
#endofcode:
_TEXT ends
end top
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/