608 lines
No EOL
12 KiB
NASM
608 lines
No EOL
12 KiB
NASM
;/****************************************************************************
|
||
;** MODULE: adraw.asm
|
||
;** AUTHOR: Sami Tammilehto / Fennosoftec OY
|
||
;** DOCUMENT: ?
|
||
;** VERSION: 1.0
|
||
;** REFERENCE: -
|
||
;** REVISED BY: -
|
||
;*****************************************************************************
|
||
;**
|
||
;** Object drawing (and polygon calculations & clipping (included))
|
||
;**
|
||
;****************************************************************************/
|
||
|
||
include a.inc
|
||
|
||
asm_code SEGMENT para public use16 'CODE'
|
||
ASSUME cs:asm_code
|
||
|
||
ALIGN 2
|
||
newlight dw 12118,10603,3030
|
||
|
||
;entry: AX=polyflags,ES:DI=normal for which to calculate light
|
||
; exit: AX=colorshade (based 0)
|
||
calclight PROC NEAR
|
||
and ax,F_SHADE32 ;=F_SHADE* orred together)
|
||
jz @@nc
|
||
;lightsource
|
||
push ax
|
||
call normallight
|
||
pop dx
|
||
shr dx,10
|
||
mov cx,6
|
||
sub cx,dx
|
||
shr ax,cl ;0400=5, 0800=4, 0C00=3
|
||
@@mm: cmp ax,1
|
||
jg @@m1
|
||
mov ax,1
|
||
@@m1: cmp ax,30
|
||
jl @@m2
|
||
mov ax,30
|
||
@@m2: ret
|
||
@@nc: xor ax,ax
|
||
jmp @@mm
|
||
calclight ENDP
|
||
|
||
normallight PROC NEAR
|
||
;return: ax=relative brightness 0..255
|
||
push bp
|
||
mov ax,es:[di+nlist_x]
|
||
imul cs:newlight[0]
|
||
mov bp,ax
|
||
mov cx,dx
|
||
mov ax,es:[di+nlist_y]
|
||
imul cs:newlight[2]
|
||
add bp,ax
|
||
adc cx,dx
|
||
mov ax,es:[di+nlist_z]
|
||
imul cs:newlight[4]
|
||
add ax,bp
|
||
adc dx,cx
|
||
mov ax,dx
|
||
sar ax,2*unitshr-7-16
|
||
add ax,128
|
||
cmp ax,255
|
||
jle @@1
|
||
mov ax,255
|
||
@@1: cmp ax,0
|
||
jge @@2
|
||
mov ax,0
|
||
@@2: pop bp
|
||
ret ;ax=0..255
|
||
normallight ENDP
|
||
|
||
checkculling PROC NEAR
|
||
;es:di=normal
|
||
;fs:si=vertex
|
||
;ret: carry=1=hidden
|
||
push bp
|
||
movsx eax,word ptr es:[di+nlist_x]
|
||
imul dword ptr fs:[si+vlist_x]
|
||
mov ebp,eax
|
||
mov ecx,edx
|
||
movsx eax,word ptr es:[di+nlist_y]
|
||
imul dword ptr fs:[si+vlist_y]
|
||
add ebp,eax
|
||
adc ecx,edx
|
||
movsx eax,word ptr es:[di+nlist_z]
|
||
imul dword ptr fs:[si+vlist_z]
|
||
add ebp,eax
|
||
adc ecx,edx
|
||
rcl ecx,1 ;if cx<0, carry=1=visible
|
||
cmc ;now carry=1 when invisible
|
||
pop bp
|
||
ret
|
||
checkculling ENDP
|
||
|
||
ALIGN 16
|
||
poly1 LABEL WORD
|
||
db POLYSIZE dup(0)
|
||
ALIGN 16
|
||
poly2 LABEL WORD
|
||
db POLYSIZE dup(0)
|
||
|
||
include adrawclp.asm
|
||
|
||
ALIGN 16
|
||
|
||
drawfill_routine dd _vid_drawfill
|
||
drawfill_routine0 dd _vid_drawfill ;nrm ;original (=NULL)
|
||
|
||
polyomin dw 0
|
||
polyomax dw 0
|
||
polycury dw 0
|
||
polylhig dw 0
|
||
polyrhig dw 0
|
||
polyoversample16 db 0
|
||
polyoversamplea db 0
|
||
polyoversamples db 0
|
||
polyoversample db 0
|
||
|
||
POLYSIDECALC MACRO fr,to
|
||
local l1,l2
|
||
;when entering, AX should be heigth
|
||
push ax
|
||
mov word ptr es:[bp-2],07777h
|
||
movsx edx,word ptr ds:[fr+POLYX]
|
||
movzx ecx,byte ptr cs:polyoversample16 ;sets ECX hi to zero
|
||
shl edx,cl
|
||
mov dx,32768 ;NOOVERSAMPLECENTER
|
||
mov es:[bp+0],edx ;Xstart
|
||
movsx eax,word ptr ds:[to+POLYX]
|
||
shl eax,cl
|
||
mov ax,32768 ;NOOVERSAMPLECENTER
|
||
sub eax,edx
|
||
cdq
|
||
pop cx
|
||
idiv ecx
|
||
mov cl,byte ptr cs:polycury
|
||
and cl,cs:polyoversamplea
|
||
jz l1
|
||
l2: sub es:[bp+0],eax
|
||
dec cl
|
||
jnz l2
|
||
l1: mov cl,cs:polyoversample
|
||
shl eax,cl
|
||
mov es:[bp+4],eax ;Xadd
|
||
add bp,8
|
||
ENDM
|
||
|
||
poly_nrm PROC NEAR
|
||
;handles a normal polygon (preclipped one)
|
||
;polydata at DS:SI. SIDES must be >=3
|
||
;drawing orders written to ES:DI
|
||
;-------Calculate bounds for SI
|
||
mov bx,ds:[si+POLYSIDES]
|
||
shl bx,2
|
||
lea ax,[bx-4+si]
|
||
mov cs:polyomax,ax
|
||
mov cs:polyomin,si
|
||
;the SI should always be in range POLYOMIN..POLYOMAX
|
||
;-------Find uppermost vertex in polygon
|
||
push si
|
||
mov bx,si
|
||
mov dx,ds:[si+POLYY]
|
||
mov bp,dx
|
||
mov cx,ds:[si+POLYSIDES]
|
||
@@11: add si,4
|
||
dec cx
|
||
jz @@2
|
||
@@1: mov ax,ds:[si+POLYY]
|
||
cmp ax,bp
|
||
jle @@13
|
||
mov bp,ax
|
||
@@13: cmp ax,dx
|
||
jge @@11
|
||
mov dx,ax
|
||
mov bx,si
|
||
jmp @@11
|
||
@@2: mov cx,bp
|
||
;DS:BX=uppermost vertex, DX=uppermost Y, CX=lowermost Y
|
||
mov cs:polycury,dx
|
||
pop si
|
||
;-------Write the startup info to drawinfo
|
||
push cx
|
||
mov bp,di ;es:di was to drawinfo, now ES:BP is
|
||
mov ax,ds:[si+POLYCOLOR]
|
||
mov es:[bp],ax
|
||
mov cl,cs:polyoversample
|
||
mov ax,dx
|
||
sar ax,cl
|
||
mov es:[bp+2],ax
|
||
add bp,4+2
|
||
pop cx
|
||
cmp dx,cx
|
||
je @@d0 ;heigth zero, nothing to do
|
||
sub bp,2
|
||
;-------Set up SI for left edge (--), DI for right edge (++)
|
||
mov si,bx
|
||
mov di,bx
|
||
;-------Loop
|
||
@@l1: mov word ptr es:[bp],0
|
||
add bp,2
|
||
mov ax,ds:[si+POLYY]
|
||
cmp ax,cs:polycury
|
||
jne @@a2
|
||
@@a4: ;Left side reload
|
||
lea bx,[si-4] ;BX=SI--
|
||
cmp bx,cs:polyomin
|
||
jge @@a1
|
||
mov bx,cs:polyomax
|
||
@@a1: mov ax,ds:[bx+POLYY]
|
||
sub ax,ds:[si+POLYY]
|
||
jc @@d0 ;turned upwards, end of polygon
|
||
jnz @@a3
|
||
mov si,bx
|
||
jmp @@a4
|
||
@@a3: mov cs:polylhig,ax
|
||
POLYSIDECALC si,bx
|
||
mov si,bx
|
||
@@a2: ;
|
||
mov word ptr es:[bp],0
|
||
add bp,2
|
||
mov ax,ds:[di+POLYY]
|
||
cmp ax,cs:polycury
|
||
jne @@b2
|
||
@@b4: ;Right side reload
|
||
lea bx,[di+4] ;BP=DI++
|
||
cmp bx,cs:polyomax
|
||
jle @@b1
|
||
mov bx,cs:polyomin
|
||
@@b1: mov ax,ds:[bx+POLYY]
|
||
sub ax,ds:[di+POLYY]
|
||
jc @@d0 ;turned upwards, end of polygon
|
||
jnz @@b3
|
||
mov di,bx
|
||
jmp @@b4
|
||
@@b3: mov cs:polyrhig,ax
|
||
POLYSIDECALC di,bx
|
||
mov di,bx
|
||
@@b2: ;
|
||
mov ax,cs:polylhig
|
||
cmp ax,cs:polyrhig
|
||
jl @@c1
|
||
;right shorter
|
||
mov ax,cs:polyrhig
|
||
@@c1: ;AX=shorter
|
||
mov cl,cs:polyoversample
|
||
mov dx,ax
|
||
sar dx,cl
|
||
mov es:[bp],dx ;Ycount
|
||
sub cs:polylhig,ax
|
||
sub cs:polyrhig,ax
|
||
add bp,2
|
||
add cs:polycury,ax
|
||
jmp @@l1
|
||
|
||
@@d0: mov word ptr es:[bp-2],0ffffh
|
||
ret
|
||
poly_nrm ENDP
|
||
|
||
POLYSIDECALC_GRD MACRO fr,to
|
||
local l1,l2
|
||
;when entering, AX should be heigth
|
||
push ax
|
||
mov word ptr es:[bp-2],07777h
|
||
;
|
||
mov cx,ax
|
||
mov ax,word ptr ds:[to+POLYGR]
|
||
mov dx,word ptr ds:[fr+POLYGR]
|
||
mov es:[bp+0],dx ;COLORstart
|
||
sub ax,dx
|
||
cwd
|
||
idiv cx
|
||
mov es:[bp+2],ax ;COLORadd
|
||
;
|
||
movsx edx,word ptr ds:[fr+POLYX]
|
||
xor ecx,ecx
|
||
mov cl,byte ptr cs:polyoversample16
|
||
shl edx,cl
|
||
mov dx,32768 ;NOOVERSAMPLECENTER
|
||
mov es:[bp+4],edx ;Xstart
|
||
movsx eax,word ptr ds:[to+POLYX]
|
||
shl eax,cl
|
||
mov ax,32768 ;NOOVERSAMPLECENTER
|
||
sub eax,edx
|
||
cdq
|
||
pop cx
|
||
idiv ecx
|
||
mov cl,byte ptr cs:polycury
|
||
and cl,cs:polyoversamplea
|
||
jz l1
|
||
l2: sub es:[bp+0],eax
|
||
dec cl
|
||
jnz l2
|
||
l1: mov cl,cs:polyoversample
|
||
shl eax,cl
|
||
mov es:[bp+8],eax ;Xadd
|
||
add bp,12
|
||
ENDM
|
||
|
||
poly_grd PROC NEAR
|
||
;handles a gouraud polygon (preclipped one)
|
||
;polydata at DS:SI. SIDES must be >=3
|
||
;drawing orders written to ES:DI
|
||
;-------Calculate bounds for SI
|
||
mov bx,ds:[si+POLYSIDES]
|
||
shl bx,2
|
||
lea ax,[bx-4+si]
|
||
mov cs:polyomax,ax
|
||
mov cs:polyomin,si
|
||
;the SI should always be in range POLYOMIN..POLYOMAX
|
||
;-------Find uppermost vertex in polygon
|
||
push si
|
||
mov bx,si
|
||
mov dx,ds:[si+POLYY]
|
||
mov bp,dx
|
||
mov cx,ds:[si+POLYSIDES]
|
||
@@11: add si,4
|
||
dec cx
|
||
jz @@2
|
||
@@1: mov ax,ds:[si+POLYY]
|
||
cmp ax,bp
|
||
jle @@13
|
||
mov bp,ax
|
||
@@13: cmp ax,dx
|
||
jge @@11
|
||
mov dx,ax
|
||
mov bx,si
|
||
jmp @@11
|
||
@@2: mov cx,bp
|
||
;DS:BX=uppermost vertex, DX=uppermost Y, CX=lowermost Y
|
||
mov cs:polycury,dx
|
||
pop si
|
||
;-------Write the startup info to drawinfo
|
||
push cx
|
||
mov bp,di ;es:di was to drawinfo, now ES:BP is
|
||
mov ax,ds:[si+POLYCOLOR]
|
||
mov es:[bp],ax
|
||
mov cl,cs:polyoversample
|
||
mov ax,dx
|
||
sar ax,cl
|
||
mov es:[bp+2],ax
|
||
add bp,4+2
|
||
pop cx
|
||
cmp dx,cx
|
||
je @@d0 ;heigth zero, nothing to do
|
||
sub bp,2
|
||
;-------Set up SI for left edge (--), DI for right edge (++)
|
||
mov si,bx
|
||
mov di,bx
|
||
;-------Loop
|
||
@@l1: mov word ptr es:[bp],0
|
||
add bp,2
|
||
mov ax,ds:[si+POLYY]
|
||
cmp ax,cs:polycury
|
||
jne @@a2
|
||
@@a4: ;Left side reload
|
||
lea bx,[si-4] ;BX=SI--
|
||
cmp bx,cs:polyomin
|
||
jge @@a1
|
||
mov bx,cs:polyomax
|
||
@@a1: mov ax,ds:[bx+POLYY]
|
||
sub ax,ds:[si+POLYY]
|
||
jc @@d0 ;turned upwards, end of polygon
|
||
jnz @@a3
|
||
mov si,bx
|
||
jmp @@a4
|
||
@@a3: mov cs:polylhig,ax
|
||
POLYSIDECALC_GRD si,bx
|
||
mov si,bx
|
||
@@a2: ;
|
||
mov word ptr es:[bp],0
|
||
add bp,2
|
||
mov ax,ds:[di+POLYY]
|
||
cmp ax,cs:polycury
|
||
jne @@b2
|
||
@@b4: ;Right side reload
|
||
lea bx,[di+4] ;BP=DI++
|
||
cmp bx,cs:polyomax
|
||
jle @@b1
|
||
mov bx,cs:polyomin
|
||
@@b1: mov ax,ds:[bx+POLYY]
|
||
sub ax,ds:[di+POLYY]
|
||
jc @@d0 ;turned upwards, end of polygon
|
||
jnz @@b3
|
||
mov di,bx
|
||
jmp @@b4
|
||
@@b3: mov cs:polyrhig,ax
|
||
POLYSIDECALC_GRD di,bx
|
||
mov di,bx
|
||
@@b2: ;
|
||
mov ax,cs:polylhig
|
||
cmp ax,cs:polyrhig
|
||
jl @@c1
|
||
;right shorter
|
||
mov ax,cs:polyrhig
|
||
@@c1: ;AX=shorter
|
||
mov cl,cs:polyoversample
|
||
mov dx,ax
|
||
sar dx,cl
|
||
mov es:[bp],dx ;Ycount
|
||
sub cs:polylhig,ax
|
||
sub cs:polyrhig,ax
|
||
add bp,2
|
||
add cs:polycury,ax
|
||
jmp @@l1
|
||
|
||
@@d0: mov word ptr es:[bp-2],0ffffh
|
||
ret
|
||
poly_grd ENDP
|
||
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> _draw_setfillroutine(void (*fillroutine)(int *)) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
;entry: Pointer to a routine to handle polygon filling
|
||
; exit: -
|
||
;descr: The specified function will be called for each polygon drawed
|
||
; with a pointer to {NORMAL-FILL-DATA} of the polygon.
|
||
_draw_setfillroutine PROC FAR
|
||
CBEG
|
||
movpar eax,0
|
||
or ax,ax
|
||
jnz @@1
|
||
mov eax,cs:drawfill_routine0
|
||
@@1: mov dword ptr cs:drawfill_routine,eax
|
||
CEND
|
||
_draw_setfillroutine ENDP
|
||
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> _draw_polylist(polylist *l,polydata *d,vlist *v,pvlist *pv,
|
||
; nlist *n,int f) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
;entry: 0 l=pointer to a polygon list (in polylist format)
|
||
; 2 d=pointer to polygon data (to which polylist points using indices)
|
||
; 4 v=pointer to rotated 3D vertices (for 3D clipping)
|
||
; 6 pv=pointer to projected vertices (for drawing)
|
||
; 8 n=pointer to normals (for culling)
|
||
; 10 f=object flags
|
||
; exit: -
|
||
;descr: draw the contents of the polylist.
|
||
_draw_polylist PROC FAR
|
||
CBEG
|
||
movpar ax,10
|
||
test ax,1
|
||
jz @@invi ;F_VISIBLE not set
|
||
;set poly oversampling
|
||
mov ax,16
|
||
mov cx,ds:_projoversampleshr
|
||
mov cs:polyoversample,cl
|
||
sub ax,cx
|
||
mov cs:polyoversample16,al
|
||
mov al,1
|
||
shl al,cl
|
||
mov cs:polyoversamples,al
|
||
dec al
|
||
mov cs:polyoversamplea,al
|
||
;start with the actual work
|
||
movpar si,0+0
|
||
add si,4 ;skip count - sort vertex
|
||
@@1: movpar ds,0+1
|
||
push si
|
||
mov si,ds:[si]
|
||
cmp si,0
|
||
je @@0 ;end of list
|
||
movpar ax,2+0
|
||
add si,ax
|
||
movpar ds,2+1
|
||
;ds:si points to polydata/polygon we are now drawing
|
||
mov cx,ds:[si+0]
|
||
movpar ax,10
|
||
or ax,0f00h
|
||
and ax,cx
|
||
mov cs:poly1[POLYFLAGS],ax
|
||
and cx,0ffh
|
||
mov cs:poly1[POLYSIDES],cx
|
||
push si
|
||
mov ax,ds:[si+4] ;normal
|
||
mov bx,ds:[si+6] ;first point
|
||
cmp word ptr ds:[si+2],-1 ;color
|
||
je @@cull2
|
||
shl bx,vlist_sizeshl
|
||
lfspar si,4 ;rotated vertices
|
||
add si,bx
|
||
mov bx,ax ;normal
|
||
shl bx,nlist_sizeshl
|
||
lespar di,8 ;rotated normals
|
||
add di,bx
|
||
test cs:poly1[POLYFLAGS],F_2SIDE
|
||
jnz @@2side
|
||
call checkculling
|
||
pop si
|
||
jc @@cull
|
||
jmp @@nocl
|
||
@@cull2: pop si
|
||
jmp @@cull
|
||
;es:di=still normal
|
||
@@2side: pop si
|
||
@@nocl: ;lightsource
|
||
mov ax,cs:poly1[POLYFLAGS]
|
||
test ax,F_GOURAUD
|
||
jnz @@nosh
|
||
call calclight
|
||
add al,ds:[si+2]
|
||
mov byte ptr cs:poly1[POLYCOLOR],al
|
||
jmp @@yosh
|
||
@@nosh: mov al,ds:[si+2]
|
||
mov byte ptr cs:poly1[POLYCOLOR],al
|
||
@@yosh: ;
|
||
mov cx,cs:poly1[POLYSIDES]
|
||
lespar di,6 ;projected vertices
|
||
mov dx,0ff00h ;for vf calc
|
||
push bp
|
||
movpar ax,4+1
|
||
movpar bp,4+0
|
||
xchg bp,di
|
||
mov cs:poly1[POLYVXSEG],ax
|
||
;ds:bp=projected vertices
|
||
;??:di=rotated vertices
|
||
zzs=0
|
||
zzd=0
|
||
REPT MAXPOLYSIDES ;max sides in polygon
|
||
mov bx,ds:[si+6+zzs]
|
||
shl bx,pvlist_sizeshl ;==vlist_sizeshl (required) [!!]
|
||
lea ax,[bx+di]
|
||
mov word ptr cs:poly1[POLYVX+zzd],ax
|
||
add bx,bp
|
||
mov al,es:[bx+pvlist_vf]
|
||
and dh,al ;if anded!=0, out of screen
|
||
or dl,al ;if orred!=0, must clip
|
||
mov eax,es:[bx+pvlist_x]
|
||
mov dword ptr cs:poly1[POLYX+zzd],eax
|
||
dec cx
|
||
jz @@2
|
||
zzs=zzs+2
|
||
zzd=zzd+4
|
||
ENDM
|
||
@@2: pop bp
|
||
push bp
|
||
push dx
|
||
;gouraud color calcs
|
||
mov ax,cs:poly1[POLYFLAGS]
|
||
test ax,F_GOURAUD
|
||
jz @@nogr
|
||
;
|
||
mov cx,cs:poly1[POLYSIDES]
|
||
lespar di,8 ;rotated normals
|
||
mov fs,cs:poly1[POLYVXSEG]
|
||
mov bp,OFFSET poly1
|
||
@@gr1: push cx
|
||
push di
|
||
mov bx,cs:[POLYVX+bp]
|
||
mov bx,fs:[bx+vlist_normal]
|
||
shl bx,nlist_sizeshl
|
||
add di,bx
|
||
;es:di=now normal for which to calculate
|
||
mov ax,cs:poly1[POLYFLAGS]
|
||
call calclight
|
||
add al,byte ptr cs:poly1[POLYCOLOR]
|
||
shl ax,8
|
||
mov cs:[POLYGR+bp],ax
|
||
pop di
|
||
pop cx
|
||
add bp,4
|
||
loop @@gr1
|
||
@@nogr: ;
|
||
pop dx
|
||
pop bp
|
||
LOADDS
|
||
push bp
|
||
push ds
|
||
mov ax,cs
|
||
mov ds,ax
|
||
mov si,OFFSET poly1
|
||
or dh,dh ;dh=visfl anded
|
||
jnz @@cl0 ;entire polygon invisible
|
||
or dl,dl ;dl=visfl orred
|
||
jz @@cl4 ;no clipping
|
||
mov di,OFFSET poly2
|
||
mov ax,ds:[si+POLYFLAGS]
|
||
call newclip
|
||
cmp word ptr ds:[si+POLYSIDES],0
|
||
je @@cl0 ;entire polygon clipped away, nothing to draw
|
||
;
|
||
@@cl4: LOADES
|
||
mov di,OFFSET _polydrw
|
||
test word ptr ds:[si+POLYFLAGS],F_GOURAUD
|
||
jz @@ngrd
|
||
mov word ptr es:[di],1 ;gouraud fill
|
||
add di,2
|
||
call poly_grd
|
||
jmp @@pgdn
|
||
@@ngrd: mov word ptr es:[di],0 ;normal fill
|
||
add di,2
|
||
call poly_nrm
|
||
@@pgdn:
|
||
push es
|
||
push OFFSET _polydrw
|
||
call cs:drawfill_routine
|
||
add sp,4
|
||
|
||
@@cl0: pop ds
|
||
pop bp
|
||
@@cull: pop si
|
||
add si,2
|
||
jmp @@1
|
||
@@0: pop si
|
||
@@invi: CEND
|
||
_draw_polylist ENDP
|
||
|
||
asm_code ENDS
|
||
END
|
||
|