708 lines
12 KiB
Text
708 lines
12 KiB
Text
;/****************************************************************************
|
|
;** MODULE: avidfill.asm
|
|
;** AUTHOR: Sami Tammilehto / Fennosoftec OY
|
|
;** DOCUMENT: ?
|
|
;** VERSION: 1.0
|
|
;** REFERENCE: -
|
|
;** REVISED BY: -
|
|
;*****************************************************************************
|
|
;**
|
|
;** Assembler / Video (polygon filling)
|
|
;**
|
|
;****************************************************************************/
|
|
|
|
;±±±±±±±± _vid_drawpolylist(...) ±±±±±±±±
|
|
;This call is obsolote. The correct call is to _draw_polylist.
|
|
_vid_drawpolylist PROC FAR
|
|
pop cx ;retoffset
|
|
pop dx ;retsegment
|
|
mov ax,0f001h
|
|
push ax ;oflags
|
|
push dx ;retsegment
|
|
push cx ;retoffset
|
|
jmp _draw_polylist ;draw.asm
|
|
_vid_drawpolylist ENDP
|
|
|
|
;±±±±±±±± _vid_drawfill(char *drawdata) ±±±±±±±±
|
|
;entry: [drawdata]=pointer to fill data stream
|
|
; exit: -
|
|
;descr: This routine fills a polygon on screen according to instructions in
|
|
; the data stream. The 'nrm' stands for normal = flat shaded polygon.
|
|
; Stream format: {FILL-DATA}
|
|
drawfill_progs LABEL WORD
|
|
dw OFFSET drawfill_nrm
|
|
dw OFFSET drawfill_grd
|
|
_vid_drawfill PROC FAR
|
|
CBEG
|
|
call vidstart
|
|
lfspar si,0
|
|
mov bx,ds:[si]
|
|
cmp bx,1
|
|
ja @@1
|
|
add bx,bx
|
|
add si,2
|
|
call drawfill_progs[bx]
|
|
@@1: CEND
|
|
_vid_drawfill ENDP
|
|
|
|
ALIGN 4
|
|
leftside db 1111b,1110b,1100b,1000b
|
|
rightside db 0001b,0011b,0111b,1111b
|
|
middledot db 0001b,0010b,0100b,1000b
|
|
ALIGN 16
|
|
vdf_leftx dd 0
|
|
vdf_lefta dd 0
|
|
vdf_rightx dd 0
|
|
vdf_righta dd 0
|
|
vdf_count dw 0
|
|
vdf_di dw 0
|
|
vdf_color db 0
|
|
ALIGN 16
|
|
vdfg_color1 dw 0
|
|
vdfg_color2 dw 0
|
|
vdfg_left dw 0
|
|
vdfg_right dw 0
|
|
vdfg_leftc dw 0 ;c & ca must be in this order for 32 bit
|
|
vdfg_leftca dw 0 ;data transfer (seek for [32])
|
|
vdfg_rightc dw 0
|
|
vdfg_rightca dw 0
|
|
vdfg_lefts dw 0
|
|
vdfg_left4 dw 0
|
|
vdfg_buf db MAXCOLS dup(0)
|
|
|
|
;±±±±±±±± drawfill_nrm ±±±±±±±±
|
|
;entry: DS:SI=pointer to {NORMAL-FILL-DATA} stream
|
|
; exit: -
|
|
drawfill_nrm PROC NEAR
|
|
mov ax,fs:[si]
|
|
mov cs:vdf_color,al
|
|
mov bx,fs:[si+2] ;StartY
|
|
add si,4
|
|
shl bx,1
|
|
mov ax,ds:_rows[bx]
|
|
mov cs:vdf_di,ax
|
|
;es:vdf_di=dest
|
|
jmp @@1
|
|
@@0: ret
|
|
|
|
@@1: mov ax,fs:[si]
|
|
add si,2
|
|
or ax,ax
|
|
js @@0
|
|
jz @@11
|
|
mov eax,fs:[si]
|
|
mov cs:vdf_leftx,eax
|
|
mov eax,fs:[si+4]
|
|
mov cs:vdf_lefta,eax
|
|
add si,8
|
|
@@11: mov ax,fs:[si]
|
|
add si,2
|
|
or ax,ax
|
|
js @@0
|
|
jz @@12
|
|
mov eax,fs:[si]
|
|
mov cs:vdf_rightx,eax
|
|
mov eax,fs:[si+4]
|
|
mov cs:vdf_righta,eax
|
|
add si,8
|
|
@@12: mov ax,fs:[si]
|
|
or ax,ax
|
|
jz @@0 ;ERROR
|
|
add si,2
|
|
mov cs:vdf_count,ax
|
|
mov di,cs:vdf_di
|
|
@@21: ;Fill loop
|
|
;;
|
|
mov eax,cs:vdf_lefta
|
|
add cs:vdf_leftx,eax
|
|
mov eax,cs:vdf_righta
|
|
add cs:vdf_rightx,eax
|
|
;
|
|
mov dx,word ptr cs:vdf_leftx[2]
|
|
mov ax,word ptr cs:vdf_rightx[2]
|
|
;dx=leftx, ax=rightx
|
|
;
|
|
cmp ax,dx
|
|
je @@20
|
|
jl @@22
|
|
xchg ax,dx
|
|
@@22: dec dx ;don't fill the rightmost pixel
|
|
|
|
mov bx,ax
|
|
sar bx,2
|
|
mov cx,dx
|
|
sar cx,2
|
|
sub cx,bx
|
|
add di,bx
|
|
|
|
mov bp,3
|
|
and bp,ax
|
|
mov bh,cs:leftside[bp]
|
|
mov bp,3
|
|
and bp,dx
|
|
mov bl,cs:rightside[bp]
|
|
mov dx,3c5h
|
|
|
|
;(di..si,bx)
|
|
cmp cx,0
|
|
je @@29 ;end and beg in same byte
|
|
;left side
|
|
mov al,bh
|
|
out dx,al
|
|
mov al,cs:vdf_color
|
|
stosb
|
|
dec cx
|
|
mov ah,al
|
|
;middle
|
|
jcxz @@24
|
|
mov al,0fh
|
|
out dx,al
|
|
cmp cx,8
|
|
jae @@23 ;fill >=8 pixels, do dword align
|
|
mov al,ah
|
|
shr cx,1
|
|
rep stosw
|
|
adc cx,cx
|
|
rep stosb
|
|
jmp @@24
|
|
@@23: mov al,ah
|
|
mov bp,ax
|
|
shl eax,16
|
|
mov ax,bp
|
|
;align
|
|
test di,3
|
|
jz @@25
|
|
stosb
|
|
dec cx
|
|
test di,3
|
|
jz @@25
|
|
stosb
|
|
dec cx
|
|
test di,3
|
|
jz @@25
|
|
stosb
|
|
dec cx
|
|
@@25: mov bp,cx
|
|
shr cx,2
|
|
rep stosd ;fill
|
|
mov cx,3
|
|
and cx,bp
|
|
rep stosb ;fill rest
|
|
@@24: ;right side
|
|
mov al,bl
|
|
out dx,al
|
|
mov al,ah
|
|
mov es:[di],al
|
|
jmp @@20
|
|
@@29: ;end and beg in same byte
|
|
mov al,bl
|
|
and al,bh
|
|
out dx,al
|
|
mov al,cs:vdf_color
|
|
mov es:[di],al
|
|
;;
|
|
@@20: mov di,cs:vdf_di
|
|
add di,ds:_rowlen
|
|
mov cs:vdf_di,di
|
|
dec cs:vdf_count
|
|
jnz @@21
|
|
jmp @@1
|
|
drawfill_nrm ENDP
|
|
|
|
;±±±±±±±± drawfill_grd ±±±±±±±±
|
|
;entry: DS:SI=pointer to {GOURAUD-FILL-DATA} stream
|
|
; exit: -
|
|
drawfill_grd PROC NEAR
|
|
mov bx,fs:[si+2] ;StartY
|
|
add si,4
|
|
shl bx,1
|
|
mov ax,ds:_rows[bx]
|
|
mov cs:vdf_di,ax
|
|
;es:vdf_di=dest
|
|
jmp @@1
|
|
@@0: ret
|
|
|
|
@@1: mov ax,fs:[si]
|
|
add si,2
|
|
or ax,ax
|
|
js @@0
|
|
jz @@11
|
|
mov eax,fs:[si] ;c&ca
|
|
mov dword ptr cs:vdfg_leftc,eax ;[32]
|
|
mov eax,fs:[si+4]
|
|
mov cs:vdf_leftx,eax
|
|
mov eax,fs:[si+8]
|
|
mov cs:vdf_lefta,eax
|
|
add si,12
|
|
@@11: mov ax,fs:[si]
|
|
add si,2
|
|
or ax,ax
|
|
js @@0
|
|
jz @@12
|
|
mov eax,fs:[si] ;c&ca
|
|
mov dword ptr cs:vdfg_rightc,eax ;[32]
|
|
mov eax,fs:[si+4]
|
|
mov cs:vdf_rightx,eax
|
|
mov eax,fs:[si+8]
|
|
mov cs:vdf_righta,eax
|
|
add si,12
|
|
@@12: mov ax,fs:[si]
|
|
or ax,ax
|
|
jz @@0 ;ERROR
|
|
add si,2
|
|
mov cs:vdf_count,ax
|
|
mov di,cs:vdf_di
|
|
@@21: ;Fill loop
|
|
;;
|
|
mov ax,cs:vdfg_leftca
|
|
add cs:vdfg_leftc,ax
|
|
mov ax,cs:vdfg_rightca
|
|
add cs:vdfg_rightc,ax
|
|
mov eax,cs:vdf_lefta
|
|
add cs:vdf_leftx,eax
|
|
mov eax,cs:vdf_righta
|
|
add cs:vdf_rightx,eax
|
|
;
|
|
mov dx,word ptr cs:vdf_leftx[2]
|
|
mov ax,word ptr cs:vdf_rightx[2]
|
|
mov bx,word ptr cs:vdfg_leftc
|
|
mov cx,word ptr cs:vdfg_rightc
|
|
;dx=leftx, ax=rightx
|
|
;
|
|
cmp ax,dx
|
|
je @@20
|
|
jl @@22
|
|
xchg bx,cx
|
|
xchg ax,dx
|
|
@@22: dec dx ;don't fill the rightmost pixel
|
|
mov cs:vdfg_color1,cx
|
|
mov cs:vdfg_color2,bx
|
|
mov cs:vdfg_left,ax
|
|
mov cs:vdfg_right,dx
|
|
;set endpoint colors
|
|
mov dx,3c5h
|
|
;end
|
|
mov bl,byte ptr cs:vdfg_right
|
|
test bl,1
|
|
jnz @@ef2
|
|
and bx,3
|
|
mov al,cs:middledot[bx]
|
|
out dx,al
|
|
mov bx,cs:vdfg_right
|
|
shr bx,2
|
|
add bx,di
|
|
mov al,byte ptr cs:vdfg_color2[1]
|
|
mov es:[bx],al
|
|
@@ef2: ;start
|
|
mov bl,byte ptr cs:vdfg_left
|
|
test bl,1
|
|
jz @@ef1
|
|
and bx,3
|
|
mov al,cs:middledot[bx]
|
|
out dx,al
|
|
mov bx,cs:vdfg_left
|
|
shr bx,2
|
|
add bx,di
|
|
mov al,byte ptr cs:vdfg_color1[1]
|
|
mov es:[bx],al
|
|
@@ef1: ;calc length & beg
|
|
mov ax,cs:vdfg_left
|
|
mov dx,cs:vdfg_right
|
|
inc ax
|
|
shr ax,1
|
|
mov cs:vdfg_lefts,ax
|
|
dec dx
|
|
shr dx,1
|
|
;
|
|
mov cx,ax
|
|
shr cx,1
|
|
add di,cx
|
|
;
|
|
mov cx,dx
|
|
sub cx,ax
|
|
inc cx ;cx=number of 2 byte blocks to fill
|
|
cmp cx,0
|
|
jg @@2f2
|
|
;ends only
|
|
jmp @@20
|
|
@@2f2:
|
|
push si
|
|
mov ax,cs:vdfg_color1
|
|
sub ax,cs:vdfg_color2
|
|
jge @@2f3
|
|
neg ax
|
|
mov bx,cx
|
|
add bx,bx
|
|
mul word ptr ds:_afilldiv[bx]
|
|
neg dx
|
|
jmp @@2f4
|
|
@@2f3: mov bx,cx
|
|
add bx,bx
|
|
mul word ptr ds:_afilldiv[bx]
|
|
@@2f4: mov si,cx
|
|
|
|
@@d0: ;dx=coloradder, cx=len (in 2 byte blocks)
|
|
cmp dx,128
|
|
jge gouraud12
|
|
cmp dx,-128
|
|
jle gouraud12
|
|
jmp gouraud4
|
|
gouraud12:
|
|
cmp dx,400
|
|
jge gouraud1
|
|
cmp dx,-400
|
|
jle gouraud1
|
|
jmp gouraud2
|
|
|
|
;----------------------------------------------------------------
|
|
|
|
gouraud1 PROC NEAR ;1 pixel accuray
|
|
sar dx,1
|
|
add cx,cx
|
|
;
|
|
mov ax,cx
|
|
shl cx,3
|
|
sub ax,cx
|
|
;ax=-cx*7
|
|
add ax,OFFSET @@vdfg_fcode
|
|
mov bx,cs:vdfg_color2
|
|
jmp ax
|
|
|
|
zzz=MAXCOLS
|
|
REPT MAXCOLS+1
|
|
add bx,dx ;2 bytes
|
|
mov cs:vdfg_buf[ (zzz and 3)*(MAXCOLS/4) + (zzz shr 2) ],bh ;5 bytes
|
|
zzz=zzz-1
|
|
ENDM
|
|
mov ax,bx ;2 bytes, 1 clock (filler)
|
|
@@vdfg_fcode:
|
|
push ds
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov cx,si
|
|
add cx,cx
|
|
;
|
|
@@f1: mov al,00010001b
|
|
test cs:vdfg_lefts,1
|
|
jz @@f2
|
|
mov al,01000100b
|
|
@@f2: ;
|
|
zzz=0
|
|
add cx,3
|
|
REPT 4
|
|
local l1
|
|
push cx
|
|
shr cx,2
|
|
jz l1
|
|
push ax
|
|
push di
|
|
mov dx,3c5h
|
|
out dx,al
|
|
mov si,OFFSET vdfg_buf+zzz*(MAXCOLS/4)
|
|
call fastmovsb
|
|
pop di
|
|
pop ax
|
|
l1: pop cx
|
|
dec cx
|
|
rol al,1
|
|
adc di,0
|
|
zzz=zzz+1
|
|
ENDM
|
|
;
|
|
@@f0: pop ds
|
|
pop si
|
|
jmp zzz20
|
|
gouraud1 ENDP
|
|
|
|
;----------------------------------------------------------------
|
|
|
|
gouraud2 PROC NEAR ;2 pixel accuray
|
|
mov ax,cx
|
|
shl cx,3
|
|
sub ax,cx
|
|
;ax=-cx*7
|
|
add ax,OFFSET @@vdfg_fcode
|
|
mov bx,cs:vdfg_color2
|
|
jmp ax
|
|
|
|
zzz=MAXCOLS
|
|
REPT MAXCOLS+1
|
|
add bx,dx ;2 bytes
|
|
mov cs:vdfg_buf[ (zzz and 1)*(MAXCOLS/2) + (zzz shr 1) ],bh ;5 bytes
|
|
zzz=zzz-1
|
|
ENDM
|
|
mov ax,bx ;2 bytes, 1 clock (filler)
|
|
@@vdfg_fcode:
|
|
push ds
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov cx,si
|
|
jcxz @@f0
|
|
;
|
|
@@f1: mov al,00110011b
|
|
test cs:vdfg_lefts,1
|
|
jz @@f2
|
|
mov al,11001100b
|
|
@@f2: ;
|
|
mov si,OFFSET vdfg_buf
|
|
push cx
|
|
push di
|
|
push ax
|
|
inc cx
|
|
shr cx,1
|
|
mov dx,3c5h
|
|
out dx,al
|
|
call fastmovsb
|
|
pop ax
|
|
pop di
|
|
pop cx
|
|
rol al,2
|
|
jnc @@f3
|
|
inc di
|
|
@@f3: mov si,OFFSET vdfg_buf+MAXCOLS/2
|
|
shr cx,1
|
|
jz @@f0
|
|
mov dx,3c5h
|
|
out dx,al
|
|
call fastmovsb
|
|
;
|
|
@@f0: pop ds
|
|
pop si
|
|
jmp zzz20
|
|
gouraud2 ENDP
|
|
|
|
;----------------------------------------------------------------
|
|
|
|
gouraud4 PROC NEAR ;4 pixel accuray
|
|
cmp cx,4
|
|
jl gouraud2
|
|
sal dx,1
|
|
;
|
|
mov cs:vdfg_left4,cx
|
|
shr cx,1 ;rescale
|
|
inc cx ;one extra
|
|
mov ax,cx
|
|
shl cx,3
|
|
sub ax,cx
|
|
;ax=-cx*7
|
|
add ax,OFFSET @@vdfg_fcode
|
|
mov bx,cs:vdfg_color2
|
|
sub bx,dx ;one extra
|
|
jmp ax
|
|
|
|
zzz=MAXCOLS
|
|
REPT MAXCOLS+1
|
|
add bx,dx ;2 bytes
|
|
mov cs:vdfg_buf[zzz],bh ;5 bytes
|
|
zzz=zzz-1
|
|
ENDM
|
|
mov ax,bx ;2 bytes, 1 clock (filler)
|
|
@@vdfg_fcode:
|
|
push ds
|
|
mov dx,cs
|
|
mov ds,dx
|
|
mov cx,si
|
|
;
|
|
@@f1: mov si,OFFSET vdfg_buf
|
|
test cs:vdfg_lefts,1
|
|
jnz @@f3
|
|
inc cx
|
|
@@f4: shr cx,1
|
|
jnc @@f5
|
|
mov dx,3c5h
|
|
mov al,0fh
|
|
out dx,al
|
|
call fastmovsb
|
|
@@f0: pop ds
|
|
pop si
|
|
jmp zzz20
|
|
|
|
@@f5: dec cx
|
|
mov dx,3c5h
|
|
mov al,0fh
|
|
out dx,al
|
|
call fastmovsb
|
|
mov dx,3c5h
|
|
mov al,03h
|
|
out dx,al
|
|
movsb
|
|
pop ds
|
|
pop si
|
|
jmp zzz20
|
|
|
|
@@f3: mov dx,3c5h
|
|
mov al,0ch
|
|
out dx,al
|
|
movsb
|
|
jmp @@f4
|
|
gouraud4 ENDP
|
|
|
|
;----------------------------------------------------------------
|
|
|
|
zzz20: ;;
|
|
@@20: mov di,cs:vdf_di
|
|
add di,ds:_rowlen
|
|
mov cs:vdf_di,di
|
|
dec cs:vdf_count
|
|
jnz @@21
|
|
jmp @@1
|
|
drawfill_grd ENDP
|
|
|
|
;±±±±±±±± fastmovsb ±±±±±±±±
|
|
;entry: DS:SI=pointer to source data
|
|
; ES:DI=pointer to destination (screen)
|
|
; CX=number of bytes to copy
|
|
;exit: copies data like REP MOVSB but uses 32 bit moves and aligns
|
|
; destination to dword boundary.
|
|
ALIGN 16
|
|
fastmovsb_bt LABEL WORD
|
|
dw OFFSET fastmovsb_b0
|
|
dw OFFSET fastmovsb_b1
|
|
dw OFFSET fastmovsb_b2
|
|
dw OFFSET fastmovsb_b3
|
|
fastmovsb_b1:
|
|
mov al,ds:[si]
|
|
sub cx,3
|
|
mov es:[di],al
|
|
mov ax,ds:[si+1]
|
|
add si,3
|
|
mov es:[di+1],ax
|
|
add di,3
|
|
jmp fastmovsb_b0
|
|
fastmovsb_b2:
|
|
mov ax,ds:[si]
|
|
sub cx,2
|
|
add si,2
|
|
mov es:[di],ax
|
|
add di,2
|
|
jmp fastmovsb_b0
|
|
fastmovsb_b3:
|
|
mov al,ds:[si]
|
|
dec cx
|
|
inc si
|
|
mov es:[di],al
|
|
inc di
|
|
jmp fastmovsb_b0
|
|
;;
|
|
ALIGN 16
|
|
fastmovsb_et LABEL WORD
|
|
dw OFFSET fastmovsb_e0
|
|
dw OFFSET fastmovsb_e1
|
|
dw OFFSET fastmovsb_e2
|
|
dw OFFSET fastmovsb_e3
|
|
fastmovsb_e1:
|
|
mov al,ds:[si]
|
|
inc si
|
|
mov es:[di],al
|
|
inc di
|
|
ret
|
|
fastmovsb_e3:
|
|
mov ax,ds:[si]
|
|
mov es:[di],ax
|
|
mov al,ds:[si+2]
|
|
add si,3
|
|
mov es:[di+2],al
|
|
add di,3
|
|
ret
|
|
fastmovsb_e2:
|
|
mov ax,ds:[si]
|
|
add si,2
|
|
mov es:[di],ax
|
|
add di,2
|
|
fastmovsb_e0:
|
|
ret
|
|
;;
|
|
ALIGN 16
|
|
fastmovsb PROC NEAR
|
|
;copies CX bytes of data from DS:SI to ES:DI aligning destination
|
|
;si/di will point to the correct position after this (cx won't)
|
|
cmp cx,4
|
|
jb @@4
|
|
mov bx,di
|
|
and bx,3
|
|
add bx,bx
|
|
jmp fastmovsb_bt[bx]
|
|
fastmovsb_b0:
|
|
mov bx,cx
|
|
and bx,3
|
|
add bx,bx
|
|
shr cx,2
|
|
rep movsd
|
|
jmp fastmovsb_et[bx]
|
|
@@4: mov bx,cx
|
|
add bx,bx
|
|
jmp fastmovsb_et[bx]
|
|
fastmovsb ENDP
|
|
|
|
;±±±±±±±± faststosb ±±±±±±±±
|
|
;entry: ES:DI=pointer to destination (screen)
|
|
; EAX=dword fill (all bytes MUST be same)
|
|
; CX=number of bytes to fill††
|
|
;exit: fills data like REP STOSB but uses 32 bit moves and aligns
|
|
; destination to dword boundary.
|
|
ALIGN 16
|
|
faststosb_bt LABEL WORD
|
|
dw OFFSET faststosb_b0
|
|
dw OFFSET faststosb_b1
|
|
dw OFFSET faststosb_b2
|
|
dw OFFSET faststosb_b3
|
|
faststosb_b1:
|
|
sub cx,3
|
|
mov es:[di],al
|
|
mov es:[di+1],ax
|
|
add di,3
|
|
jmp faststosb_b0
|
|
faststosb_b2:
|
|
sub cx,2
|
|
mov es:[di],ax
|
|
add di,2
|
|
jmp faststosb_b0
|
|
faststosb_b3:
|
|
dec cx
|
|
mov es:[di],al
|
|
inc di
|
|
jmp faststosb_b0
|
|
;;
|
|
ALIGN 16
|
|
faststosb_et LABEL WORD
|
|
dw OFFSET faststosb_e0
|
|
dw OFFSET faststosb_e1
|
|
dw OFFSET faststosb_e2
|
|
dw OFFSET faststosb_e3
|
|
faststosb_e1:
|
|
mov es:[di],al
|
|
inc di
|
|
ret
|
|
faststosb_e3:
|
|
mov es:[di],ax
|
|
mov es:[di+2],al
|
|
add di,3
|
|
ret
|
|
faststosb_e2:
|
|
mov es:[di],ax
|
|
add di,2
|
|
faststosb_e0:
|
|
ret
|
|
;;
|
|
ALIGN 16
|
|
faststosb PROC NEAR
|
|
;fills CX bytes of data with AX to ES:DI aligning destination
|
|
;di will point to the correct position after this (cx won't)
|
|
cmp cx,4
|
|
jb @@4
|
|
mov bx,di
|
|
and bx,3
|
|
add bx,bx
|
|
jmp faststosb_bt[bx]
|
|
faststosb_b0:
|
|
mov bx,cx
|
|
and bx,3
|
|
add bx,bx
|
|
shr cx,2
|
|
rep movsd
|
|
jmp faststosb_et[bx]
|
|
@@4: mov bx,cx
|
|
add bx,bx
|
|
jmp faststosb_et[bx]
|
|
faststosb ENDP
|
|
|