mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-12 17:32:30 -04:00
342 lines
10 KiB
NASM
342 lines
10 KiB
NASM
.model small
|
|
.386
|
|
;16 bit line (de)comprimator
|
|
;
|
|
_TEXT segment byte public 'CODE' use32
|
|
assume CS:_TEXT
|
|
assume DS:DGROUP
|
|
|
|
|
|
|
|
cwrite macro REG,BIT ;zapise al do [di] pouze BIT bitu ze zadu
|
|
local cwrit2
|
|
shl edx,BIT ;posun EDX o pripraveny pocet bitu
|
|
and REG,0ffh shr (8-BIT) ;odmaskuj pripadne bity v REG
|
|
or dl,REG ;pridej REG do dl
|
|
add ch,BIT ;pripocti pridany pocet bitu
|
|
cmp ch,8 ;jestli to preteklo
|
|
jc cwrit2 ;ne, vse je OK
|
|
sub ch,8 ;ano pak odecti 8 bitu
|
|
mov cl,8 ;cl=8-ch;
|
|
sub cl,ch ;
|
|
shl edx,cl ;tj kolik zbejva posunout.
|
|
mov [edi],dh ;zapis osmice
|
|
shr dl,cl ;vrat dl do puvodniho stavu
|
|
inc edi ;dalsi adresa
|
|
cwrit2:
|
|
endm
|
|
|
|
cwrit8 macro REG ;zapise 8 bitu do [EDI]
|
|
shl edx,8 ;posun 8 bitu
|
|
or dl,REG ;sfuzuj
|
|
mov cl,8 ;kolik urcite preteklo
|
|
sub cl,ch ;a o kolik teda posunout
|
|
shl edx,cl ;posun na dorovnani na bajt
|
|
mov [edi],dh ;zapis bajt
|
|
shr dl,cl ;spodek vrat do puvodniho stavu.
|
|
inc edi ;dalsi adresa
|
|
endm
|
|
|
|
write_ax: ;zapisuje AX do [edi] v komprimovanem tvaru
|
|
;hodnoty
|
|
; 0 ... 000
|
|
; 1 ... 001
|
|
; 2 ... 010
|
|
; 3 ... 011
|
|
; 4 ... 100
|
|
; 5 ... 101
|
|
; 6 ... 110
|
|
; 7 ... 11100000
|
|
; 8 ... 11100001
|
|
; 9 ... 11100010
|
|
;10 ...
|
|
;...
|
|
;37 ... 11111110
|
|
;38 ... 1111111100000000
|
|
;39 ... 1111111100000001
|
|
;
|
|
;291 .. 1111111111111101
|
|
;292 .. 1111111111111110
|
|
;>293 .. 1111111111111111 Lo Hi
|
|
|
|
cmp eax,293 ;eax>293 (7+31+255)
|
|
jnc wr_16 ;zapis 16 bitove hodnoty
|
|
cmp al,38 ;eax>38 (7+31)
|
|
jnc wr_8 ;zapis 8 bitove hodnoty
|
|
cmp al,7 ;eax>7
|
|
jnc wr_5 ;zapis 5 bitove hodnoty
|
|
cwrite al,3 ;pro cisla eax<7 (0..6) staci 3 bity
|
|
ret ;konec
|
|
wr_16: sub eax,293 ;odecti to co je zname
|
|
mov cl,0ffh ;zapis dvou hodnot 255 jako znacka ze nasleduje
|
|
cwrit8 cl ;16 bitova hodnota
|
|
mov cl,0ffh
|
|
cwrit8 cl
|
|
cwrit8 al ;zapis nizsi
|
|
mov al,ah
|
|
cwrit8 ah ;zapis vyssi
|
|
ret
|
|
wr_5: sub al,7 ;odecti co zname
|
|
or al,0E0h ;tri bity na 1 znaci 5 bitovou hodnotu
|
|
cwrit8 al ;zapis to
|
|
ret
|
|
wr_8: sub al,38 ;odecti to co je uz zname.
|
|
mov cl,0ffh ;zapis jedne hodnoty 255 znaci 8 bitovou hodnotu
|
|
cwrit8 cl ;zapis ji
|
|
cwrit8 al ;zapis al
|
|
ret
|
|
|
|
|
|
;vsechny mody -
|
|
; vstup: ESI - data
|
|
; EDI - buffer
|
|
; ECX - delka dat (max 65535)
|
|
; EBX - bitova rovina (bit na pozici roviny = 1)
|
|
|
|
flush macro
|
|
local fjmp
|
|
shr ecx,16
|
|
or ch,ch
|
|
jz fjmp
|
|
mov eax,7
|
|
call write_ax
|
|
fjmp:
|
|
endm
|
|
|
|
public cmode0_
|
|
cmode0_: ;komprimuje pro mod 11110000 (uvazuji se retezce 00001 nebo 11110 pricemz
|
|
; 0000111110 se pocita vcetne rozdilu (
|
|
; \---/\---/
|
|
; 4 4 tj 100100
|
|
|
|
|
|
push ebp
|
|
xor edx,edx
|
|
xor ebp,ebp
|
|
xor eax,eax
|
|
cmode0b: lodsw
|
|
and ax,bx
|
|
cmp ax,bp
|
|
jnz cmode0a
|
|
add eax,10000h
|
|
dec cx
|
|
jnz cmode0b
|
|
shr eax,16
|
|
shr ecx,16
|
|
call write_ax
|
|
flush
|
|
pop ebp
|
|
ret
|
|
cmode0a: xor ebp,ebx
|
|
shr eax,16
|
|
rol ecx,16
|
|
call write_ax
|
|
rol ecx,16
|
|
dec cx
|
|
jnz cmode0b
|
|
flush
|
|
pop ebp
|
|
ret
|
|
|
|
public cmode1_
|
|
|
|
cmode1_: ;komprimuje pro mod 00010001
|
|
;komprimuje se vcetne jednicky tj
|
|
;
|
|
;000100001
|
|
;\--/\---/
|
|
; 3 4 tj 011100
|
|
xor edx,edx
|
|
xor eax,eax
|
|
cmode1b: lodsw
|
|
and ax,bx
|
|
jnz cmode1a
|
|
add eax,10000h
|
|
dec cx
|
|
jnz cmode1b
|
|
shr eax,16
|
|
shr ecx,16
|
|
call write_ax
|
|
flush
|
|
ret
|
|
cmode1a: shr eax,16
|
|
rol ecx,16
|
|
call write_ax
|
|
rol ecx,16
|
|
dec cx
|
|
jnz cmode1b
|
|
flush
|
|
ret
|
|
|
|
public cmode2_
|
|
|
|
cmode2_: ;komprimuje pro mod 11101110
|
|
;komprimuje se vcetne 0 tj
|
|
;
|
|
;111101011110111110
|
|
;\---/\/\---/\----/
|
|
; 4 1 4 4 tj 100001100100
|
|
xor edx,edx
|
|
xor eax,eax
|
|
cmode2b: lodsw
|
|
and ax,bx
|
|
jz cmode2a
|
|
add eax,10000h
|
|
dec cx
|
|
jnz cmode2b
|
|
shr eax,16
|
|
shr ecx,16
|
|
call write_ax
|
|
flush
|
|
ret
|
|
cmode2a: shr eax,16
|
|
rol ecx,16
|
|
call write_ax
|
|
rol ecx,16
|
|
dec cx
|
|
jnz cmode2b
|
|
flush
|
|
ret
|
|
|
|
public cmode3_
|
|
cmode3_: ;kopiruje rovinu
|
|
mov edx,8 ;8 bitu
|
|
cmode3b: lodsw ;cti slovo
|
|
and ax,bx ;kontroluj rovinu
|
|
cmp ax,bx ;nastav carry podle vysledku
|
|
cmc ;ale spravne
|
|
rcl dh,1 ;soupni ho do dh
|
|
dec dl ;dalsi pozice
|
|
jnz cmode3a ;kdyz to neni vse pokracuj
|
|
mov [edi],dl ;je to vse
|
|
inc edi ;dalsi bajt
|
|
mov edx,8 ;dalsich 8 bitu
|
|
cmode3a: dec ecx ;dalsi slovo
|
|
jnz cmode3b ;dokud to neni vse.
|
|
cmp dl,8
|
|
jz cmode3c
|
|
mov cl,dl
|
|
shl dh,cl
|
|
mov [edi],dh
|
|
inc edi
|
|
cmode3c: ret
|
|
|
|
|
|
; DEKOMPRIMACE
|
|
|
|
cread macro REG,BIT
|
|
local crd1
|
|
mov cl,BIT
|
|
cmp ch,cl ;zjisti zda pocet zbylych bitu
|
|
jnc crd1 ;neni nahodou min nez potrebnych
|
|
mov cl,ch ;ano, tj posun ty zbyle do dh
|
|
shl edx,cl
|
|
mov dl,[esi] ;do dl vloz dalsi bajt
|
|
inc esi ;a zvys adresu
|
|
sub cl,BIT ;odecti pocet pozadovanych bitu
|
|
mov ch,8 ;to je aktualizovana hodnota noveho ch
|
|
neg cl ;v cl je nyni mnozstvi chybejicich bitu
|
|
crd1: shl edx,cl ;prisun je do dh
|
|
sub ch,cl
|
|
mov REG,dh ;vem je do REG
|
|
and REG,0xff shr (8-BIT) ;odmaskuj horejsek
|
|
endm
|
|
|
|
;vsechny mody -
|
|
; vstup: ESI - data
|
|
; EDI - vysledek
|
|
; ECX - delka dat (max 65535)
|
|
; EBX - bitova rovina (bit na pozici roviny = 1)
|
|
|
|
cread_ax macro
|
|
local crd_ok
|
|
rol ecx,16 ;nejdriv schovej cx v horni pulce
|
|
xor eax,eax ;vynuluj eax
|
|
cread al,3 ;nacti 3 bity
|
|
cmp al,7 ;pokud to da hodnotu 7 pak pokracuj
|
|
jnz crd_ok ;jinak jsem hotov
|
|
cread al,5 ;nacti dalsi 5 bitu
|
|
add al,7 ;pricti ztracenych 7
|
|
cmp al,38 ;pokracuj kdyz to da dohromady 38
|
|
jnz crd_ok
|
|
cread al,8 ;nacti 8 bitu
|
|
add eax,38 ;a pricti 38
|
|
cmp eax,293 ;pokracuj kdyz to da 293
|
|
jnz crd_ok
|
|
cread al,8 ;precti dalsi 8 bitu
|
|
cread ah,8 ;Nejdriv dolni a pak horni
|
|
add eax,293
|
|
crd_ok: rol ecx,16 ;obnov cx
|
|
|
|
endm
|
|
|
|
public cread0_
|
|
cread0_: and ecx,0ffffh ;vynuluj horni pulku ecx
|
|
xor edx,edx ;vynuluj pamet bitu
|
|
cread_ax ;precti prvni zaznam
|
|
or eax,eax ;je li 0 zaciname jednickami
|
|
jnz cread0a
|
|
cread0c: cread_ax ;precti zaznam
|
|
inc eax ;+1
|
|
cread0b: xor [edi],bx ;invertuj rovinu
|
|
add edi,2
|
|
dec ecx ;odecitej ecx
|
|
dec eax ;odecti citac
|
|
jnz cread0b ;dokud neni ax=0
|
|
or cx,cx ;kontrola zda nejsme na konci
|
|
jz cread0e ;kdyz ne
|
|
cread_ax ;precti dalsi zaznam
|
|
inc eax ;+1
|
|
cread0a: sub cx,ax ;ted se jenom preskoci
|
|
jz cread0e ;ale kdyz jsme na konci tak nic nedelej
|
|
shl eax,1 ;preskoci 2*eax bajtu
|
|
add edi,eax ;skok!
|
|
jmp cread0c ;a jedem znova.
|
|
cread0e: ret
|
|
|
|
public cread1_
|
|
cread1_: and ecx,0ffffh
|
|
xor edx,edx
|
|
cread1a: cread_ax ;cti zaznam
|
|
add edi,eax ;preskoc EAX bajtu a zapis 1
|
|
xor [edi],ebx
|
|
add edi,2
|
|
dec ecx ;jedna za jeden bod
|
|
sub cx,ax ;a jeste ax bajtu
|
|
jnz cread1a ;jeste to neni vse?
|
|
ret
|
|
|
|
public cread2_
|
|
cread2_: and ecx,0ffffh
|
|
xor edx,edx
|
|
cread2a: cread_ax ;cti zaznam
|
|
add edi,eax ;zapis EAX bajtu a preskoc 1
|
|
cread2b: xor [edi],ebx
|
|
add edi,2
|
|
dec ecx ;jedna za jeden bod
|
|
dec eax
|
|
jnz cread2b
|
|
add edi,2
|
|
dec ecx
|
|
jnz cread2a
|
|
ret
|
|
|
|
public cread3_
|
|
cread3_: mov dh,8 ;dh - citac bitu
|
|
mov dl,[esi] ;vezmi prvni osmici
|
|
inc esi ;zvys adresu
|
|
cread3b: shl dl,1 ;nacti bit do cf
|
|
sbb eax,eax ;je-li nastaven je vysledek 0xffffffff
|
|
and eax,ebx ;nastav prislusnou rovinu
|
|
xor [edi],ax ;proved XOR
|
|
add edi,2 ;dalsi bod
|
|
dec ecx ;odecti si ho
|
|
jz cread3a ;kdyz uz jsme na konci skok na cread3a
|
|
dec dh ;odecti citac bitu
|
|
jz cread3_ ;jakmile klesne na nulu zacni od zacatku
|
|
jmp cread3b ;jinak opakuj.
|
|
cread3a: ret
|
|
|
|
_TEXT ends
|
|
|
|
END
|