gates_of_skeldal/VIDEO/BITLINE.ASM
2025-01-24 18:27:22 +01:00

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