Нет, ну, ты, мёртвого заколебёшь... :) Разбирайся сам

Нет, ну, ты, мёртвого заколебёшь...:) Разбирайся сам - это точно рабочее:
;[]------------------------------------------------------------------[]
; Start of Decompress Engine
;[]------------------------------------------------------------------[]

;[]==============================================================[]
;Entry: ES : SEGMENT of Source Data
; BX : OFFSET of Source Data
; DX : Segment of Expand Data buffer
;if BP=0 -> it`s no BIOS-file
;Exit: ECX: Compressed Size
; EDX: Original Size
;[]==============================================================[]
Expand:
;vyvod msg_tochka
push ds
push si
push di
push bx
assume ds, EXP_DATA

; Init data segment registers
mov [cs:unpack_seg], dx ;store segment where to unpack

push es ; save source segment

;Initialize EXP_DATA segment, in case there's garbage left
assume es, EXP_DATA;fx00;ds
xor di, di
mov cx, length_exp_data;4000h
rep stosb;w
pop es

; Read compressed data from segment:offset
;assume - fos seg->seg operations
push es
mov [ds:SrcSegment], es
mov [ds:SrcOffset], bx
mov [cs:temp_word], bx ;store TEMP for save files...
; Temp Target Segment, Offset

; make CRC table
call MakeCRCTable
; read header
call ReadHeader
jc error_exit_decompress ; error, something wrong

;-- calculate compressed total size and return when decompress complete
mov ecx, [ds:compsize] ;compressed size
xor eax, eax
mov al, [ds:headersize] ;compressed header size
add ecx, eax
add ecx, COMPRESSED_UNKNOW_BYTE;unknow bytes
mov edx, [ds:origsize]
;now in ECX - compressed size, in EDX - original size
cmp bp, 0 ;check - it`s decompress for BIOS or another files?...
jne BIOSpart

;bp=0 -> it`s no BIOS-part...
assume [ds:TgtSegment], [cs:unpack_0]
assume [ds:TgtOffset], 0 ;clear offset
jmp go_decompress

BIOSpart:

;----output EXTEND INFO--------------------------------------------
cmp byte [cs:Extend_Info], 1
jne .skip_Extend_Info
BK
pushad
push ds
push es
push ecx
assume es, [ds:SrcSegment]
mov di, [cs:temp_word];- becose [ds:SrcOffset] is changing to begin of 'compressed_data'
assume ds, es

;output PART_NAME
mov dx, di
add dx, 16h ;=begin of NAME_FIL in LHA-header
movzx cx, [es:di+15h] ;=length of NAME_FIL
cmp cx, 12
jbe @F
mov cx, 12 ;cut CX if more than 12 (for aligning on next step)
@@:
push cx
mov bx, 1 ;output to screen
mov ah, 40h
int 21h
;aligning...
pop ax ;length of NAME_FIL in AX
mov cx, 13
sub cx, ax
@@:
._.
loop @B
;output SEG_OFF_Target
._.
mov ecx, [es:di+0fh]
_test32reg ecx
;output Compress Size
._.
mov ecx, [es:di+7]
_test32reg ecx
;output Real Size
vyvod msg_slash
mov ecx, [es:di+0bh]
_test32reg ecx
pop ecx ;restore length of BIOS-part
._.

;for ultrapack---------------
cmp dword [es:di+0fh], 50000000h
je .skip_ultrapack
cmp byte [cs:ultrapack], 1
jne .skip_ultrapack
BK
vyvod msg_for_remove_this_module_press_r_or_any_another_key_for_continue;
;wait for key...;
mov ah ,1;
int 21h;
;check press key...;
cmp al, 'r';
je .skip_ultrapack;
cmp al, 'R';
je .skip_ultrapack;

write_file_check [cs:id_ost_rrr], [cs:temp_word], cx;write ost.rrr
.skip_ultrapack:
;end ultrapack-operations=====[]

pop es
pop ds
popad

mov ax, [ds:ExpSegment]

cmp ax, 4000h ;microcodes
jne @F
vyvod msg_its_logo
@@:
cmp ax, 4001h ;microcodes
jne @F
vyvod msg_its_cpucode_bin
@@:
cmp ax, 4002h ;EPA
jne @F
vyvod msg_its_EPA
@@:
cmp ax, 4003h ;ACPITBL
jne @F
vyvod msg_its_ACPITBL
@@:

cmp ax, 4007h ;antivirus
jne @F
vyvod msg_its_antivirus
@@:

cmp ax, 4029h ;Phoenix_Setup
jne @F
vyvod msg_its_Phoenix_Setup
@@:

cmp ax, 4080h ;VGA
jne @F
vyvod msg_its_VGA
@@:

cmp ax, 0800h ;~scsi
jne @F
vyvod msg_may_be_scsi
@@:

cmp ax, 4086h ;ncr
jne @F
vyvod msg_its_ncr_4086
@@:
cmp ax, 4087h ;aha
jne @F
vyvod msg_its_aha_4087
@@:

cmp ax, 5000h ;original
jne @F
vyvod msg_its_original_tmp
@@:
cmp ax, 407fh ;awardext
jne @F
vyvod msg_its_awardext_rom
@@:
cmp ax, 4100h ;awardext
jne @F
vyvod msg_its_awardext_rom
@@:
cmp ax, 6000h ;awardext
jne @F
vyvod msg_its_awardext_rom
@@:
cmp ax, 400eh ;awardeYt
jne @F
vyvod msg_its_awardeyt_rom
@@:

cmp ax, 4e00h ;rom.by
jne @F
vyvod msg_its_rom_by_modul
@@:

cmp ax, 5000h ;...this compare must be in the end...
jbe .skip_Extend_Info
cmp ax, 6FFFh
ja .skip_Extend_Info
vyvod msg_its_original_tm1 ;second part of original.tmp

.skip_Extend_Info:
;=== END Extend_Info =====================================================[]
;vsad
mov ax, [ds:ExpSegment] ;[cs:unpack_seg];

;new unpack/save-method - expand to unpack_0/unpack_1 and after select-saving...
assume [ds:TgtSegment], [cs:unpack_0]
assume [ds:TgtOffset], 0 ;clear offset

; cmp dword [cs:TCCS], 0
; je @F
cmp ax, 4001h ;it`s 'cpucode.bin'?
je @F ;yes - skip (becose it release with cbrom in future)...

add [cs:TCCS], ecx ;add compressed size of this part...
;pushad
;vyvod msg_tochka
; mov ecx, [cs:TCCS] ;add compressed size of this part...
;_test32reg ecx
;popad
@@:
cmp ax, 4086h
jne @F
mov [cs:ncr_exist], ecx
@@:
cmp ax, 4087h
jne @F
mov [cs:aha_exist], ecx
@@:
cmp ax, 4007h
jne @F
mov [cs:vrs_exist], ecx
@@:

cmp ax, 4001h ;cpucode.bin
je decompress_cpucode
cmp ax, 4029h ;_en_code.bin
je decompress__en_code_tmp
cmp ax, 4100h ;awardext.rom
je decompress_awext
cmp ax, 407fh ;awardext.rom
je decompress_awext
cmp ax, 6000h ;ASUS-awardext.rom
je decompress_awext
cmp ax, 5000h
je decompress_orig
jb _done_exit ;it`s not a 'awardext.rom' or 'original.tmp''(1)'
cmp ax, 6FFFh
ja _done_exit ;it`s not a 'awardext.rom' or 'original.tmp''(1)'

;it`s second half of tiled BIOS...
jmp go_decompress
;cpucode.bin...
decompress_cpucode:
jmp go_decompress
;_en_code.bin...
decompress__en_code_tmp:
jmp go_decompress
;awardext.rom...
decompress_awext:
jmp go_decompress
;original.tmp...
decompress_orig:

go_decompress:
push edx
push ecx

;check data is store type or compress type
push bx
add bx, 5 ;offset 5 ('-lh0-' or '-lh5-')
call Get_Exp_Src_Byte ;get compress or store type value
pop bx
cmp al, '0' ;Is store type?
jne Not_Store ;No, jump

;-lh0- type...
push ds
push si
push bx
mov di, [ds:ExpOffset]
movzx ax, byte [ds:headersize];compressed header size
add ax, 2 ;store unknow bytes
add bx, ax
mov cx, word [ds:compsize];compressed size
mov ax, [ds:ExpSegment]
mov es, ax
add cx, 3 ;transfer to dword unit
shr cx, 2 ;-------

Get_Store_Data_Loop:
call Get_Exp_Src_Dword ;get compress or store type value
add bx, 4 ;next data offset
stosd ;store to buffer
loop Get_Store_Data_Loop

pop bx ;restore BX
pop si
pop ds
jmp Expand_Over

;-lh5- type...
Not_Store:
push word [ds:TgtSegment]
push word [ds:TgtOffset]
push dword [ds:origsize]

; extract content from compressed file
call Extract

pop dword [ds:origsize]
pop word [ds:TgtOffset]
pop word [ds:TgtSegment]

Expand_Over: ;R137
;;722; clean up temp target buffer, so that no garbage left in user's base memory
;;722; if data decompression stub is called before memory testing, then
;;722; we don't need to call this cleanup routine.
;;722 call CleanUpBaseMemory
pop ecx ;return compressed total size
pop edx

; done, exit.
_done_exit:
clc
error_exit_decompress:
pop es
pop bx
pop di
pop si
pop ds
ret















;********************************************************************
;********************* LHA subs *************************************
;********************************************************************

MakeCRCTable:
; Input : None
; Destroy : None
; Modify Global Variable : CRCTABLE[]
push cx
push bx
push ax
push si
mov si, crctable;offset of crctable->si
mov cx, 100h ; for (i = 0; i <= 0xff; i++)

MCRCT_1:
mov ax, 100h
sub ax, cx ; r = i;
push ax ; save index
MCRCT_2:
mov bx, 0 ; for (j = 0; j < 8; j++)
MCRCT_2_1:
test ax, 1 ; (r & 1)
jz MCRCT_3

shr ax, 1
xor ax, CRCPOLY
jmp MCRCT_4
MCRCT_3:
shr ax, 1
MCRCT_4:
inc bx
cmp bx, 8
jb MCRCT_2_1

pop bx ; pop out saved index to !!! REG BX !!! so that
; we won't destroy AX

mov word [ds:si + bx], ax
inc si ; since this is an array of word, we increase bx
; and si respectively so that totaly make up a 2
; bytes increment.
loop MCRCT_1

pop si
pop ax
pop bx
pop cx
ret

; Input : None
; Output : Carry Set - several reason might cause the carry flag be set
; 1. header size is 0
; 2. header check sum is not correct
; 3. data pattern does not match in some specific
; location.
; : Carry clear - header size is not 0
ReadHeader:
pusha

; read in headersize byte
push es
mov bx, [ds:SrcOffset]
call Get_Exp_Src_Byte ;R171
inc word [ds:SrcOffset]
mov byte [ds:headersize], al
pop es

cmp byte [ds:headersize], 0
jne RH_2
RH_1:
stc
jmp RH_Exit
RH_2:
; read in headersum byte
push es
mov bx, [ds:SrcOffset]
call Get_Exp_Src_Byte ;R171
inc word [ds:SrcOffset]
mov byte [ds:headersum], al
pop es

call FreadCRC ; CRC not used

call CalcHeadersum

; compare headersum and result of CalcHeadersum
cmp al, byte [ds:headersum]
je @F
jmp RH_1
@@:
mov bx, 5
mov cx, 4
call GetFromHeader
mov dword [ds:compsize], eax

mov bx, 9
mov cx, 4
call GetFromHeader
mov dword [ds:origsize], eax

mov bx, 13
mov cx, 2
call GetFromHeader
mov word [ds:ExpOffset], ax
mov word [cs:ExpOffset_], ax ;/////store copy in CS

mov bx, 15
mov cx, 2
call GetFromHeader
mov word [ds:ExpSegment], ax
mov word [cs:ExpSegment_], ax ;/////store copy in CS

cmp byte [ds:Header + 17], 20h ; check specific spot of header
jne RH_1

cmp byte [ds:Header + 18], 01h ; check specific spot of header
jne RH_1

movzx bx, byte [ds:headersize]
sub bx, 5
mov cx, 2
call GetFromHeader
mov word [ds:file_crc], ax ; truncate upper word

mov bx, NAMELENIDX
mov bl, byte [ds:Header + bx]
mov ax, OUTFILENAME
add bx, ax
mov byte [ds:Header + bx], '$' ; assembly version
mov byte [ds:Header + bx+1], 0 ; assembly version

clc
RH_Exit:
popa
ret

;[]------------------------------------------------------------------[]
;Get_Exp_Src_Byte : Get decompressed source data from SrcSegment:BX
;
;Input : SrcSegment = source data of segment
; BX = source data of offset
; DS = expand data of segment
;Output: AX = get source data to AL and clear AH
;[]------------------------------------------------------------------[]
Get_Exp_Src_Byte:
push es
call Enter_Expand_Prot
movzx ax, byte [es:bx]
pop es
ret

;Set_Exp_Src_Byte:
;push es
;call Enter_Expand_Prot
; mov [es:bx], al
;pop es
; ret

Get_Exp_Src_Dword:
push es
call Enter_Expand_Prot
mov eax, dword [es:bx]

pop es
ret

Enter_Expand_Prot:
;.....
;CHANGE!!!!
assume es, [ds:SrcSegment];[cs:orig_0];fx00
;CHANGE !!!!!!!!extract_seg
ret


; Globally parameters passing : Header, Headersize, InpFileHandle
; Modify global variable: origsize
FreadCRC:
push ax
push bx
push cx
push dx
movzx cx, byte [ds:headersize]
push es
push si
mov bx, word [ds:SrcOffset]
mov si, Header ;offset Header to SI
FCRC_0:
call Get_Exp_Src_Byte
mov byte [ds:si], al
inc bx
inc si
loop FCRC_0 ;store header...

mov ax, bx
sub ax, word [ds:SrcOffset]; how many bytes we have read ?
mov word [ds:SrcOffset], bx
pop si
pop es

mov byte [ds:headersize], al


mov cx, ax ; save a copy
add word [ds:origsize], ax
inc cx
mov bx, Header
FCRC_1:
movzx ax, byte [ds:bx] ;offset Header to BX
dec cx
jcxz FCRC_2

call UpdateCRC

inc bx ; increment pointer
jmp FCRC_1
FCRC_2:
pop dx
pop cx
pop bx
pop ax
ret

;from macro UpdateCRC...
UpdateCRC:
push ax
push bx
push si
mov si, ax
mov ax, word [ds:crc]
xor ax, si
and ax, 0ffh
mov si, ax
shl si, 1
mov bx, word [ds:crctable + si]
mov ax, word [ds:crc]
shr ax, 8
xor ax, bx
mov word [ds:crc], ax
pop si
pop bx
pop ax
ret

; Input : None
; Output : AX
; Destroy : AX
; Global variable : None
CalcHeadersum:
push bx
push cx
push dx
mov ax, 0 ; clear sum
movzx cx, byte [ds:headersize]
CH_1:
movzx bx, byte [ds:headersize]
sub bx, cx
movzx dx, byte [ds:Header + bx]
add ax, dx
loop CH_1

pop dx
pop cx
pop bx
and ax, 0ffh
ret

;---------------
;Extract--------
;---------------
Extract:
pusha
; Get file name string starting point

; save file name length
mov bx, NAMELENIDX
mov bl, byte [ds:Header + bx]
mov byte [ds:namelen], bl
; print message on screen

; compress/decompress method recognition
mov word [ds:crc], INIT_CRC
movzx dx, byte [ds:Header + 3] ; get mrthod
mov byte [ds:Header + 3], 20h ; fill with blank

; decompress starts here
call DecodeStart

Ex_1:
cmp dword [ds:origsize], 0;1c000h
je Ex_3
mov ecx, DICSIZ ; assume origsize is smalller than DIGSIZ
cmp dword [ds:origsize], DICSIZ
ja @F
mov ecx, dword [ds:origsize]
@@:
push ecx

; with parameter cx and buffer
call Decode

; with buffer, cx andOutFileHandle
call FwriteCRC

; display '.' to tell user the program is running
pop ecx
mov eax, dword [ds:origsize]
sub eax, ecx
mov dword [ds:origsize], eax
;_test32reg eax
jmp Ex_1
Ex_3:
popa
ret

;------------------------------------------------
;-------------LHA`s Algoritm---------------------
;------------------------------------------------
DecodeStart:
call HufDecodeStart
mov word [ds:j], 0 ; remaining bytes to copy
ret

HufDecodeStart:
call InitGetBits
mov word [ds:blocksize], 0
ret

InitGetBits:
mov word [ds:bitbuf], 0
mov word [ds:subbitbuf], 0
mov word [ds:bitcount], 0

mov ax, BITBUFSIZ
call FillBuf ; with parameter pass-in BITBUFSIZ (16)
ret

; Input : AX
; Output : None
FillBuf:
pusha
mov word [ds:temp_param], ax ; save
mov cx, ax
mov ax, word [ds:bitbuf]
shl ax, cl
mov word [ds:bitbuf], ax
FB_1:
mov ax, word [ds:temp_param]
cmp ax, word [ds:bitcount]
jbe FB_3

sub ax, word [ds:bitcount]
mov word [ds:temp_param], ax
push ax
mov ax, word [ds:subbitbuf]
pop cx ; pop out temp_param
shl ax, cl
or word [ds:bitbuf], ax
cmp dword [ds:compsize], 0
je FB_2

dec dword [ds:compsize]
push es
mov bx, word [ds:SrcOffset]
call Get_Exp_Src_Byte ;R171
mov word [ds:subbitbuf], ax
inc word [ds:SrcOffset]
jnz @F
;R84
add word [ds:SrcSegment], 1000h ;R84
@@: ;R84
pop es
jmp @F
FB_2:
mov word [ds:subbitbuf], 0
@@:
mov word [ds:bitcount], CHAR_BIT
jmp FB_1
FB_3:
mov ax, word [ds:bitcount]
sub ax, word [ds:temp_param]
mov word [ds:bitcount], ax
push ax
mov ax, word [ds:subbitbuf]
pop cx
shr ax, cl
or word [ds:bitbuf], ax
popa
ret

; Input : CX and Buffer
Decode:
pusha
mov bx, word [ds:s_i]
xor si, si ; r
D_2:
dec word [ds:j] ; remaining bytes to copy to
cmp word [ds:j], 0
js D_3

mov al, byte [ds:buffer + bx]
mov byte [ds:buffer + si], al
inc bx
mov ax, DICSIZ
dec ax
and bx, ax
inc si
cmp si, cx ;
jne D_2

mov word [ds:s_i], bx ; save
popa
ret
D_3:
call DecodeC ; return result in AX
cmp ax, UCHAR_MAX
ja D_4
mov byte [ds:buffer + si], al
inc si
cmp si, cx
jne D_3

mov word [ds:s_i], bx ; save
popa
ret
D_4: ; j = c - (UCHAR_MAX + 1 - THRESHOLD)
sub ax, UCHAR_MAX
dec ax
add ax, THRESHOLD
mov word [ds:j], ax

mov ax, si
call DecodeP ; return result in BX
sub ax, bx
dec ax
mov bx, ax
mov ax, DICSIZ
dec ax
and bx, ax ; i = BX
D_4_1:
dec word [ds:j]
cmp word [ds:j], 0
js D_3
mov al, byte [ds:buffer + bx]
mov byte [ds:buffer + si], al
mov ax, DICSIZ
dec ax
inc bx
and bx, ax ; i = BX
inc si
cmp si, cx
je D_6 ; bye now!
jmp D_4_1 ; go back to while loop
; D_5:
; jmp D_3
D_6:
mov word [ds:s_i], bx ; save
popa
ret

; Input : None
; OutPut : AX
DecodeC:
push bx
push cx
push si
push di

cmp word [ds:blocksize], 0
jne DC_1
mov ax, 16
call GetBits
mov word [ds:blocksize], ax

mov si, NT
mov ax, TBIT
mov di, 3

call ReadPtLen ; NT, TBIT, 3

call ReadCLen

mov si, NP
mov ax, PBIT
mov di, -1

call ReadPtLen ; NP, PBIT, -1

DC_1:
dec word [ds:blocksize]
mov cx, BITBUFSIZ
sub cx, 12
mov ax, word [ds:bitbuf]
shr ax, cl
mov bx, ax ; used as index
shl bx, 1 ; adjust to word index
mov ax, word [ds:c_table + bx]
mov si, ax ; use SI to represent J

cmp ax, NC
jb DC_4
mov ax, 1
mov cx, BITBUFSIZ
sub cx, 13
shl ax, cl
DC_2:
; variable MASK is stored in AX
mov bx, word [ds:bitbuf]
and bx, ax
mov bx, si ; get variable j, prepare word index
jnz DC_3
shl bx, 1 ; adjust to word index
mov si, word [ds:left + bx]
jmp DC_3_1
DC_3:
shl bx, 1 ; adjust to word index
mov si, word [ds:right + bx]
DC_3_1:
shr ax, 1
cmp si, NC
jae DC_2

DC_4:
movzx ax, byte [ds:c_len + si]
call FillBuf
mov ax, si ; value to be returned

DC_Exit :
pop di
pop si
pop cx
pop bx
ret

; Input : None
; Output : BX
DecodeP:
push ax
push cx
push si
mov cx, BITBUFSIZ
sub cx, 8
mov ax, word [ds:bitbuf]
shr ax, cl
mov bx, ax ; used as index
shl bx, 1 ; adjust to word index
mov ax, word [ds:pt_table + bx]
mov si, ax ; use SI to represent J

cmp ax, NP
jb DP_4

mov cx, BITBUFSIZ
sub cx, 9
mov ax, 1
shl ax, cl
DP_1:
; variable MASK is stored in AX
mov bx, word [ds:bitbuf]
and bx, ax
mov bx, si ; get variable j, prepare word index
jnz DP_2

shl bx, 1 ; adjust to word index
mov si, word [ds:left + bx]
jmp DP_3
DP_2:
shl bx, 1 ; adjust to word index
mov si, word [ds:right + bx]
DP_3:
shr ax, 1
cmp si, NP
jae DP_1
DP_4:
movzx ax, byte [ds:pt_len + si]
call FillBuf

cmp si, 0
je DP_5

mov cx, si
dec cx
mov ax, 1
shl ax, cl
mov cx, ax ; store temp result
mov ax, si
dec ax
call GetBits
add ax, cx
mov si, ax
DP_5:
mov bx, si
DP_Exit:
pop si
pop cx
pop ax
ret

; Input : AX
; Output : AX
GetBits:
push cx
push bx

mov cx, BITBUFSIZ
sub cx, ax
mov bx, ax ; save a copy for later use

mov ax, word [ds:bitbuf]
shr ax, cl

push ax ; save returned result

mov ax, bx ; restore original parameter
call FillBuf

pop ax ; returned value
pop bx
pop cx
ret

; Input : CX -- number of bytes to write to output file
FwriteCRC:
push ax
push bx
push dx
push cx
push es
push si
mov ax, word [ds:TgtSegment]
mov es, ax
mov bx, word [ds:TgtOffset]
mov si, buffer
FWCRC_0:
mov al, [ds:si]
mov [es:bx], al
inc si
inc bx
loop FWCRC_0

mov word [ds:TgtOffset], bx
or bx, bx ; if bx is zero means we need to change segment
jnz @F

add word [ds:TgtSegment], 1000h
@@:
pop si
pop es
pop cx
cmp ax, cx
jb FWCRC_Err

inc cx
mov bx, buffer
FWCRC_1:
movzx ax, byte [ds:bx]
dec cx
jcxz FWCRC_2

call UpdateCRC
inc bx
jmp FWCRC_1
FWCRC_Err:
FWCRC_2:
pop dx
pop bx
pop ax
ret

InitLocalVars:
push bx
mov word [ds:i], 0
mov word [ds:k], 0
mov word [ds:len], 0
mov word [ds:jutbits], 0
mov word [ds:avail], 0
mov word [ds:nextcode], 0
mov word [ds:vmask], 0

xor bx, bx
ILV_1:
cmp bx, 34
jae ILV_2

mov word [ds:count + bx], 0
mov word [ds:weight + bx], 0
mov word [ds:start_decomp + bx], 0
add bx, 2
jmp ILV_1
ILV_2:
mov word [ds:start_decomp + 34], 0
pop bx
ret

; Input : BX, SI, DX, DI
; Output :
MakeTable:
pusha
call InitLocalVars ; init local variables and arrays
push bx
mov bx, 2
MT_1:
cmp bx, 32
ja MT_2

mov word [ds:count + bx], 0
inc bx
inc bx
jmp MT_1
MT_2:
pop cx ; get nchar parameter to cx
push cx ; save nchar for later use
xor bx, bx
MT_3:
cmp bx, cx
jae MT_4

push si
add si, bx
movzx ax, byte [ds:si]
shl ax, 1 ; adjust to word index
mov si, ax
inc word [ds:count + si]
pop si
inc bx
jmp MT_3
MT_4:
mov word [ds:start_decomp + 2], 0 ; adjust to word index (from 1 to 2)

mov bx, 1
MT_5:
cmp bx, 16
ja MT_6

mov cx, 16
sub cx, bx
push bx
shl bx, 1
mov ax, word [ds:count + bx]
shl ax, cl
add ax, word [ds:start_decomp + bx]
mov word [ds:start_decomp + bx + 2], ax
pop bx
inc bx
jmp MT_5
MT_6:
mov ax, 1
shl ax, 16
cmp ax, word [ds:start_decomp + 34]
je MT_7
MT_Err:
;error
jmp MT_Exit ; bye ! now
MT_7:
mov cx, 16
sub cx, dx
mov word [ds:jutbits], cx
mov bx, 1
MT_8:
cmp bx, dx
ja MT_9

push bx ; save bx
shl bx, 1 ; adjust to word index
mov ax, word [ds:start_decomp + bx]
mov cx, word [ds:jutbits]
shr ax, cl
mov word [ds:start_decomp + bx], ax
pop bx ; get original index
mov cx, dx
sub cx, bx
mov ax, 1
shl ax, cl
push bx ; save index
shl bx, 1 ; adjust to word index
mov word [ds:weight + bx], ax
pop bx ; get original index
inc bx
jmp MT_8
MT_9:
cmp bx, 16
ja MT_10
mov cx, 16
sub cx, bx
mov ax, 1
shl ax, cl
push bx ; save original index
shl bx, 1 ; adjust to word index
mov word [ds:weight + bx], ax
pop bx ;restore original index
inc bx
jmp MT_9
MT_10:
mov cx, word [ds:jutbits]
mov bx, dx
inc bx
shl bx, 1 ; adjust to word index
mov ax, word [ds:start_decomp + bx]
shr ax, cl
mov bx, ax ; store in bx for var i
mov ax, 1
shl ax, 16
cmp bx, ax
je MT_12

mov cx, dx
mov ax, 1
shl ax, cl
MT_11:
cmp bx, ax
je MT_12
push bx ; save original index
shl bx, 1 ; adjust to word index
add bx, di ; di contains the offset of array table
mov word [ds:bx], 0
pop bx
inc bx
jmp MT_11
MT_12:
pop cx ; restore nchar

; from this point we start using global variable for result
; storing. We might consider to change to use global variable
; instead of pushing/poping a lot of registers later.
mov word [ds:avail], cx
mov word [ds:nchar], cx ; move this line to the upper
; part of this subroutine
mov cx, 15
sub cx, dx
mov ax, 1
shl ax, cl
mov word [ds:vmask], ax
xor bx, bx ; BX stand for variable ch
MT_13:
cmp bx, word [ds:nchar]
jae MT_Exit

movzx ax, byte [bx+si] ; si contains the offset of array bitlen
mov word [ds:len], ax
cmp word [ds:len], 0
je MT_20 ; continue looping

push bx ; bx contains value of variable ch
mov bx, word [ds:len]
shl bx, 1 ; adjust to word index
mov ax, word [ds:start_decomp + bx]
add ax, word [ds:weight + bx]
mov word [ds:nextcode], ax
cmp word [ds:len], dx ; dx contains the value of tablebits
ja MT_15

mov bx, word [ds:len]
shl bx, 1 ; adjust to word index
mov ax, word [ds:start_decomp + bx]
pop bx ; now bx contains the value of ch
MT_14:
cmp ax, word [ds:nextcode]
jae MT_19
push di
add di, ax
add di, ax ; adjust to word index
mov word [ds:di], bx
pop di
inc ax
jmp MT_14
MT_15:
; stack is not yet balanced

; Now BX stored in the stack still contains value of var ch
mov bx, word [ds:len]
shl bx, 1 ; adjust to word index
mov ax, word [ds:start_decomp + bx]
mov word [ds:k], ax
mov cx, word [ds:jutbits]
shr ax, cl
mov bx, ax
shl bx, 1 ; adjust to word index
add bx, di
mov word [ds:p], bx ; get the pointer of table[k>>jutbits]
mov bx, word [ds:len]
sub bx, dx
mov word [ds:i], bx
MT_16:
cmp word [ds:i], 0
je MT_18

mov bx, word [ds:p]
cmp word [ds:bx], 0
jne MT_17

mov bx, word [ds:avail]
shl bx, 1 ; adjust to word index
mov word [ds:right + bx], 0
mov word [ds:left + bx], 0
mov bx, word [ds:p]
mov ax, word [ds:avail]
mov word [ds:bx], ax
inc ax
mov word [ds:avail], ax
MT_17:
mov ax, word [ds:k]
mov bx, word [ds:vmask]
and ax, bx
jz MT_17_1

; the following 5 lines of code are converted from "p = &right[*p]"
mov bx, word [ds:p]
mov ax, word [ds:bx]
shl ax, 1 ; adjust to word index
mov bx, right
add bx, ax
mov word [ds:p], bx
jmp MT_17_2
MT_17_1:
; the following 5 lines of code are converted from "p = &left[*p]
mov bx, word [ds:p]
mov ax, word [bx]
shl ax, 1 ; adjust to word index
mov bx, left
add bx, ax
mov word [ds:p], bx
MT_17_2:
mov ax, word [ds:k]
shl ax, 1
mov word [ds:k], ax
dec word [ds:i]
jmp MT_16
MT_18:
pop bx ; get ch back, and stack now is balanced
xchg ax, bx
mov bx, word [ds:p]
mov word [ds:bx], ax
xchg ax, bx

MT_19: ; to here BX should contains the value of var ch
push bx
mov bx, word [ds:len]
shl bx, 1 ; adjust to word index
mov ax, word [ds:nextcode]
mov word [ds:start_decomp + bx], ax
pop bx
MT_20:
inc bx
jmp MT_13
MT_Exit:
;pop bx
popa
ret

; Input : None
; Output : None
ReadCLen:
pusha
mov ax, CBIT
call GetBits
cmp ax, 0
jne RCL_3

mov ax, CBIT
call GetBits ; AX contains the value of var c
mov cx, NC
RCL_1:
mov bx, NC
sub bx, cx
mov byte [ds:c_len + bx], 0
loop RCL_1

mov cx, 4096
RCL_2:
mov bx, 4096
sub bx, cx
mov di, bx
shl di, 1 ; prepare word index
mov word [ds:c_table + di], ax
loop RCL_2
jmp RCL_Exit
RCL_3:
mov dx, ax ; AX carry result of n, save n
mov si, 0 ; i
RCL_4:
cmp dx, si ; dx -> n, si -> i
jbe RCL_10

mov cx, word BITBUFSIZ
sub cx, 8
mov bx, word [ds:bitbuf]
shr bx, cl
shl bx, 1 ; prepare word index
mov di, word [ds:pt_table + bx] ; c
cmp di, NT
jb RCL_7

mov cx, word BITBUFSIZ
sub cx, 9
mov bx, 1
shl bx, cl ; BX is used to store MASK temporarily
RCL_5:
mov ax, word [ds:bitbuf]
and ax, bx
jz RCL_6

shl di, 1 ; prepare word index
mov di, word [ds:right + di]
jmp RCL_6_1
RCL_6:
shl di, 1 ; prepare word index
mov di, word [ds:left + di]
RCL_6_1:
shr bx, 1
cmp di, NT
jae RCL_5
RCL_7:
movzx ax, byte [ds:pt_len + di]

call FillBuf
cmp di, 2
ja RCL_9

cmp di, 0
jne RCL_7_1

mov di, 1
jmp RCL_8
RCL_7_1:
cmp di, 1
jne RCL_7_2

mov ax, 4 ; prepare input for GetBits
call GetBits ; get a result from AX
add ax, 3
mov di, ax
jmp RCL_8
RCL_7_2:
mov ax, CBIT
call GetBits
add ax, 20
mov di, ax
RCL_8: ; while (--c >= 0) c_len[i++] = 0
dec di
cmp di, 0
js RCL_4

mov byte [ds:c_len + si], 0
inc si
jmp RCL_8
RCL_9:
mov ax, di
sub ax, 2
mov byte [ds:c_len + si], al
inc si
jmp RCL_4

RCL_10: ; when i >= n
cmp si, NC
jae RCL_11

mov byte [ds:c_len + si], 0
inc si
jmp RCL_10
RCL_11:
mov bx, NC ; bx -- parameter 1
mov si, c_len ; prepare parameter 2
mov dx, 12 ; dx -- parameter 3
mov di, c_table ; prepare parameter 4
call MakeTable
RCL_Exit:
popa
ret

; Input : SI->nn(int), AX->nbit(int), DI->i_special(int)
; Output : None
ReadPtLen:
pusha
push ax ; save nbits for later use
call GetBits
mov dx, ax ; save n

cmp dx, 0
pop ax
jne RPL_3_1
call GetBits ; get a result put it in AX for var c

xor bx, bx
RPL_1:
cmp bx, si
jae RPL_2
mov byte [ds:pt_len + bx], 0
inc bx
jmp RPL_1
RPL_2:
xor bx, bx
RPL_3:
cmp bx, 512 ; word index
jae RPL_Exit ; bye !
mov word [ds:pt_table + bx], ax
add bx, 2 ; moving pointer 1 word forward
jmp RPL_3
RPL_3_1:
xor bx, bx ; i
RPL_4:
cmp bx, dx ; i < n ?
jae RPL_10

mov cx, BITBUFSIZ
sub cx, 3
mov ax, word [ds:bitbuf]
shr ax, cl

push di ; save parameter since we want to use di
mov di, ax ; save for later var c referencing

cmp di, 7
jne RPL_6

mov cx, BITBUFSIZ
sub cx, 4
mov ax, 1
shl ax, cl ; variable mask is ready
RPL_5:
mov cx, word [ds:bitbuf]
and cx, ax
jz RPL_6
shr ax, 1
inc di
jmp RPL_5

RPL_6: ; fillbuf((c < 7) ? 3 : c - 3)
mov ax, 3
cmp di, 7
jb RPL_7
mov ax, di
sub ax, 3
RPL_7:
call FillBuf

mov ax, di
mov byte [ds:pt_len + bx], al
inc bx

pop di
cmp bx, di
jne RPL_4
mov ax, 2
call GetBits
RPL_8:
dec ax
cmp ax, 0
js RPL_4 ; loop back
mov byte [ds:pt_len + bx], 0
inc bx
jmp RPL_8

RPL_10: ; while (i >= n)
cmp bx, si ; while (i < nn) loop
jae RPL_11
mov byte [ds:pt_len + bx], 0
inc bx
jmp RPL_10
RPL_11:
mov bx, si ; prepare parameter for MakeTable call
mov si, pt_len
mov dx, 8
mov di, pt_table

call MakeTable

RPL_Exit:
popa
ret

; Input : BX -- from
; CX -- count
; Output : EAX
; Destroy : EAX
GetFromHeader:
push bx
push edx
push si
xor eax, eax ; prepare unsigned long variable output

dec bx
inc cx
GFH_1:
dec cx
jcxz GFH_2

shl eax, 8
mov si, bx
add si, cx
movzx edx, byte [ds:Header + si]
add eax, edx ; little endian
jmp GFH_1
GFH_2:
pop si
pop edx
pop bx
ret

;.....................vars.......................................
; Equates File for Data Decompression

;ReadDataFromFile EQU 1
;WriteDataToFile EQU 1
;DOSVERSION EQU 1

FNAME_MAX = 255 - 25
CRCPOLY = 0A001h ; ANSI CRC-16
; CCITT: 08408h

INIT_CRC = 0 ; CCITT: 0xFFFF
DICBIT = 13 ; 12(-lh4-) or 13(-lh5-)
DICSIZ = 2000h ; (1 << DICBIT)
UCHAR_MAX = 0ffh ; maximum unsigned char value
MAXMATCH = 256 ; formerly F (not more than UCHAR_MAX + 1)
THRESHOLD = 3 ; choose optimal value
BITBUFSIZ = 16 ; (CHAR_BIT * sizeof bitbuf)
; CHAR_BIT is 8 for PC and
; bitbuf is claimed as unsigned int which is 2 bytes

CHAR_BIT = 8
NC = (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
; alphabet = {0, 1, 2, ..., NC - 1}
CBIT = 9 ; $\lfloor \log_2 NC \rfloor + 1$
CODE_BIT = 16 ; codeword length

NP = (DICBIT + 1)
NT = (CODE_BIT + 3)

PBIT = 4 ; smallest integer such that (1U << PBIT) > NP
TBIT = 5 ; smallest integer such that (1U << TBIT) > NT

IF NT > NP
NPT = NT
ELSE
NPT = NP
END IF

OUTFILENAME = 20
NAMELENIDX = 19

;;SRC_SEGMENT EQU 0e000h
;TGT_SEGMENT = 8000h

;R01 start
COMPRESSED_UNKNOW_BYTE = 3
;BootExt_Off = 0
;DecmpCode_Off = 2
;Extract_Off = 0ah
;Expand_Off = 0eh
;BootExt_Size = 17h
;DecmpCode_Size = 18h
;OutHook_Off = 19h
;P6UPD_Start_Seg = 1bh

;BtExtRom_Seg = 0e000h

;[]------------------------------------------------------------------[]
; End of Decompress Engine
;[]------------------------------------------------------------------[]