552 lines
11 KiB
NASM
552 lines
11 KiB
NASM
;/****************************************************************************
|
|
;** MODULE: adrawclp.asm
|
|
;** AUTHOR: Sami Tammilehto / Fennosoftec OY
|
|
;** DOCUMENT: ?
|
|
;** VERSION: 1.0
|
|
;** REFERENCE: -
|
|
;** REVISED BY: -
|
|
;*****************************************************************************
|
|
;**
|
|
;** Polygon clipping (included to adraw.asm)
|
|
;** All routines take DS:SI as an entry list and write a clipped list to
|
|
;** ES:DI. The clipnear also returns in AX the orred visvf for the clipped
|
|
;** polygon since it might change during Z clipping.
|
|
;**
|
|
;****************************************************************************/
|
|
|
|
ALIGN 16
|
|
newclipflip db 0,0
|
|
newclipprog dw 0
|
|
clipcount dw 0
|
|
clipzero dw 0
|
|
clipvisfl dw 0
|
|
|
|
newclip_grd PROC NEAR
|
|
;DS:BX->DS:SI is clipped at CX (BX end=0..16384=SI end)
|
|
;resulted clip stored to ES:DI
|
|
mov ax,ds:[bx+POLYGR]
|
|
sub ax,ds:[si+POLYGR]
|
|
imul cx
|
|
shld dx,ax,2
|
|
add dx,ds:[si+POLYGR]
|
|
mov ds:[di+POLYGR],dx
|
|
ret
|
|
ENDP
|
|
|
|
NEWCLIPCALC MACRO clipped,other
|
|
local l1,l2,l3,l4,l5,l6
|
|
;DS:BX->DS:SI is clipped at (-,BP) with result stored to DS:DI
|
|
push si
|
|
push bx
|
|
push bp
|
|
mov dx,ds:[si+other]
|
|
mov cx,ds:[si+clipped]
|
|
mov ax,ds:[bx+other]
|
|
mov bx,ds:[bx+clipped]
|
|
mov cs:newclipflip,0
|
|
cmp cx,bx
|
|
jl l3
|
|
mov cs:newclipflip,1
|
|
xchg cx,bx
|
|
xchg ax,dx
|
|
l3: push dx
|
|
sub bp,cx
|
|
sub ax,dx
|
|
push ax
|
|
mov dx,bp
|
|
xor ax,ax
|
|
shrd ax,dx,2
|
|
sar dx,2
|
|
;dx:ax=short length*16384
|
|
sub bx,cx
|
|
idiv bx
|
|
mov bx,ax
|
|
;bx=0..16384 multiplier
|
|
pop ax
|
|
imul bx
|
|
shld dx,ax,2
|
|
pop ax
|
|
add dx,ax ;dx=clipped other
|
|
pop bp
|
|
mov cx,bp
|
|
cmp ds:[di+other-4],dx
|
|
jne l1
|
|
cmp ds:[di+clipped-4],cx
|
|
jne l1
|
|
jmp l2
|
|
l1: mov ds:[di+other],dx
|
|
mov ds:[di+clipped],cx
|
|
mov cx,bx
|
|
pop bx
|
|
mov ax,cs:newclipprog
|
|
or ax,ax
|
|
jz l4
|
|
mov dl,cs:newclipflip
|
|
or dl,dl
|
|
jz l6
|
|
xchg si,bx
|
|
l6: call ax ;also stores gouraud&texture clipped
|
|
l4: add di,4
|
|
jmp l5
|
|
l2: pop bx
|
|
l5: pop si
|
|
ENDM
|
|
|
|
NEWCLIPNEXT MACRO ;sets bx(last)=si(current) and loads si with next vertex
|
|
local l1,l2
|
|
mov bx,si
|
|
mov dx,cs:clipcount
|
|
dec dx
|
|
cmp dx,1
|
|
jl @@0 ;list ended, jmp to end of clip procedure
|
|
mov cs:clipcount,dx
|
|
jg l1
|
|
;1 vertex left, means we rotated the list
|
|
mov si,cs:clipzero
|
|
jmp l2
|
|
l1: add si,4
|
|
l2: ENDM
|
|
|
|
NEWCLIPCOPY MACRO ;should copy also texture
|
|
local l1
|
|
mov eax,ds:[si+POLYX] ;&POLYY
|
|
cmp ds:[di+POLYX-4],eax
|
|
je l1
|
|
mov ds:[di+POLYX],eax
|
|
mov ax,ds:[si+POLYGR]
|
|
mov ds:[di+POLYGR],ax
|
|
add di,4
|
|
l1: ENDM
|
|
|
|
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
ZCLIPCLIP MACRO
|
|
local l1,l41,l42,l43,l44
|
|
;(fs:bp)-(fs:bx) is clipped at (-,-,ECX) with result stored to (DX,CX) & AX=visfl
|
|
push bx
|
|
push bp
|
|
push esi
|
|
push edi
|
|
push ecx
|
|
;
|
|
mov eax,fs:[bx+vlist_z]
|
|
mov edx,fs:[bp+vlist_z]
|
|
cmp eax,edx
|
|
jg l1
|
|
xchg eax,edx
|
|
xchg bx,bp
|
|
l1: ;EAX=farther vertex (>EDX), BX=offset of farther vertex
|
|
mov esi,eax
|
|
mov edi,eax
|
|
sub esi,edx ;>=0 divver
|
|
sub edi,ecx ;>=0 muller, esi>edi
|
|
;
|
|
mov eax,fs:[bp+vlist_x]
|
|
sub eax,fs:[bx+vlist_x]
|
|
imul edi
|
|
idiv esi
|
|
add eax,fs:[bx+vlist_x]
|
|
push eax
|
|
;
|
|
mov eax,fs:[bp+vlist_y]
|
|
sub eax,fs:[bx+vlist_y]
|
|
imul edi
|
|
idiv esi
|
|
add eax,fs:[bx+vlist_y]
|
|
;
|
|
pop esi ;X
|
|
pop ecx ;cliplimit
|
|
xor di,di
|
|
;
|
|
imul gs:_projmuly
|
|
idiv ecx
|
|
add eax,gs:_projaddy
|
|
cmp eax,gs:_projclipy[CLIPMAX]
|
|
jng l41
|
|
or di,VF_DOWN
|
|
l41: cmp eax,gs:_projclipy[CLIPMIN]
|
|
jnl l42
|
|
or di,VF_UP
|
|
l42: push ax
|
|
;
|
|
mov eax,esi
|
|
imul gs:_projmulx
|
|
idiv ecx
|
|
add eax,gs:_projaddx
|
|
cmp eax,gs:_projclipx[CLIPMAX]
|
|
jng l43
|
|
or di,VF_RIGHT
|
|
l43: cmp eax,gs:_projclipx[CLIPMIN]
|
|
jnl l44
|
|
or di,VF_LEFT
|
|
l44: ;
|
|
mov dx,ax
|
|
mov ax,di
|
|
pop cx
|
|
;dx=x,cx=y,ax=visfl
|
|
pop edi
|
|
pop esi
|
|
pop bp
|
|
pop bx
|
|
;NOTE: ECX was destroyed while clipping. It is used to return data.
|
|
;It must be pushed by the 'calling' procedure after the macro and
|
|
;the usage of the data the macro returned!
|
|
ENDM
|
|
|
|
ZCLIPGETVX MACRO ;reads to bx the offset of next vertex from DS:SI (copies last vx to bp)
|
|
local l1,l2
|
|
mov bp,bx
|
|
mov dx,cs:clipcount
|
|
dec dx
|
|
cmp dx,1
|
|
jl @@0 ;list ended, jmp to end of clip procedure
|
|
mov cs:clipcount,dx
|
|
jg l1
|
|
;1 vertex left, means we rotated the list
|
|
mov si,cs:clipzero
|
|
jmp l2
|
|
l1: add si,4
|
|
l2: mov bx,ds:[si+POLYVX]
|
|
ENDM
|
|
|
|
ZCLIPADDVISVX MACRO ;adds ds:si[bx+POLYX/Y] to list (the vx must be visible for this to work) at DS:DI
|
|
local l1,l2
|
|
mov dx,ds:[si+POLYX]
|
|
mov ax,ds:[si+POLYY]
|
|
cmp ds:[di+POLYX-4],dx
|
|
jne l1
|
|
cmp ds:[di+POLYY-4],ax
|
|
jne l1
|
|
jmp l2
|
|
l1: mov ds:[di+POLYX],dx
|
|
mov ds:[di+POLYY],ax
|
|
mov ax,ds:[si+POLYGR]
|
|
mov ds:[di+POLYGR],ax
|
|
add di,4
|
|
l2: ;;;
|
|
ENDM
|
|
|
|
ZCLIPADDVX MACRO ;adds (DX,CX) to list at DS:DI
|
|
local l1,l2
|
|
cmp ds:[di+POLYX-4],dx
|
|
jne l1
|
|
cmp ds:[di+POLYY-4],cx
|
|
jne l1
|
|
jmp l2
|
|
l1: mov ds:[di+POLYX],dx
|
|
mov ds:[di+POLYY],cx
|
|
mov ax,ds:[di-4+POLYGR]
|
|
mov ds:[di+POLYGR],ax
|
|
add di,4
|
|
l2: ;;;
|
|
ENDM
|
|
|
|
clipnear PROC NEAR
|
|
;clips list DS:SI -> DS:DI (source list must NOT be empty)
|
|
push bp
|
|
push si
|
|
push di
|
|
mov cs:clipzero,si
|
|
mov ecx,gs:_projclipz[CLIPMIN] ;ECX=cliplimit
|
|
mov eax,ds:[si+POLYSIDES] ;&POLYCOLOR
|
|
mov ds:[di+POLYSIDES],eax
|
|
inc ax
|
|
mov cs:clipcount,ax
|
|
mov eax,ds:[si+POLYFLAGS] ;&POLYVXSEG
|
|
mov ds:[di+POLYFLAGS],eax
|
|
mov fs,ds:[si+POLYVXSEG]
|
|
|
|
mov word ptr ds:[di+POLYX-4],07fffh ;for CLIPADDVX to surely do it's work
|
|
|
|
mov bx,ds:[si+POLYVX]
|
|
cmp ecx,fs:[bx+vlist_z]
|
|
jle @@2
|
|
|
|
@@1: ;LAST POINT HIDDEN
|
|
ZCLIPGETVX
|
|
cmp ecx,fs:[bx+vlist_z]
|
|
jge @@1
|
|
;this point visible, clip
|
|
ZCLIPCLIP ;returns data in cx
|
|
or cs:clipvisfl,ax
|
|
ZCLIPADDVX
|
|
mov ecx,gs:_projclipz[CLIPMIN] ;ECX was destroyed by ZCLIPCLIP
|
|
|
|
@@2: ;LAST POINT VISIBLE
|
|
ZCLIPADDVISVX
|
|
ZCLIPGETVX
|
|
cmp ecx,fs:[bx+vlist_z]
|
|
jle @@2
|
|
;this point hidden, clip
|
|
ZCLIPCLIP ;returns data in cx
|
|
or cs:clipvisfl,ax
|
|
ZCLIPADDVX
|
|
mov ecx,gs:_projclipz[CLIPMIN] ;ECX was destroyed by ZCLIPCLIP
|
|
jmp @@1 ;to hidden
|
|
|
|
@@0: pop bx
|
|
sub di,bx
|
|
shr di,2
|
|
mov ds:[bx+POLYSIDES],di ;Sides in clipped polygon
|
|
mov di,bx
|
|
pop si
|
|
pop bp
|
|
mov ax,cs:clipvisfl
|
|
ret
|
|
clipnear ENDP
|
|
|
|
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
|
newclipup PROC NEAR
|
|
;clips list DS:SI -> DS:DI (source list must NOT be empty)
|
|
push bp
|
|
push si
|
|
push di
|
|
mov cs:clipzero,si
|
|
mov bp,word ptr gs:_projclipy[CLIPMIN]
|
|
mov eax,ds:[si+POLYSIDES] ;&POLYCOLOR
|
|
mov ds:[di+POLYSIDES],eax
|
|
inc ax
|
|
mov cs:clipcount,ax
|
|
mov eax,ds:[si+POLYFLAGS] ;&POLYVXSEG
|
|
mov ds:[di+POLYFLAGS],eax
|
|
|
|
mov word ptr ds:[di+POLYX-4],07fffh ;for CLIPADDVX to surely do it's work
|
|
|
|
;bx=last, si=current
|
|
cmp ds:[si+POLYY],bp
|
|
jge @@2
|
|
|
|
@@1: ;LAST POINT HIDDEN
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYY],bp
|
|
jle @@1
|
|
;this point visible, clip
|
|
NEWCLIPCALC POLYY,POLYX
|
|
|
|
@@2: ;LAST POINT VISIBLE
|
|
NEWCLIPCOPY ;copies always also texture & gouraud
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYY],bp
|
|
jge @@2
|
|
;this point hidden, clip
|
|
NEWCLIPCALC POLYY,POLYX
|
|
jmp @@1 ;to hidden
|
|
|
|
@@0: pop bx
|
|
sub di,bx
|
|
shr di,2
|
|
mov ds:[bx+POLYSIDES],di ;Sides in clipped polygon
|
|
mov di,bx
|
|
pop si
|
|
pop bp
|
|
ret
|
|
newclipup ENDP
|
|
|
|
newclipdown PROC NEAR
|
|
;clips list DS:SI -> DS:DI (source list must NOT be empty)
|
|
push bp
|
|
push si
|
|
push di
|
|
mov cs:clipzero,si
|
|
mov bp,word ptr gs:_projclipy[CLIPMAX]
|
|
mov eax,ds:[si+POLYSIDES] ;&POLYCOLOR
|
|
mov ds:[di+POLYSIDES],eax
|
|
inc ax
|
|
mov cs:clipcount,ax
|
|
mov eax,ds:[si+POLYFLAGS] ;&POLYVXSEG
|
|
mov ds:[di+POLYFLAGS],eax
|
|
|
|
mov word ptr ds:[di+POLYX-4],07fffh ;for CLIPADDVX to surely do it's work
|
|
|
|
;bx=last, si=current
|
|
cmp ds:[si+POLYY],bp
|
|
jle @@2
|
|
|
|
@@1: ;LAST POINT HIDDEN
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYY],bp
|
|
jge @@1
|
|
;this point visible, clip
|
|
NEWCLIPCALC POLYY,POLYX
|
|
|
|
@@2: ;LAST POINT VISIBLE
|
|
NEWCLIPCOPY ;copies always also texture & gouraud
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYY],bp
|
|
jle @@2
|
|
;this point hidden, clip
|
|
NEWCLIPCALC POLYY,POLYX
|
|
jmp @@1 ;to hidden
|
|
|
|
@@0: pop bx
|
|
sub di,bx
|
|
shr di,2
|
|
mov ds:[bx+POLYSIDES],di ;Sides in clipped polygon
|
|
mov di,bx
|
|
pop si
|
|
pop bp
|
|
ret
|
|
newclipdown ENDP
|
|
|
|
newclipleft PROC NEAR
|
|
;clips list DS:SI -> DS:DI (source list must NOT be empty)
|
|
push bp
|
|
push si
|
|
push di
|
|
mov cs:clipzero,si
|
|
mov bp,word ptr gs:_projclipx[CLIPMIN]
|
|
mov eax,ds:[si+POLYSIDES] ;&POLYCOLOR
|
|
mov ds:[di+POLYSIDES],eax
|
|
inc ax
|
|
mov cs:clipcount,ax
|
|
mov eax,ds:[si+POLYFLAGS] ;&POLYVXSEG
|
|
mov ds:[di+POLYFLAGS],eax
|
|
|
|
mov word ptr ds:[di+POLYX-4],07fffh ;for CLIPADDVX to surely do it's work
|
|
|
|
;bx=last, si=current
|
|
cmp ds:[si+POLYX],bp
|
|
jge @@2
|
|
|
|
@@1: ;LAST POINT HIDDEN
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYX],bp
|
|
jle @@1
|
|
;this point visible, clip
|
|
NEWCLIPCALC POLYX,POLYY
|
|
|
|
@@2: ;LAST POINT VISIBLE
|
|
NEWCLIPCOPY ;copies always also texture & gouraud
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYX],bp
|
|
jge @@2
|
|
;this point hidden, clip
|
|
NEWCLIPCALC POLYX,POLYY
|
|
jmp @@1 ;to hidden
|
|
|
|
@@0: pop bx
|
|
sub di,bx
|
|
shr di,2
|
|
mov ds:[bx+POLYSIDES],di ;Sides in clipped polygon
|
|
mov di,bx
|
|
pop si
|
|
pop bp
|
|
ret
|
|
newclipleft ENDP
|
|
|
|
newclipright PROC NEAR
|
|
;clips list DS:SI -> DS:DI (source list must NOT be empty)
|
|
push bp
|
|
push si
|
|
push di
|
|
mov cs:clipzero,si
|
|
mov bp,word ptr gs:_projclipx[CLIPMAX]
|
|
mov eax,ds:[si+POLYSIDES] ;&POLYCOLOR
|
|
mov ds:[di+POLYSIDES],eax
|
|
inc ax
|
|
mov cs:clipcount,ax
|
|
mov eax,ds:[si+POLYFLAGS] ;&POLYVXSEG
|
|
mov ds:[di+POLYFLAGS],eax
|
|
|
|
mov word ptr ds:[di+POLYX-4],07fffh ;for CLIPADDVX to surely do it's work
|
|
|
|
;bx=last, si=current
|
|
cmp ds:[si+POLYX],bp
|
|
jle @@2
|
|
|
|
@@1: ;LAST POINT HIDDEN
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYX],bp
|
|
jge @@1
|
|
;this point visible, clip
|
|
NEWCLIPCALC POLYX,POLYY
|
|
|
|
@@2: ;LAST POINT VISIBLE
|
|
NEWCLIPCOPY ;copies always also texture & gouraud
|
|
NEWCLIPNEXT
|
|
cmp ds:[si+POLYX],bp
|
|
jle @@2
|
|
;this point hidden, clip
|
|
NEWCLIPCALC POLYX,POLYY
|
|
jmp @@1 ;to hidden
|
|
|
|
@@0: pop bx
|
|
sub di,bx
|
|
shr di,2
|
|
mov ds:[bx+POLYSIDES],di ;Sides in clipped polygon
|
|
mov di,bx
|
|
pop si
|
|
pop bp
|
|
ret
|
|
newclipright ENDP
|
|
|
|
newclip PROC NEAR
|
|
;ENTRY:
|
|
;ds:si=pointer to list to be clipped
|
|
;ds:di=pointer to temporary list
|
|
;dx=visibility flag for polygon
|
|
;ax=flags for polygon (determines if texture and/or gouraud is clipped)
|
|
;EXIT:
|
|
;ds:si=clipped list (could be either of the entry lists)
|
|
xor bx,bx
|
|
test ax,F_GOURAUD
|
|
jz @@f1
|
|
mov bx,OFFSET newclip_grd
|
|
@@f1: mov cs:newclipprog,bx
|
|
;
|
|
LOADGS
|
|
test dh,VF_FAR ;If *ANY* vertex is 'far', entire polygon is
|
|
jnz @@cl7 ;skipped (no clipping visible far away)
|
|
test dl,VF_NEAR ;ClipNear must be done first, for in NEAR case
|
|
jz @@cl6 ;not all vertices are even calculated!
|
|
cmp word ptr ds:[si+POLYSIDES],0
|
|
je @@cl6
|
|
push dx
|
|
call clipnear
|
|
xchg si,di
|
|
pop dx ; clipnear return in ax the visfl for new vertices.
|
|
or dl,al ;<-this is done so that if the new vertices are outside the screen they'll be clipped
|
|
@@cl6: ;
|
|
test dl,VF_UP
|
|
jz @@cl1
|
|
cmp word ptr ds:[si+POLYSIDES],0
|
|
je @@cl1
|
|
push dx
|
|
call newclipup
|
|
xchg si,di
|
|
pop dx
|
|
@@cl1: ;
|
|
test dl,VF_DOWN
|
|
jz @@cl2
|
|
cmp word ptr ds:[si+POLYSIDES],0
|
|
je @@cl2
|
|
push dx
|
|
call newclipdown
|
|
xchg si,di
|
|
pop dx
|
|
@@cl2: ;
|
|
test dl,VF_LEFT
|
|
jz @@cl3
|
|
cmp word ptr ds:[si+POLYSIDES],0
|
|
je @@cl3
|
|
push dx
|
|
call newclipleft
|
|
xchg si,di
|
|
pop dx
|
|
@@cl3: ;
|
|
test dl,VF_RIGHT
|
|
jz @@cl4
|
|
cmp word ptr ds:[si+POLYSIDES],0
|
|
je @@cl4
|
|
push dx
|
|
call newclipright
|
|
xchg si,di
|
|
pop dx
|
|
;
|
|
@@cl4: ret
|
|
@@cl7: ;polygon marked invisible:
|
|
mov word ptr ds:[si+POLYSIDES],0
|
|
ret
|
|
newclip ENDP
|
|
|