; modulo per la visualizzazione di bitmap planari (4 piani)
; a 256 colori
.386P
code32 segment para public use32
assume cs:code32,ds:code32
include 386video.inc
BlastGet macro @PIFF
@PIFF:
mov cl,bh
rep movsd
add esi,ebp
dec bl
jne @PIFF
endm
PlanGet macro @PIFFO
inc ah
and ah,PIXMUP
jnz @PIFFO
inc esi
@PIFFO: out dx,ax
endm
; 1 nudget = 4 pixel (plane aligned, one pixel for every plane)
; 1 big nudget = 16 pixel (plane aligned, four nudgets)
; PIC format:
; offset size name description
; 0 1 WX Width of picture in BIG NUDGETS
; 1 1 WY Height of picture in PIXELS
; 2 WX*WY*4 ---- First plane
; 2+WX*WY*4 WX*WY*4 ---- Second plane
; 2+WX*WY*8 WX*WY*4 ---- Third plane
; 2+WX*WY*12 WX*WY*4 ---- Fourth plane
public _GetPic
; reads picture from screen
_GetPic:
; in:
; edi = pic dest
; esi = scr source
; eax = x in nudgets
; edx = y in pixels
; ecx = x width in big-nudgets
; ebx = y height in pixels
; out:
; edi = ptr to end of picture
push eax
push ebx
push ecx
push edx
push esi
push ebp
; [esp-4] == screen start
; [esp-8] == counter
add esi,[edx*4+_RowStart]
add esi,eax
BLITMODE BLITPLANE
; dx == GRAPHICS
mov ax,RP0
mov ch,bl ; y height
mov [edi],cx ; registra ampiezza ed altezza
mov bh,cl ; store x counter
add edi,2 ; advance pointer
xor ch,ch ; ripulisci ch
shl ecx,2 ; from big-nudgets to nudgets
mov ebp,PXWIDTH ; avanzamento di linea iniziale
mov [esp-4],esi
sub ebp,ecx ; correggi per avanzamento
mov [esp-8],ebx
out dx,ax ; read starting from plane 0
BlastGet @gpbp0
mov ebx,[esp-8]
mov esi,[esp-4]
PlanGet @gpgoz1
BlastGet @gpbp1
mov ebx,[esp-8]
mov esi,[esp-4]
PlanGet @gpgoz2
BlastGet @gpbp2
mov ebx,[esp-8]
mov esi,[esp-4]
PlanGet @gpgoz3
BlastGet @gpbp3
; edi = posizione DOPO la lettura della bitmap
pop ebp
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
BlastPut macro @PFFON
@PFFON:
mov cl,bl
rep movsd
add edi,ebp
dec bh
jne @PFFON
endm
BlastRPut macro @drzoom,@revup
@drzoom:
mov cl,bl
@revup:
lodsd
rol ax,8 ; one for the money
sub edi,4 ; (interleave this instruction)
rol eax,16 ; two for the show
rol ax,8 ; three get ready
mov [edi],eax ; & let's rock!
loop @revup
add edi,ebp
dec bh
jne @drzoom
endm
PlanPut macro
rol ah,1
adc edi,00
out dx,ax
endm
PlanRPut macro
ror ah,1
sbb edi,00
out dx,ax
endm
public _PutPic
; blits a picture to screen
; Warning! L' unica opzione valida e' LEFTRIGHT!
_PutPic:
; edi = scr dest
; esi = pic ptr
; eax = x in pixels
; edx = y in pixels
; bl = blit mode flag 1=reverse left-right
mov ecx,eax
shr eax,PIXSHIFT
add edi,[edx*4+_RowStart]
and ecx,PIXMUP
add edi,eax
inc ecx
BLITMODE BLITPLANE
and bl,LEFTRIGHT
jnz @pleftright
@pnorm:
mov ax,WWP0
rol ah,cl
mov bx,[esi] ;width & height
add esi,2
mov cl,bl
mov dx,SEQUENCER
shl cl,2 ; big nudgets to nudgets
mov ebp,PXWIDTH ; incremento di linea
sub ebp,ecx ; correggi per avanzamento
out dx,ax
push edi
push ebx
BlastPut @pbp0
pop ebx
pop edi
PlanPut
push edi
push ebx
BlastPut @pbp1
pop ebx
pop edi
PlanPut
push edi
push ebx
BlastPut @pbp2
pop ebx
pop edi
PlanPut
BlastPut @pbp3
@pgottaut:
ret
@pleftright:
; LEFT TO RIGHT <--> RIGHT TO LEFT
mov dx,SEQUENCER
mov ax,WWP3
rol ah,cl
dec cl
jz @noinc
inc edi
@noinc:
mov bx,[esi]
mov cl,bl
add esi,2
shl ecx,2 ; size in nudgets
mov ebp,PXWIDTH ; incremento di linea
add ebp,ecx ; correggi per retrocessione
add edi,ecx ; portati a fine linea
out dx,ax ; seleziona il primo piano
push edi
push ebx
push eax
BlastRPut @rbp1a,@rbp1b
pop eax
pop ebx
pop edi
PlanRPut
push edi
push ebx
push eax
BlastRPut @rbp2a,@rbp2b
pop eax
pop ebx
pop edi
PlanRPut
push edi
push ebx
push eax
BlastRPut @rbp3a,@rbp3b
pop eax
pop ebx
pop edi
PlanRPut
BlastRPut @rbp4a,@rbp4b
ret
; Un Spt (encoded SPriTe)
; ha una word di intestazione come una PICture
; offset size significato
; 0 1 ampiezza immagine in nudgets
; 1 1 altezza immagine in pixels
; Ma poi i 4 piani di bytes sono descritti da "pacchetti"
; con colore trasparente codificato in RLE
; formato di un RLE packet: [..] == .. e' opzionale
; RLE_HEADER, [INCR 1byte ], [DATA_HEAD 0..3 byte ],[DATA_DWORD 0..n dwords]
; RLE_HEADER bit 0..1 = data_head lenght (0..3 BYTES)
; bit 2 = dword data present
; bit 3 = new line after this blit
; bit 4..7 = dword counter n (0..15 DWORDS)
; un pacchetto 00 (fine piano) oppure 08 (newline)
; non ha neppure il campo [INCR] (tutti gli altri invece ne hanno uno)
crunch macro
; decode next packet
lodsw
mov cl,al ; dword count into ecx (higher 4 bits)
mov bl,ah ; skip count into ebx
and eax,0Fh
add edi,ebx ; skip_null_pixels increment (don't worry)
jmp [eax*4+offset ETable] ; go to packet decoder
endm
eblast macro
; blit a dword count
shr ecx,4
rep movsd
endm
ncrunch macro
; newline & decode next packet
lodsw
add ebp,PXWIDTH ; move to next line
mov cl,al
mov bl,ah
mov edi,ebp ; perform newline
and eax,0Fh
add edi,ebx ; increment
jmp [eax*4+ offset ETable] ; perform blit
endm
; Hndl : Header, n== perform newline,d == dword data, l == data head lenght
H000: ; END OF PLANE
pop ebp
pop ecx
pop eax
dec esi ; the [incr] field is not present, so move one step back
rol ah,1 ; update plane pointer & index
adc ebp,0 ;
out dx,ax ;
dec ecx ;
je @basta ; last plane ?
mov edi,ebp
push eax
push ecx
push ebp
crunch
H001: movsb
crunch
H002: movsw
crunch
H003: movsb
movsw
crunch
H010: eblast
crunch
H011: movsb
eblast
crunch
H012: movsw
eblast
crunch
H013: movsb
movsw
eblast
crunch
H100: dec esi ; no [incr] field present
ncrunch
H101: movsb
ncrunch
H102: movsw
ncrunch
H103: movsb
movsw
ncrunch
H110: eblast
ncrunch
H111: movsb
eblast
ncrunch
H112: movsw
eblast
ncrunch
H113: movsb
movsw
eblast
ncrunch
align dword
ETable: dd offset H000, offset H001, offset H002, offset H003
dd offset H010, offset H011, offset H012, offset H013
dd offset H100, offset H101, offset H102, offset H103
dd offset H110, offset H111, offset H112, offset H113
align byte
rcrunch macro
lodsw
mov cl,al
mov bl,ah
and eax,0Fh
sub edi,ebx ; increment
jmp [eax*4+offset RETable] ; perform blit
endm
reblast macro @lup
shr ecx,4
@lup: lodsd
sub edi,4
rol ax,8
rol eax,16
rol ax,8
mov [edi],eax
loop @lup
endm
rncrunch macro
lodsw
add ebp,PXWIDTH ; to next line
mov cl,al
mov bl,ah
mov edi,ebp ; set next line
and eax,0Fh
sub edi,ebx ; increment
jmp [eax*4+offset RETable] ; perform blit
endm
rmovsb macro
dec edi
lodsb
mov [edi],al
endm
rmovsw macro
sub edi,2
lodsw
rol ax,8
mov [edi],ax
endm
rmovsbw macro
sub edi,2
lodsd
rol ax,8
mov [edi],ax
shr eax,16 ; Pronti a blittare il terzo byte
dec edi
dec esi ; il byte piu alto e' stato letto "a vuoto"
mov [edi],al
endm
RH000: pop ebp
pop ecx
pop eax
dec esi ; no increment field present
ror ah,1
sbb ebp,0
out dx,ax
dec ecx
je @basta
mov edi,ebp
push eax
push ecx
push ebp
rcrunch
RH001: rmovsb
rcrunch
RH002: rmovsw
rcrunch
RH003: rmovsbw
rcrunch
RH010: reblast a0
rcrunch
RH011: rmovsb
reblast a1
rcrunch
RH012: rmovsw
reblast a2
rcrunch
RH013: rmovsbw
reblast a3
rcrunch
RH100: dec esi ; no [incr] field present
rncrunch
RH101: rmovsb
rncrunch
RH102: rmovsw
rncrunch
RH103: rmovsbw
rncrunch
RH110: reblast a4
rncrunch
RH111: rmovsb
reblast a5
rncrunch
RH112: rmovsw
reblast a6
rncrunch
RH113: rmovsbw
reblast a7
rncrunch
align dword
RETable: dd offset RH000, offset RH001, offset RH002, offset RH003
dd offset RH010, offset RH011, offset RH012, offset RH013
dd offset RH100, offset RH101, offset RH102, offset RH103
dd offset RH110, offset RH111, offset RH112, offset RH113
align byte
@basta: ret ; terminate Spt blitting
;-----------------------END OF RLE BLIT CODE------------------------
public _PutSpt
_PutSpt:
; edi = scr dest
; esi = encoded sprite pic ptr
; eax = x in pixels
; edx = y in pixels
; bl = drawing flags
mov ecx,eax
add edi,[edx*4+_RowStart]
shr eax,PIXSHIFT
and ecx,PIXMUP
add edi,eax
inc ecx
BLITMODE BLITPLANE
; eax,edx thrashed
and ebx,LEFTRIGHT
jnz @esleftright
@esnorm:
mov ax,WWP0
mov dx,SEQUENCER
rol ah,cl
add esi,2 ; skip sprite header
mov ecx,4 ; set plane count
mov ebp,edi ; set line start
out dx,ax ; plane select
push eax
push ecx
push ebp
crunch
@esleftright:
; LEFT TO RIGHT <--> RIGHT TO LEFT
mov dx,SEQUENCER
mov ax,WWP3
rol ah,cl
dec cl
jz @esnoinc
inc edi
@esnoinc:
movzx ecx,byte ptr [esi]
shl ecx,2 ;big nudgets to nudgets
add esi,2
add edi,ecx
mov ecx,4
mov ebp,edi
out dx,ax ; seleziona il primo piano
push eax
push ecx
push ebp
rcrunch
align dword
plane dd 0
y dd 0
yheight dd 0
x dd 0
align byte
NO_WAY db 08
public _Pic2Spt
_Pic2Spt:
; converter from PIC bitmap format to SPT bitmap format
;
; ESI = pointer to PIC data
; EDI = pointer to buffer for SPT data
; returns:
; ESI = end of PIC data
; EDI = pointer to end of SPT bitmap data
; If PIC data is too big, EDI is equal to its initial value +2
push eax
push ebx
push ecx
push edx
push ebp
mov eax,0
mov ebx,0
mov plane,4
lodsw ; load&store bitmap header
stosw ;
xchg ah,bl ; eax= x ebx= y
shl eax,2 ; big-nudgets to nudgets
cmp eax,63 ; 63 nudgets == 252 pixels
jnbe the_end ; PIC too large for this bitmap compiler
mov x,eax ; store width for every plane
mov yheight,ebx ; store line count
jmp short comp_entry
newline:
dec y ;
jne inplane ; if NOT decoded last line, do not switch
; else switch plane
mov byte ptr [edi],0 ; store a switch-plane packet
inc edi ;
dec plane ;
je the_end ; is this the fourth plane ?
; no, another plane to compile
comp_entry:
mov eax,yheight ; get line count
mov ebx, offset NO_WAY ; lock smart-newlines
mov y,eax ; recharge line counter
inplane:
mov ecx,x ; reload width counter
mov ebp,ebx ; store previous packet head position into ebp
skippy_mode:
mov ebx,edi ; store packet head position
mov edx,0
add edi,2
skip:
mov al,[esi]
cmp al,0
jne xburst
; skip this pixels
inc esi ; to next pix
inc dh ; increase skip count
skipped1:
dec ecx
jne skip ; skip if not end of PIC line
; END OF PIC LINE WHILE SKIPPING
test byte ptr [ebp],8 ; had last packet a newline ?
jnz no_nu
; No, we can stuff a newline there
or byte ptr [ebp],08
sub edi,2 ; move back this pointer
jmp newline
no_nu: ; Yes, it had a newline.
; We have to waste one byte
mov byte ptr [ebx],8 ; packet
dec edi ; we don't need an increment for a simple newline
jmp newline
burst: mov al,[esi]
cmp al,0
je endburst ; test end of burst
xburst:
inc esi ; to next pix
mov [edi],al ;store pix
inc dl ; increase pixel burst counter
inc edi ; increase pointer
dec ecx
jne burst ; continue bursting pixels if not end ot PIC line
; compose burst packet
mov al,dl
and al,3 ; select non-dword count bits
or al,8 ; set newline bit
cmp dl,4
jb blit_d
or al,4 ; set dword_data bit
blit_d:
rol dl,2
and dl,0F0h ; position dword count into packet
or dl,al
mov [ebx],dx ; store packet head
jmp newline
endburst:
; end of pixel burst, store packet & restart skip counting
inc esi
; compose burst packet without newline
mov al,dl
and al,3 ; select non-dword count bits
; no newline here, next "skip" can be stuffed here
cmp dl,4
jb dblit_d
or al,4 ; set dword_data bit
dblit_d:
rol dl,2
and dl,0F0h ; position dword count into packet
or dl,al
mov [ebx],dx ; store packet head
mov ebp,ebx ; set previous_packet pointer
mov edx,0100h ; skip count is already 1
mov ebx,edi ; store packet head position
add edi,2 ; increase data pointer
jmp skipped1
the_end:
pop ebp
pop edx
pop ecx
pop ebx
pop eax
ret
code32 ends
END