Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 110 → Rev 111

/programs/other/mhc/trunk/mhc.asm
0,0 → 1,977
;
; MHC archiver for MenuetOS - very fast compression tool
;
; version 0.09
;
; Written by Nikita Lesnikov (nlo_one@mail.ru, Republic of Belarus, Sluck)
;
 
;==============================================================================
 
;
; Brief file format description:
;
; +-----------+------------------------+
; File structure: | Method ID | Compressed data |
; +-----------+------------------------+
;
; Methods list:
;
; 0. LZP (order-2 specified specially for *.ASM,*.RAW and MeOS executables)
;
; New methods can be easily added without loss of compatibility
; with older versions
;
 
;==============================================================================
 
; SYSTEM HEADER
 
use32
 
org 0x0
db "MENUET01"
dd 0x01
dd ENTRANCE
dd MHC_END
dd 0x300000 ; 3 megs of memory needed
dd 0x2FF000
dd 0x0
dd 0x0
 
include 'lang.inc'
include 'macros.inc'
; CODE AREA
 
ENTRANCE:
 
; ======== user interface =========
 
 
call draw_window ; draw the window
 
still:
 
mov eax,10 ; wait for event
int 0x40
 
cmp eax,1 ; redraw?
jnz no_redraw
call draw_window
no_redraw:
 
cmp eax,2 ; key pressed?
jz key
 
cmp eax,3 ; button pressed?
jz button
 
jmp still
 
; Key handler
 
key:
mov eax,2 ; read it
int 0x40
shr eax,8
 
cmp byte [editstate],0
jz still
 
cmp al,8 ; backspace
jnz no_bksp
cmp byte [editpos],0
jz no_del_last
dec byte [editpos]
xor ebx,ebx
mov bl,byte [editpos]
add ebx,cmfile
cmp byte [editstate],2
jnz no_add_base_1
add ebx,12
no_add_base_1:
mov byte [ebx],32
no_del_last:
call draw_info
jmp still
no_bksp:
 
cmp al,13 ; enter
jnz no_enter
mov byte [editstate],0
call draw_info
jmp still
no_enter:
 
cmp eax,dword 31
jbe no_lit
cmp eax,dword 95
jb capital
sub eax,32
capital:
xor ebx,ebx
mov bl,byte [editpos]
add ebx,cmfile
cmp byte [editstate],2
jnz no_add_base_2
add ebx,12
no_add_base_2:
mov byte [ebx],al
inc byte [editpos]
cmp byte [editpos],12
jnz no_null_state
mov byte [editstate],0
no_null_state:
call draw_info
no_lit:
 
jmp still
 
; Button handler
 
button:
 
mov eax,17
int 0x40
 
cmp ah,1
jnz no_quit
mov eax,-1
int 0x40
no_quit:
 
cmp ah,4
jnz nofirst
cld
mov byte [editstate],1
mov edi,cmfile
mov eax,0x20202020
mov ecx,3
rep stosd
mov byte [editpos],0
mov byte [msgid],0
call draw_info
nofirst:
 
cmp ah,5
jnz nosecond
cld
mov byte [editstate],2
mov edi,iofile
mov eax,0x20202020
mov ecx,3
rep stosd
mov byte [editpos],0
mov byte [msgid],0
call draw_info
nosecond:
 
cmp ah,2
jnz no_compress
call compress
no_compress:
 
cmp ah,3
jnz no_decompress
call decompress
no_decompress:
 
cmp ah,6
jnz no_delete_io
pusha
mov eax,32
mov ebx,iofile
int 0x40
popa
no_delete_io:
 
cmp ah,7
jnz no_delete_archive
pusha
mov eax,32
mov ebx,cmfile
int 0x40
popa
no_delete_archive:
 
jmp still
 
; WINDOW DRAW
 
draw_window:
 
mov eax,12 ; Start redrawing
mov ebx,1
int 0x40
 
xor eax,eax ; Define window
mov ebx,100*65536+240
mov ecx,100*65536+130
mov edx,0x02AAAAAA
mov esi,0x80777777
mov edi,0x00777777
int 0x40
 
mov eax,4 ; Draw all needed texts
mov ebx,8*65536+8
mov ecx,0x00FFFFFF
mov edx,title
mov esi,arclab-title
int 0x40
 
xor ecx,ecx
mov edx,arclab
mov esi,unplab-arclab
add ebx,10*65536+28
int 0x40
 
mov edx,unplab
mov esi,fin_text-unplab
add ebx,18
int 0x40
 
pusha
 
mov eax,8 ; Buttons
mov ebx,222*65536+10
mov ecx,6*65536+10
mov edx,1
mov esi,0x555555
int 0x40
 
mov ebx,15*65536+100
mov ecx,70*65536+13
inc edx
int 0x40
 
inc edx
add ebx,110*65536
int 0x40
 
inc edx
mov ebx,214*65536+11
mov ecx,33*65536+11
int 0x40
 
inc edx
add ecx,18*65536
int 0x40
 
inc edx
mov ebx,15*65536+100
mov ecx,86*65536+13
int 0x40
 
inc edx
add ebx,110*65536
int 0x40
 
popa
 
mov ecx,0x00FFFFFF
mov edx,keylab
mov esi,dellab-keylab
add ebx,19
int 0x40
 
mov edx,dellab
mov esi,title-dellab
add ebx,16
int 0x40
 
call draw_info
 
mov eax,12 ; Finish redrawing
mov ebx,2
int 0x40
 
ret
 
draw_info: ; Draw filenames and compressor state
 
activecolor equ 0x00112299
 
pusha ; Save registers
 
mov eax,13 ; Clean draw area
mov ebx,127*65536+85
mov ecx,33*65536+33
mov edx,0x00AAAAAA
int 0x40
 
mov eax,4 ; Draw filenames
mov ebx,134*65536+36
mov edx,cmfile
xor ecx,ecx
mov esi,12
cmp byte [editstate],1
jnz no_active_1
mov ecx,activecolor
no_active_1:
int 0x40
xor ecx,ecx
cmp byte [editstate],2
jnz no_active_2
mov ecx,activecolor
no_active_2:
add ebx,18
add edx,12
int 0x40
 
mov eax,13 ; Clean info area
mov ebx,14*65536+210
mov ecx,107*65536+14
mov edx,0x00AAAAAA
int 0x40
 
cmp byte [msgid],0 ; Draw info string
jz notype
mov ebx,16*65536+110
xor ecx,ecx
mov esi,16
mov al, byte [msgid]
dec al
shl al,4
xor ah,ah
xor edx,edx
mov dx,ax
add edx,msgtable
mov eax,4
int 0x40
notype:
 
popa ; Restore registers
 
ret
 
; interface data
 
keylab db " COMPRESS DECOMPRESS"
dellab db " DELETE I/O DELETE *.MHC"
title db "MHC 0.09"
arclab db "COMPRESSED FILE:"
unplab db "INPUT/OUTPUT FILE:"
fin_text:
 
cmfile db "FILENAME.MHC"
iofile db "FILENAME.XYZ"
 
editstate db 0
editpos db 0
msgid db 0
 
msgtable:
db "COMPRESSING... "
db "DECOMPRESSING..."
db "I/O NOT FOUND! "
db "*.MHC NOT FOUND!"
db "INVALID METHOD! "
 
; ======== compression/decompression engine ========
 
; Adresses declaration
 
hashtable equ MHC_END
ifile equ hashtable+65536*4
ofile equ ifile+1000000
 
compress: ; File compression
 
call fill_filebufs
 
mov eax,6
mov ebx,iofile
xor ecx,ecx
mov edx,ecx
not edx
mov esi,ifile
int 0x40
 
cmp eax,0xFFFFFFFF
jnz compress_filefound ; i/o file not found
mov byte [msgid],3
call draw_info
ret
 
compress_filefound:
 
mov byte [msgid],1
call draw_info
 
jmp lzp_compress ; compress with order-2 LZP
compress_dumpdata:
 
push edx
 
mov eax,32
mov ebx,cmfile
int 0x40
 
mov eax,33
pop edx
mov ebx,cmfile
mov ecx,ofile
xor esi,esi
int 0x40
 
mov byte [msgid],0
call draw_info
 
ret
 
 
decompress: ; File decompression
 
call fill_filebufs
 
mov eax,6
mov ebx,cmfile
xor ecx,ecx
mov edx,ecx
not edx
mov esi,ofile
int 0x40
 
cmp eax,0xFFFFFFFF
jnz decompress_filefound ; *.mhc file not found
mov byte [msgid],4
call draw_info
ret
 
decompress_filefound:
 
cmp byte [ofile],0 ; Invalid method!
jz right_method
mov byte [msgid],5
call draw_info
ret
 
right_method:
mov byte [msgid],2
call draw_info
 
jmp lzp_decompress
decompress_dumpdata:
 
push edx
 
mov eax,32
mov ebx,iofile
int 0x40
 
mov eax,33
pop edx
mov ebx,iofile
mov ecx,ifile
xor esi,esi
int 0x40
 
mov byte [msgid],0
call draw_info
 
ret
 
fill_filebufs: ; Fill filebufs with garbage to simplify matching
pusha
cld
mov eax,0xF7D9A03F ; <- "magic number" :) just garbage...
mov ecx,2000000/4
mov edi,ifile
rep stosd
popa
ret
 
; ==== algorithms section ====
 
; Method 0: LZP compression algorithm
 
lzp_compress: ; EDX - how much bytes to dump
 
cld ; clear direction flag
 
mov esi,ifile ; init pointers
mov edi,ofile
 
push eax ; write header: ID0+4bfilesize => total 5 bytes
xor eax,eax
stosb
pop eax
stosd
 
pusha ; fill hash table
mov eax,ifile
mov edi,hashtable
mov ecx,65536
rep stosd
popa
 
add eax,esi ; calculate endpointer
mov dword [endpointer],eax
 
movsw ; copy three bytes
movsb
 
mov dword [controlp],edi
inc edi
 
mov byte [controld],0
mov byte [controlb],0
 
c_loop:
cmp dword [endpointer],esi ; check end of file
ja c_loop_ok
jmp finish_c_loop
c_loop_ok:
 
call chash
call compare
jz two_match_c
 
lodsb
mov byte [literal],al
call chash
call compare
jz lit_match_c
 
mov al,0
call putbit
mov al,byte [literal]
stosb
movsb
jmp end_c_loop
 
lit_match_c:
mov al,1
call putbit
mov al,0
call putbit
mov al,byte [literal]
stosb
jmp encode_match
 
two_match_c:
mov al,1
call putbit
call putbit
 
encode_match:
call incpos
call compare
jz one_c
mov al,0
call putbit
jmp end_c_loop
one_c:
 
call incpos
mov al,1
call putbit
 
call compare
jnz ec1
call incpos
call compare
jnz ec2
call incpos
call compare
jnz ec3
call incpos
mov al,1
call putbit
call putbit
call compare
jnz ec4
call incpos
call compare
jnz ec5
call incpos
call compare
jnz ec6
call incpos
call compare
jnz ec7
call incpos
call compare
jnz ec8
call incpos
call compare
jnz ec9
call incpos
call compare
jnz ec10
call incpos
 
mov al,1
call putbit
call putbit
call putbit
xor ecx,ecx
 
match_loop_c:
cmp esi,dword [endpointer]
jae out_match_loop_c
call compare
jnz out_match_loop_c
inc ecx
call incpos
jmp match_loop_c
out_match_loop_c:
 
mov al,0xFF
out_lg:
cmp ecx,255
jb out_lg_out
stosb
sub ecx,255
jmp out_lg
out_lg_out:
mov al,cl
stosb
jmp end_c_loop
 
ec10:
mov al,1
call putbit
call putbit
mov al,0
call putbit
jmp end_c_loop
 
ec9:
mov al,1
call putbit
mov al,0
call putbit
mov al,1
call putbit
jmp end_c_loop
 
ec8:
mov al,1
call putbit
mov al,0
call putbit
call putbit
jmp end_c_loop
 
ec7:
mov al,0
call putbit
mov al,1
call putbit
call putbit
jmp end_c_loop
 
ec6:
mov al,0
call putbit
mov al,1
call putbit
mov al,0
call putbit
jmp end_c_loop
 
ec5:
mov al,0
call putbit
call putbit
mov al,1
call putbit
jmp end_c_loop
 
ec4:
mov al,0
call putbit
call putbit
call putbit
jmp end_c_loop
 
ec3:
mov al,1
call putbit
mov al,0
call putbit
jmp end_c_loop
 
ec2:
mov al,0
call putbit
mov al,1
call putbit
jmp end_c_loop
 
ec1:
mov al,0
call putbit
call putbit
 
end_c_loop:
jmp c_loop
 
finish_c_loop:
 
mov eax,dword [controlp] ; store last tagbyte
mov bl,byte [controld]
mov [eax], byte bl
 
sub edi,ofile ; calculate dump size
mov edx,edi
 
jmp compress_dumpdata
 
; LZP decompression algorithm
 
lzp_decompress: ; EDX - how much bytes to dump
 
cld
 
mov edi,ifile
mov esi,ofile+1
 
pusha ; fill hash table
mov eax,ifile
mov edi,hashtable
mov ecx,65536
rep stosd
popa
 
lodsd
 
mov ebx,edi
add ebx,eax
mov dword [endpointer],ebx
 
movsw
movsb
 
lodsb
mov byte [controld],al
mov byte [controlb],0
 
d_loop:
cmp dword [endpointer],edi
ja d_loop_ok
jmp finish_d_loop
d_loop_ok:
 
call getbit
cmp al,0
jnz match_d
call dhash
movsb
call dhash
movsb
jmp end_d_loop
 
match_d:
 
call getbit
cmp al,0
jnz no_literal_before_match
call dhash
movsb
no_literal_before_match:
 
call dhash
mov ecx,1
call copymatch
 
call getbit
cmp al,0
jz end_d_loop
mov ecx,1
call copymatch
call getbit
cmp al,0
jz dc2
mov ecx,2
call copymatch
call getbit
cmp al,0
jz end_d_loop
mov ecx,1
call copymatch
call getbit
cmp al,0
jz dc4
mov ecx,4
call copymatch
call getbit
cmp al,0
jz dc5
call getbit
cmp al,0
jz dc6
mov ecx,3
call copymatch
 
do:
lodsb
xor ecx,ecx
mov cl,al
call copymatch
cmp al,0xFF
jnz end_do
jmp do
end_do:
jmp end_d_loop
 
dc6:
mov ecx,2
call copymatch
jmp end_d_loop
 
dc5:
call getbit
cmp al,0
jz ndc5
mov ecx,1
call copymatch
ndc5:
jmp end_d_loop
 
dc4:
call getbit
cmp al,0
jz ndc4
call getbit
mov ecx,3
cmp al,1
jz ndcc4
dec ecx
ndcc4:
call copymatch
jmp end_d_loop
ndc4:
call getbit
cmp al,0
jz ndccc4
mov ecx,1
call copymatch
ndccc4:
jmp end_d_loop
 
dc2:
call getbit
cmp al,0
jz ndc2
mov ecx,1
call copymatch
ndc2:
 
end_d_loop:
jmp d_loop
finish_d_loop:
 
mov edx, dword [ofile+1]
 
jmp decompress_dumpdata
 
; LZP subroutines
 
putbit: ; bit -> byte tag, AL holds bit for output
pusha
mov cl,byte [controlb]
shl al,cl
mov bl,byte [controld]
or bl,al
mov byte [controld],bl
inc cl
cmp cl,8
jnz just_increment
mov byte [controlb],0
mov byte [controld],0
push edi
mov edi, dword [controlp]
mov al,bl
stosb
pop edi
mov dword [controlp],edi
popa
inc edi
ret
just_increment:
mov byte [controlb],cl
popa
ret
 
getbit: ; tag byte -> bit, AL holds input
push ecx
mov al,byte [controld]
mov cl,byte [controlb]
shr al,cl
and al,1
inc cl
cmp cl,8
jnz just_increment_d
mov byte [controlb],0
push eax
lodsb
mov byte [controld],al
pop eax
pop ecx
ret
just_increment_d:
mov byte [controlb],cl
pop ecx
ret
 
chash: ; calculate hash -> mp -> fill position
pusha
xor eax,eax
mov al, byte [esi-1]
mov ah, byte [esi-2]
shl eax,2
add eax,hashtable
mov edx,dword [eax]
mov dword [mp],edx
mov dword [eax],esi
popa
ret
 
dhash: ; calculate hash -> mp -> fill position
pusha
xor eax,eax
mov al, byte [edi-1]
mov ah, byte [edi-2]
shl eax,2
add eax,hashtable
mov edx,dword [eax]
mov dword [mp],edx
mov dword [eax],edi
popa
ret
 
copymatch: ; ECX bytes from [mp] to [rp]
push esi
mov esi,dword [mp]
rep movsb
mov dword [mp],esi
pop esi
ret
 
compare: ; compare [mp] with [cpos]
push edi
push esi
mov edi,dword [mp]
cmpsb
pop esi
pop edi
ret
 
incpos:
inc dword [mp]
inc esi
ret
 
 
; LZP algorithm data
 
endpointer dd 0
controlp dd 0
controlb db 0
controld db 0
mp dd 0
literal db 0
 
MHC_END: ; the end... - Nikita Lesnikov (nlo_one)
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property