3616 lines
68 KiB
NASM
3616 lines
68 KiB
NASM
;; Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved.
|
|
;;
|
|
;; $Id: TI8_PIZ.ASM 1.2 1996/09/27 17:54:50 JOHNG Exp $
|
|
;; $Locker: $
|
|
;;
|
|
;; 8 bit Indexed mode
|
|
;;
|
|
;; Triangle scan convertion and rendering
|
|
;;
|
|
;; Perfect scan, integer vertices, Z buffered
|
|
;;
|
|
.386p
|
|
.model flat,c
|
|
|
|
include drv.inc
|
|
include 586_macs.inc
|
|
|
|
USE_RCP equ 1
|
|
|
|
if 1
|
|
SHOW_CODESIZE macro _name,_total
|
|
%out _name = _total
|
|
endm
|
|
else
|
|
SHOW_CODESIZE macro x,y
|
|
endm
|
|
endif
|
|
|
|
X equ 0
|
|
Y equ 1
|
|
Z equ 2
|
|
|
|
_X equ 0
|
|
_Y equ 4
|
|
_Z equ 8
|
|
|
|
;; Setup some macros that are used to put colour, texture and depth buffers in different
|
|
;; segments
|
|
;;
|
|
if 0
|
|
CSEG equ es:
|
|
DSEG equ
|
|
TSEG equ
|
|
SETUP_SEGS macro
|
|
push es
|
|
mov es,word ptr work.colour.base+4
|
|
endm
|
|
RESTORE_SEGS macro
|
|
pop es
|
|
endm
|
|
else
|
|
CSEG equ
|
|
DSEG equ
|
|
TSEG equ
|
|
SETUP_SEGS macro
|
|
endm
|
|
RESTORE_SEGS macro
|
|
endm
|
|
endif
|
|
|
|
|
|
;; Various macros for generating the triangle renderers
|
|
;;
|
|
|
|
; Divide edx:eax by g_divisor with no overflow
|
|
;
|
|
; Assumes Z flag has sign of numerator
|
|
;
|
|
; Trashes ebx
|
|
;
|
|
;
|
|
GDIVIDE macro dirn
|
|
local negative,done,overflow
|
|
|
|
mov ebx,g_divisor
|
|
js negative
|
|
cmp ebx,edx
|
|
jbe overflow
|
|
div ebx
|
|
ifidni <dirn>,<b>
|
|
neg eax
|
|
endif
|
|
jmp done
|
|
|
|
negative: neg edx
|
|
neg eax
|
|
sbb edx,0
|
|
cmp ebx,edx
|
|
jbe overflow
|
|
div ebx
|
|
ifidni <dirn>,<f>
|
|
neg eax
|
|
endif
|
|
overflow:
|
|
done:
|
|
endm
|
|
|
|
; Comparison that change sense with rendering direction
|
|
;
|
|
CMP_f macro a,b
|
|
cmp a,b
|
|
endm
|
|
|
|
CMP_b macro a,b
|
|
cmp b,a
|
|
endm
|
|
|
|
; Equates for the vertex coordinates
|
|
;
|
|
if SCREEN_FIXED
|
|
V0_X equ <vertex_0[_X]>
|
|
V0_Y equ <vertex_0[_Y]>
|
|
V1_X equ <vertex_1[_X]>
|
|
V1_Y equ <vertex_1[_Y]>
|
|
V2_X equ <vertex_2[_X]>
|
|
V2_Y equ <vertex_2[_Y]>
|
|
else
|
|
V0_X equ <[esi].brp_vertex.comp[C_SX*4]>
|
|
V0_Y equ <[esi].brp_vertex.comp[C_SY*4]>
|
|
V1_X equ <[edi].brp_vertex.comp[C_SX*4]>
|
|
V1_Y equ <[edi].brp_vertex.comp[C_SY*4]>
|
|
V2_X equ <[ebp].brp_vertex.comp[C_SX*4]>
|
|
V2_Y equ <[ebp].brp_vertex.comp[C_SY*4]>
|
|
endif
|
|
|
|
; Setup of an integer, perfect scan triangle
|
|
;
|
|
; Leave g_divisor in eax, with sign of g_divisor in flags
|
|
;
|
|
SETUP_PI macro
|
|
|
|
_setup_start = $
|
|
|
|
; Get Y components of vertices
|
|
;
|
|
mov eax,[esi].brp_vertex.comp[C_SY*4]
|
|
mov ebx,[edi].brp_vertex.comp[C_SY*4]
|
|
mov ecx,[ebp].brp_vertex.comp[C_SY*4]
|
|
|
|
; Sort pointers and values in order of y value
|
|
;
|
|
cmp eax,ebx
|
|
jg short sort_3
|
|
cmp ebx,ecx
|
|
jle short sort_done
|
|
; abc
|
|
cmp eax,ecx
|
|
jg short sort_2
|
|
; acb
|
|
SWAP edi,ebp
|
|
jmp short sort_done
|
|
sort_2:
|
|
; cab
|
|
SWAP edi,ebp
|
|
SWAP esi,edi
|
|
jmp short sort_done
|
|
sort_3:
|
|
cmp ecx,ebx
|
|
jg short sort_4
|
|
; cba
|
|
SWAP esi,ebp
|
|
jmp short sort_done
|
|
|
|
sort_4: cmp eax,ecx
|
|
jg short sort_5
|
|
; bac
|
|
SWAP esi,edi
|
|
jmp short sort_done
|
|
sort_5:
|
|
; bca
|
|
SWAP esi,edi
|
|
SWAP edi,ebp
|
|
sort_done:
|
|
|
|
if SCREEN_FIXED
|
|
; Work out integer vertex values
|
|
;
|
|
; XXX Should really do this at projection time
|
|
;
|
|
mov eax,[esi].brp_vertex.comp[C_SX*4]
|
|
mov ebx,[edi].brp_vertex.comp[C_SX*4]
|
|
mov ecx,[ebp].brp_vertex.comp[C_SX*4]
|
|
sar eax,16
|
|
sar ebx,16
|
|
sar ecx,16
|
|
mov vertex_0[_X],eax
|
|
mov vertex_1[_X],ebx
|
|
mov vertex_2[_X],ecx
|
|
|
|
mov eax,[esi].brp_vertex.comp[C_SY*4]
|
|
mov ebx,[edi].brp_vertex.comp[C_SY*4]
|
|
mov ecx,[ebp].brp_vertex.comp[C_SY*4]
|
|
sar eax,16
|
|
sar ebx,16
|
|
sar ecx,16
|
|
mov vertex_0[_Y],eax
|
|
mov vertex_1[_Y],ebx
|
|
mov vertex_2[_Y],ecx
|
|
endif
|
|
|
|
; Work out deltas and gradients along edges
|
|
;
|
|
|
|
; long edge
|
|
;
|
|
mov ebx,V2_Y ; work.main.y
|
|
sub ebx,V0_Y
|
|
je quit ; Ignore zero height polys
|
|
mov work.main.y,ebx
|
|
|
|
if USE_RCP
|
|
mov eax,V2_X ; work.main.x
|
|
sub eax,V0_X
|
|
mov work.main.x,eax
|
|
; work.main.grad = work.main.x/work.main.y
|
|
imul _reciprocal[ebx*4]
|
|
else
|
|
mov edx,V2_X ; work.main.x
|
|
sub edx,V0_X
|
|
mov work.main.x,edx
|
|
|
|
FIX_DIV
|
|
idiv ebx
|
|
endif
|
|
mov work.main.grad,eax
|
|
mov word ptr work.main.d_f+2,ax
|
|
sar eax,16
|
|
add eax,work.colour.stride_b
|
|
mov work.main.d_i,eax
|
|
|
|
; top short edge
|
|
;
|
|
if USE_RCP
|
|
mov eax,V1_X ; work.top.x
|
|
sub eax,V0_X
|
|
mov work.top.x,eax
|
|
|
|
mov ebx,V1_Y ; work.top.y
|
|
sub ebx,V0_Y
|
|
mov work.top.y,ebx
|
|
mov work.top.count,ebx
|
|
je short no_top
|
|
|
|
imul _reciprocal[ebx*4]
|
|
else
|
|
mov edx,V1_X ; work.top.x
|
|
sub edx,V0_X
|
|
mov work.top.x,edx
|
|
|
|
mov ebx,V1_Y ; work.top.y
|
|
sub ebx,V0_Y
|
|
mov work.top.y,ebx
|
|
mov work.top.count,ebx
|
|
je short no_top
|
|
|
|
FIX_DIV ; work.top.grad = work.top.x/work.top.y
|
|
idiv ebx
|
|
endif
|
|
|
|
mov work.top.grad,eax
|
|
mov word ptr work.top.d_f+2,ax
|
|
sar eax,16
|
|
add eax,work.colour.stride_b
|
|
mov work.top.d_i,eax
|
|
no_top:
|
|
; bottom short edge (don't need to save deltas)
|
|
;
|
|
mov ebx,V2_Y ; work.bot.y
|
|
sub ebx,V1_Y
|
|
mov work.bot.count,ebx
|
|
je short no_bottom
|
|
|
|
if USE_RCP
|
|
mov eax,V2_X ; work.bot.x
|
|
sub eax,V1_X
|
|
|
|
imul _reciprocal[ebx*4]
|
|
else
|
|
mov edx,V2_X ; work.bot.x
|
|
sub edx,V1_X
|
|
|
|
FIX_DIV ; work.bot.grad = work.bot.x/work.bot.y
|
|
idiv ebx
|
|
endif
|
|
|
|
mov work.bot.grad,eax
|
|
mov word ptr work.bot.d_f+2,ax
|
|
sar eax,16
|
|
add eax,work.colour.stride_b
|
|
mov work.bot.d_i,eax
|
|
|
|
no_bottom:
|
|
|
|
; Work out start values for edges as pixel offsets
|
|
;
|
|
if 1
|
|
mov ebx,work.colour.stride_b
|
|
mov ecx,dword ptr work.colour.base
|
|
|
|
mov eax,V0_Y
|
|
imul ebx
|
|
add eax,V0_X
|
|
|
|
mov work.main.f,080000000h
|
|
mov work.main.i,eax
|
|
add eax,ecx
|
|
mov work.top.f,080000000h
|
|
mov work.top.i,eax
|
|
|
|
mov eax,V1_Y
|
|
imul ebx
|
|
add eax,V1_X
|
|
else
|
|
lea ebx,work.row_table
|
|
mov ecx,dword ptr work.colour.base
|
|
|
|
mov eax,V0_Y
|
|
mov eax,[ebx+eax*4]
|
|
add eax,V0_X
|
|
|
|
mov work.main.f,080000000h
|
|
mov work.main.i,eax
|
|
add eax,ecx
|
|
mov work.top.f,080000000h
|
|
mov work.top.i,eax
|
|
|
|
mov eax,V1_Y
|
|
mov eax,[ebx+eax*4]
|
|
add eax,V1_X
|
|
endif
|
|
|
|
add eax,ecx
|
|
mov work.bot.f,080000000h
|
|
mov work.bot.i,eax
|
|
|
|
; Work out divisor for use in parameter gradient calcs.
|
|
;
|
|
mov eax,work.main.x
|
|
imul work.top.y
|
|
mov ebx,eax
|
|
mov eax,work.top.x
|
|
imul work.main.y
|
|
sub eax,ebx
|
|
|
|
je quit ; quit if g_divisor is 0
|
|
|
|
; Leave g_divisor in eax
|
|
endm
|
|
|
|
; Per parameter initialisation of perfect scan, integer vertex triangle
|
|
;
|
|
PARAM_PI_DIRN macro vparam,param,dirn
|
|
|
|
; d_p_x = (d_p_1.work.main.y - d_p_2.work.top.y)/g_denom
|
|
;
|
|
mov eax,[ebp].brp_vertex.vparam ; d_p_2
|
|
sub eax,[esi].brp_vertex.vparam
|
|
push eax
|
|
imul work.top.y
|
|
mov ebx,eax
|
|
mov ecx,edx
|
|
|
|
mov eax,[edi].brp_vertex.vparam ; d_p_1
|
|
sub eax,[esi].brp_vertex.vparam
|
|
push eax
|
|
imul work.main.y
|
|
sub eax,ebx
|
|
sbb edx,ecx
|
|
|
|
GDIVIDE dirn
|
|
|
|
mov param.grad_x,eax
|
|
|
|
; d_p_y = (d_p_2.work.top.x - d_p_1.work.main.x)/g_denom
|
|
;
|
|
pop eax ; d_p_1
|
|
imul work.main.x
|
|
mov ebx,eax
|
|
mov ecx,edx
|
|
pop eax ; d_p_2
|
|
imul work.top.x
|
|
sub eax,ebx
|
|
sbb edx,ecx
|
|
|
|
GDIVIDE dirn
|
|
|
|
mov param.grad_y,eax
|
|
|
|
; Initialise parameter from top vertex
|
|
;
|
|
mov eax,[esi].brp_vertex.vparam
|
|
|
|
mov ebx,param.grad_x
|
|
sar ebx,1
|
|
adc eax,ebx
|
|
|
|
mov param.current,eax
|
|
|
|
; Work out parameter increments per scanline
|
|
;
|
|
movsx eax,word ptr work.main.grad+2
|
|
imul param.grad_x
|
|
add eax,param.grad_y
|
|
mov param.d_nocarry,eax
|
|
add eax,param.grad_x
|
|
mov param.d_carry,eax
|
|
endm
|
|
|
|
.data
|
|
db '$Id: TI8_PIZ.ASM 1.2 1996/09/27 17:54:50 JOHNG Exp $',0
|
|
align 4
|
|
|
|
; reciprocal table from fixed386.asm
|
|
;
|
|
extern _reciprocal:dword
|
|
|
|
p0_offset_x dd 0 ; Offset of start pixel centre from vertex 0
|
|
p0_offset_y dd 0
|
|
|
|
temp_i dd 0
|
|
temp_u dd 0
|
|
temp_v dd 0
|
|
temp_r dd 0
|
|
temp_g dd 0
|
|
temp_b dd 0
|
|
temp_y dd 0
|
|
|
|
; Integer vertex poitisions
|
|
;
|
|
vertex_0 dd 2 dup(?)
|
|
vertex_1 dd 2 dup(?)
|
|
vertex_2 dd 2 dup(?)
|
|
|
|
g_divisor dd 0 ; Bottom of param. gradient calc.
|
|
|
|
.code
|
|
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
; void TriangleRenderPIZ2(struct br_vertex *pvertex_0,
|
|
; struct br_vertex *pvertex_1,
|
|
; struct br_vertex *pvertex_2);
|
|
;
|
|
; C stub directly to triangle renderer
|
|
;
|
|
|
|
TriangleRenderPIZ2 proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2 endp
|
|
|
|
|
|
; Trapezoid loop for flat shaded z (16 bit) buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2 macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop:
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; bl: colour
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
sub edx,ebp ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax, DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
add edx,ebp ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
CMP_&dirn esi,ecx
|
|
jb short pixel_loop
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
dec work.half.count
|
|
jne short scan_loop
|
|
jmp short done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
; Triangle_PIZ2
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Flat colour
|
|
; Z buffer
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2 proc
|
|
; Extract constant components
|
|
;
|
|
mov eax,[esi].brp_vertex.comp[C_I*4]
|
|
mov work.pi.current,eax
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
; Scan forwards
|
|
;
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
mov bl,byte ptr work.pi.current+2
|
|
|
|
TRAPEZOID_PIZ2 top,f
|
|
TRAPEZOID_PIZ2 bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
mov bl,byte ptr work.pi.current+2
|
|
|
|
TRAPEZOID_PIZ2 top,b
|
|
TRAPEZOID_PIZ2 bot,b
|
|
ret
|
|
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2>,<%($-_setup_start)>
|
|
|
|
RawTriangle_PIZ2 endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
; void TriangleRenderPIZ2I(struct br_vertex *pvertex_0,
|
|
; struct br_vertex *pvertex_1,
|
|
; struct br_vertex *pvertex_2);
|
|
;
|
|
; C stub directly to triangle renderer
|
|
;
|
|
|
|
|
|
TriangleRenderPIZ2I proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2I
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2I endp
|
|
|
|
; Trapezoid loop for gouraud shaded z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2I macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop:
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
mov eax,work.pi.current
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; eax: colour (16.16)
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
pixel_loop:
|
|
|
|
ifidni <dirn>,<b>
|
|
sub edx,ebp ; z += d_z_z
|
|
sub eax,work.pi.grad_x
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
mov ebx,edx
|
|
shr ebx,16
|
|
cmp bx, DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
|
|
mov DSEG [edi],bx ; *zptr = z
|
|
|
|
mov ebx,eax
|
|
shr ebx,16
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
add edx,ebp ; z += d_z_z
|
|
add eax,work.pi.grad_x
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
CMP_&dirn esi,ecx
|
|
jb short pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
mov eax,work.pi.d_nocarry
|
|
add work.pi.current,eax
|
|
|
|
dec work.half.count
|
|
jne short scan_loop
|
|
jmp short done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
mov eax,work.pi.d_carry
|
|
add work.pi.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2I
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour index
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2I proc
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2I top,f
|
|
TRAPEZOID_PIZ2I bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2I top,b
|
|
TRAPEZOID_PIZ2I bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2I>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2I endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
|
|
TriangleRenderPIZ2T proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2T
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2T endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2T macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop:
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
;; Per pixel update - backwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,ebp ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
add ebx,work.texture.base
|
|
mov bl,TSEG [ebx]
|
|
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,ebp ; z += d_z_z
|
|
inc esi ; ptr++
|
|
add edi,2 ; z_ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2T
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2T proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2T top,f
|
|
TRAPEZOID_PIZ2T bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2T top,b
|
|
TRAPEZOID_PIZ2T bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2T>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2T endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
TriangleRenderPIZ2TI proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TI
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TI endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TI macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov ebp,work.pi.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
mov temp_i,ebp
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub ebp,work.pi.grad_x
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov bl,TSEG [ebp+ebx]
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
|
|
mov bh,byte ptr temp_i+2
|
|
add ebx,work.shade_table
|
|
mov bl,[ebx]
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add ebp,work.pi.grad_x
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
no_pixels:
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_nocarry
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_carry
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TI
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated shade index
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TI proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TI top,f
|
|
TRAPEZOID_PIZ2TI bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TI top,b
|
|
TRAPEZOID_PIZ2TI bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TI>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TI endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z4
|
|
|
|
; void TriangleRenderPIZ4(struct br_vertex *pvertex_0,
|
|
; struct br_vertex *pvertex_1,
|
|
; struct br_vertex *pvertex_2);
|
|
;
|
|
; C stub directly to triangle renderer
|
|
;
|
|
TriangleRenderPIZ4 proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ4
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ4 endp
|
|
|
|
; Trapezoid loop for flat shaded z (32 bit) buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ4 macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*4]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; bl: colour
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
sub edx,ebp ; z += d_z_z
|
|
sub edi,4 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
cmp edx, DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
mov DSEG [edi],edx ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
add edx,ebp ; z += d_z_z
|
|
add edi,4 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
CMP_&dirn esi,ecx
|
|
jb short pixel_loop
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
dec work.half.count
|
|
jne short scan_loop
|
|
jmp short done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
; Triangle_PIZ4
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Flat colour
|
|
; Z buffer
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ4 proc
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
; Scan forwards
|
|
;
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
mov bl,byte ptr work.pi.current+2
|
|
|
|
TRAPEZOID_PIZ4 top,f
|
|
TRAPEZOID_PIZ4 bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
mov bl,byte ptr work.pi.current+2
|
|
|
|
TRAPEZOID_PIZ4 top,b
|
|
TRAPEZOID_PIZ4 bot,b
|
|
ret
|
|
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ4>,<%($-_setup_start)>
|
|
|
|
RawTriangle_PIZ4 endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z4
|
|
|
|
; void TriangleRenderPIZ4I(struct br_vertex *pvertex_0,
|
|
; struct br_vertex *pvertex_1,
|
|
; struct br_vertex *pvertex_2);
|
|
;
|
|
; C stub directly to triangle renderer
|
|
;
|
|
TriangleRenderPIZ4I proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ4I
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ4I endp
|
|
|
|
; Trapezoid loop for gouraud shaded z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ4I macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop:
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*4]
|
|
add esi,dword ptr work.colour.base
|
|
mov eax,work.pi.current
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; bl: colour
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
pixel_loop:
|
|
|
|
ifidni <dirn>,<b>
|
|
sub edx,ebp ; z += d_z_z
|
|
sub eax,work.pi.grad_x
|
|
sub edi,4 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
cmp edx, DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
|
|
mov DSEG [edi],edx ; *zptr = z
|
|
|
|
mov ebx,eax
|
|
shr ebx,16
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
add edx,ebp ; z += d_z_z
|
|
add eax,work.pi.grad_x
|
|
add edi,4 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
CMP_&dirn esi,ecx
|
|
jb short pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
mov eax,work.pi.d_nocarry
|
|
add work.pi.current,eax
|
|
|
|
dec work.half.count
|
|
jne short scan_loop
|
|
jmp short done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
mov eax,work.pi.d_carry
|
|
add work.pi.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ4I
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour index
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ4I proc
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ4I top,f
|
|
TRAPEZOID_PIZ4I bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ4I top,b
|
|
TRAPEZOID_PIZ4I bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ4I>,<%($-_setup_start)>
|
|
RawTriangle_PIZ4I endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z4
|
|
|
|
TriangleRenderPIZ4T proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ4T
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ4T endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ4T macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop:
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*4]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
;; Per pixel update - backwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,ebp ; z += d_z_z
|
|
sub edi,4 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
cmp edx,DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
add ebx,work.texture.base
|
|
mov bl,TSEG [ebx]
|
|
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov DSEG [edi],edx ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,ebp ; z += d_z_z
|
|
add edi,4 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ4T
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ4T proc
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ4T top,f
|
|
TRAPEZOID_PIZ4T bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ4T top,b
|
|
TRAPEZOID_PIZ4T bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ4T>,<%($-_setup_start)>
|
|
RawTriangle_PIZ4T endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z4
|
|
|
|
TriangleRenderPIZ4TI proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ4TI
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ4TI endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ4TI macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*4]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov ebp,work.pi.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
mov temp_i,ebp
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae short no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub ebp,work.pi.grad_x
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,4 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
cmp edx,DSEG [edi] ; if (z > *zptr)
|
|
jae short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov bl,TSEG [ebp+ebx]
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov DSEG [edi],edx ; *zptr = z
|
|
|
|
mov bh,byte ptr temp_i+2
|
|
add ebx,work.shade_table
|
|
mov bl,[ebx]
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
mov DSEG [edi],edx ; *zptr = z
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add ebp,work.pi.grad_x
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,4 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
no_pixels:
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_nocarry
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_carry
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ4TI
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated shade index
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ4TI proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ4TI top,f
|
|
TRAPEZOID_PIZ4TI bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ4TI top,b
|
|
TRAPEZOID_PIZ4TI bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ4TI>,<%($-_setup_start)>
|
|
RawTriangle_PIZ4TI endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_BUMP
|
|
|
|
TriangleRenderPIZ2TN proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TN
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TN endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TN macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub ebp,work.pr.grad_x
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov al,TSEG [ebp+ebx] ; Get texel
|
|
mov ebp,work.bump.base
|
|
mov bl,TSEG [ebp+ebx] ; Get normal
|
|
xor bh,bh
|
|
|
|
;; Get lighting level from normal
|
|
|
|
mov ebp,work.lighting_table
|
|
mov ah,[ebp+ebx]
|
|
|
|
;; Light texel
|
|
|
|
mov ebp,work.shade_table
|
|
mov bl,[ebp+eax]
|
|
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
no_pixels:
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov ebp,work.pr.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pr.d_nocarry
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pr.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
mov ebp,work.pg.current
|
|
mov eax,work.pb.current
|
|
add ebp,work.pg.d_nocarry
|
|
add eax,work.pb.d_nocarry
|
|
mov work.pg.current,ebp
|
|
mov work.pb.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov ebp,work.pr.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pr.d_carry
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pr.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
mov ebp,work.pg.current
|
|
mov eax,work.pb.current
|
|
add ebp,work.pg.d_carry
|
|
add eax,work.pb.d_carry
|
|
mov work.pg.current,ebp
|
|
mov work.pb.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TN
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated shade r g and b for coloured lights
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TN proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_R*4],work.pr,f
|
|
PARAM_PI_DIRN comp[C_G*4],work.pg,f
|
|
PARAM_PI_DIRN comp[C_B*4],work.pb,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TN top,f
|
|
TRAPEZOID_PIZ2TN bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_R*4],work.pr,b
|
|
PARAM_PI_DIRN comp[C_G*4],work.pg,b
|
|
PARAM_PI_DIRN comp[C_B*4],work.pb,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TN top,b
|
|
TRAPEZOID_PIZ2TN bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TN>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TN endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
TriangleRenderPIZ2TIB proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TIB
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TIB endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered faces with blending
|
|
; Note: only *reads* z buffer
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TIB macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov ebp,work.pi.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
mov temp_i,ebp
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub ebp,work.pi.grad_x
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov bl,TSEG [ebp+ebx]
|
|
|
|
if 0
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
endif
|
|
|
|
mov bh,byte ptr temp_i+2
|
|
mov eax,work.shade_table
|
|
mov bl,[eax+ebx]
|
|
mov bh, CSEG [esi]
|
|
mov eax,work.blend_table
|
|
mov bl,[eax+ebx]
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov ebp,temp_i
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add ebp,work.pi.grad_x
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_i,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
no_pixels:
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_nocarry
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov ebp,work.pi.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pi.d_carry
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pi.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TIB
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated shade index
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TIB proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TIB top,f
|
|
TRAPEZOID_PIZ2TIB bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TIB top,b
|
|
TRAPEZOID_PIZ2TIB bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TIB>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TIB endp
|
|
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
ditherspec macro i,a,b,c,d
|
|
dither&i&0 equ a*4096
|
|
dither&i&1 equ b*4096
|
|
dither&i&2 equ c*4096
|
|
dither&i&3 equ d*4096
|
|
endm
|
|
|
|
@dith macro x,y
|
|
exitm %dither&x&&y&
|
|
endm
|
|
|
|
; Specify dither pattern
|
|
|
|
ditherspec 0,13,1,4,0
|
|
ditherspec 1,8,12,9,5
|
|
ditherspec 2,10,6,7,11
|
|
ditherspec 3,3,15,14,2
|
|
|
|
TriangleRenderPIZ2TD proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TD
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TD endp
|
|
|
|
; Trapezoid loop for linear dithered texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TD macro half,dirn
|
|
local scan_loop,pixel_loop,no_pixels
|
|
local done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
ifidni <half>,<top>
|
|
mov eax,vertex_0[_Y]
|
|
else
|
|
mov eax,vertex_1[_Y]
|
|
endif
|
|
and eax,3
|
|
|
|
; Indexed jump into correct row modulo 4
|
|
|
|
jmp rowtable_PIZ2TD&half&&dirn&[eax*4]
|
|
|
|
.data
|
|
rowtable_PIZ2TD&half&&dirn& label ptr dword
|
|
dd scan_loop&half&&dirn&0
|
|
dd scan_loop&half&&dirn&1
|
|
dd scan_loop&half&&dirn&2
|
|
dd scan_loop&half&&dirn&3
|
|
|
|
.code
|
|
|
|
scan_loop:
|
|
for row,<0,1,2,3>
|
|
local pixel_loop,start_carried,no_pixels
|
|
local next_row
|
|
|
|
scan_loop&half&&dirn&&row&:
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
|
|
; Indexed jump into correct column modulo 4
|
|
|
|
mov eax,esi
|
|
and eax,3
|
|
jmp columntable_PIZ2TD&row&&half&&dirn&[eax*4]
|
|
.data
|
|
columntable_PIZ2TD&row&&half&&dirn& label ptr dword
|
|
ifidni <dirn>,<f>
|
|
dd pixel_start&half&&dirn&&row&0
|
|
dd pixel_start&half&&dirn&&row&1
|
|
dd pixel_start&half&&dirn&&row&2
|
|
dd pixel_start&half&&dirn&&row&3
|
|
else
|
|
dd pixel_start&half&&dirn&&row&0
|
|
dd pixel_start&half&&dirn&&row&3
|
|
dd pixel_start&half&&dirn&&row&2
|
|
dd pixel_start&half&&dirn&&row&1
|
|
endif
|
|
.code
|
|
|
|
for col,<0,1,2,3>
|
|
pixel_start&half&&dirn&&row&&col&:
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
ifidni <dirn>,<f>
|
|
add eax,@dith(row,col)
|
|
add ebx,@dith(row,col)
|
|
else
|
|
add eax,@dith(row,%(4-col and 3))
|
|
add ebx,@dith(row,%(4-col and 3))
|
|
endif
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
jmp pixel_loop&half&&dirn&&row&&col&
|
|
endm
|
|
|
|
pixel_loop:
|
|
for col,<0,1,2,3>
|
|
local pixel_behind
|
|
|
|
pixel_loop&half&&dirn&&row&&col&:
|
|
|
|
ifidni <dirn>,<b>
|
|
;; Per pixel update - backwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
add eax,@dith(row,%(3-col and 3))-@dith(row,%(4-col and 3))
|
|
add ebx,@dith(row,%(3-col and 3))-@dith(row,%(4-col and 3))
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
sub edx,ebp ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
add ebx,work.texture.base
|
|
mov bl,TSEG [ebx]
|
|
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Dithered increments for u and v
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
add eax,@dith(row,%(col+1 and 3))-@dith(row,col)
|
|
add ebx,@dith(row,%(col+1 and 3))-@dith(row,col)
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
add edx,ebp ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
|
|
endm ; col,<0,1,2,3>
|
|
jmp pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
je done_trapezoid
|
|
jmp next_row
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
dec work.half.count
|
|
je done_trapezoid
|
|
next_row:
|
|
endm ; row,<1,2,3,4>
|
|
|
|
jmp scan_loop
|
|
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TD
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TD proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2TD top,f
|
|
TRAPEZOID_PIZ2TD bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
mov eax,vertex_0[_Y]
|
|
mov temp_y,eax
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2TD top,b
|
|
TRAPEZOID_PIZ2TD bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TD>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TD endp
|
|
|
|
endif
|
|
|
|
|
|
; Lighting dither may be out of phase with (u,v) dithering
|
|
; ui_phase_x and ui_phase_y specify the phase difference
|
|
; in the x and y directions
|
|
|
|
ui_phase_x equ 2
|
|
ui_phase_y equ 2
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
TriangleRenderPIZ2TID proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TID
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TID endp
|
|
|
|
; Trapezoid loop for lit linear dithered-u,v texture mapped z buffered faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TID macro half,dirn
|
|
local scan_loop,pixel_loop,no_pixels
|
|
local done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
ifidni <half>,<top>
|
|
mov eax,vertex_0[_Y]
|
|
else
|
|
mov eax,vertex_1[_Y]
|
|
endif
|
|
and eax,3
|
|
|
|
; Indexed jump into correct row modulo 4
|
|
|
|
jmp rowtable_PIZ2TID&half&&dirn&[eax*4]
|
|
|
|
.data
|
|
rowtable_PIZ2TID&half&&dirn& label ptr dword
|
|
dd scan_loop&half&&dirn&0
|
|
dd scan_loop&half&&dirn&1
|
|
dd scan_loop&half&&dirn&2
|
|
dd scan_loop&half&&dirn&3
|
|
|
|
.code
|
|
|
|
scan_loop:
|
|
for row,<0,1,2,3>
|
|
local pixel_loop,start_carried,no_pixels
|
|
local next_row
|
|
|
|
scan_loop&half&&dirn&&row&:
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
|
|
; Indexed jump into correct column modulo 4
|
|
|
|
mov eax,esi
|
|
and eax,3
|
|
jmp columntable_PIZ2TID&row&&half&&dirn&[eax*4]
|
|
|
|
.data
|
|
columntable_PIZ2TID&row&&half&&dirn& label ptr dword
|
|
ifidni <dirn>,<f>
|
|
dd pixel_start&half&&dirn&&row&0
|
|
dd pixel_start&half&&dirn&&row&1
|
|
dd pixel_start&half&&dirn&&row&2
|
|
dd pixel_start&half&&dirn&&row&3
|
|
else
|
|
dd pixel_start&half&&dirn&&row&0
|
|
dd pixel_start&half&&dirn&&row&3
|
|
dd pixel_start&half&&dirn&&row&2
|
|
dd pixel_start&half&&dirn&&row&1
|
|
endif
|
|
.code
|
|
|
|
for col,<0,1,2,3>
|
|
pixel_start&half&&dirn&&row&&col&:
|
|
|
|
;; Dithered increments for u, v and index
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov ebp,work.pi.current
|
|
|
|
ifidni <dirn>,<f>
|
|
add eax,@dith(row,col)
|
|
add ebx,@dith(row,col)
|
|
add ebp,@dith(%(ui_phase_y+row and 3),%(ui_phase_x+col and 3))
|
|
else
|
|
add eax,@dith(row,%(4-col and 3))
|
|
add ebx,@dith(row,%(4-col and 3))
|
|
add ebp,@dith(%(ui_phase_y+row and 3),%(ui_phase_x+4-col and 3))
|
|
endif
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
mov temp_i,ebp
|
|
|
|
jmp pixel_loop&half&&dirn&&row&&col&
|
|
endm
|
|
|
|
pixel_loop:
|
|
for col,<0,1,2,3>
|
|
local pixel_behind
|
|
|
|
pixel_loop&half&&dirn&&row&&col&:
|
|
|
|
ifidni <dirn>,<b>
|
|
;; Dithered increments for u, v and index
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
add eax,@dith(row,%(3-col and 3))-@dith(row,%(4-col and 3))
|
|
add ebx,@dith(row,%(3-col and 3))-@dith(row,%(4-col and 3))
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
mov ebp,temp_i
|
|
sub ebp,work.pi.grad_x
|
|
add ebp,@dith(%(ui_phase_y+row and 3),%(ui_phase_x+3-col and 3))-@dith(%(ui_phase_y+row and 3),%(ui_phase_x+4-col and 3))
|
|
mov temp_i,ebp
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov bl,TSEG [ebp+ebx]
|
|
|
|
and bl,bl ; Check for transparency
|
|
je pixel_behind
|
|
|
|
mov bh,byte ptr temp_i+2
|
|
add ebx,work.shade_table
|
|
mov bl,[ebx]
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
add eax,@dith(row,%(col+1 and 3))-@dith(row,col)
|
|
add ebx,@dith(row,%(col+1 and 3))-@dith(row,col)
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
mov ebp,temp_i
|
|
add ebp,work.pi.grad_x
|
|
add ebp,@dith(%(ui_phase_y+row and 3),%(ui_phase_x+col+1 and 3))-@dith(%(ui_phase_y+row and 3),%(ui_phase_x+col and 3))
|
|
mov temp_i,ebp
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
|
|
endm ; col,<0,1,2,3>
|
|
jmp pixel_loop
|
|
|
|
no_pixels:
|
|
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
mov ebp,work.pi.current
|
|
add ebp,work.pi.d_nocarry
|
|
mov work.pi.current,ebp
|
|
|
|
dec work.half.count
|
|
je done_trapezoid
|
|
jmp next_row
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
mov ebp,work.pi.current
|
|
add ebp,work.pi.d_carry
|
|
mov work.pi.current,ebp
|
|
|
|
dec work.half.count
|
|
je done_trapezoid
|
|
next_row:
|
|
endm ; row,<1,2,3,4>
|
|
|
|
jmp scan_loop
|
|
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TID
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TID proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2TID top,f
|
|
TRAPEZOID_PIZ2TID bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
PARAM_PI_DIRN comp[C_I*4],work.pi,b
|
|
|
|
mov eax,vertex_0[_Y]
|
|
mov temp_y,eax
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
mov ebp,work.pz.grad_x
|
|
|
|
TRAPEZOID_PIZ2TID top,b
|
|
TRAPEZOID_PIZ2TID bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TID>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TID endp
|
|
|
|
endif
|
|
|
|
if PARTS and PART_8Z
|
|
|
|
TriangleRenderPIZ2TIC proc uses eax ebx ecx edx esi edi,
|
|
pblock : ptr dword,
|
|
pvertex_0 : ptr word,
|
|
pvertex_1 : ptr word,
|
|
pvertex_2 : ptr word
|
|
|
|
; Get pointers to vertex structures and colour
|
|
;
|
|
; eax = colour
|
|
; esi = vertex 0
|
|
; edi = vertex 1
|
|
; ebp = vertex 2
|
|
;
|
|
push ebp
|
|
SETUP_SEGS
|
|
|
|
mov esi,pvertex_0
|
|
mov edi,pvertex_1
|
|
mov ebp,pvertex_2
|
|
call RawTriangle_PIZ2TIC
|
|
|
|
RESTORE_SEGS
|
|
pop ebp
|
|
ret
|
|
TriangleRenderPIZ2TIC endp
|
|
|
|
; Trapezoid loop for linear texture mapped z buffered RGB lit faces
|
|
;
|
|
; Arguments control:
|
|
; whether loop uses 'top' or 'bottom' variables
|
|
; which direction scanline are rendered from the long edge
|
|
;
|
|
TRAPEZOID_PIZ2TIC macro half,dirn
|
|
local scan_loop,pixel_loop,pixel_behind,no_pixels
|
|
local start_carried,done_trapezoid
|
|
|
|
cmp work.half.count,0
|
|
je done_trapezoid
|
|
|
|
mov ecx,work.half.i
|
|
|
|
; Prepare for next iteration of loop
|
|
;
|
|
scan_loop: push esi
|
|
push edx
|
|
|
|
mov edi,work.depth.base
|
|
lea edi,[edi+esi*2]
|
|
add esi,dword ptr work.colour.base
|
|
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
mov ebp,work.pr.current
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
mov temp_r,ebp
|
|
|
|
mov eax,work.pg.current
|
|
mov ebx,work.pb.current
|
|
mov temp_g,eax
|
|
mov temp_b,ebx
|
|
|
|
; Render same colour pixels along scanline (forwards or backwards)
|
|
;
|
|
; ecx: address of end of scanline
|
|
; edx: z (16.16)
|
|
; ebp: z delta (16.16)
|
|
; esi: frame buffer ptr
|
|
; edi: z buffer ptr
|
|
;
|
|
CMP_&dirn esi,ecx
|
|
jae no_pixels
|
|
pixel_loop:
|
|
ifidni <dirn>,<b>
|
|
mov ebp,temp_r
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
sub ebp,work.pr.grad_x
|
|
sub eax,work.pu.grad_x
|
|
sub ebx,work.pv.grad_x
|
|
mov temp_r,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
mov ebp,temp_g
|
|
mov eax,temp_b
|
|
sub ebp,work.pg.grad_x
|
|
sub eax,work.pb.grad_x
|
|
mov temp_g,ebp
|
|
mov temp_b,eax
|
|
|
|
sub edx,work.pz.grad_x ; z += d_z_z
|
|
sub edi,2 ; z_ptr++
|
|
dec esi ; ptr++
|
|
endif
|
|
|
|
;; Depth test
|
|
;;
|
|
mov eax,edx
|
|
shr eax,16
|
|
cmp ax,DSEG [edi] ; if (z > *zptr)
|
|
ja short pixel_behind
|
|
|
|
;; Per pixel fetch colour
|
|
;;
|
|
mov DSEG [edi],ax ; *zptr = z
|
|
xor ebx,ebx
|
|
mov bl,byte ptr temp_u+2
|
|
mov bh,byte ptr temp_v+2
|
|
mov ebp,work.texture.base
|
|
mov bl,TSEG [ebp+ebx] ; Get texel
|
|
|
|
if 1 ; DELETE ME!!!!
|
|
|
|
;; Light texel
|
|
|
|
mov ebp,work.shade_table
|
|
|
|
;; Light red component
|
|
|
|
mov bh,byte ptr temp_r+2
|
|
mov bl,2[ebp+4*ebx]
|
|
|
|
;; Light green component
|
|
|
|
mov bh,byte ptr temp_g+2
|
|
mov bl,1[ebp+4*ebx]
|
|
|
|
;; Light blue component
|
|
|
|
mov bh,byte ptr temp_b+2
|
|
mov bl,[ebp+4*ebx]
|
|
endif
|
|
|
|
mov CSEG [esi],bl ; *ptr = colour
|
|
|
|
pixel_behind:
|
|
|
|
ifidni <dirn>,<f>
|
|
;; Per pixel update - forwards
|
|
;;
|
|
mov ebp,temp_r
|
|
mov eax,temp_u
|
|
mov ebx,temp_v
|
|
add ebp,work.pr.grad_x
|
|
add eax,work.pu.grad_x
|
|
add ebx,work.pv.grad_x
|
|
mov temp_r,ebp
|
|
mov temp_u,eax
|
|
mov temp_v,ebx
|
|
|
|
mov ebp,temp_g
|
|
mov eax,temp_b
|
|
add ebp,work.pg.grad_x
|
|
add eax,work.pb.grad_x
|
|
mov temp_g,ebp
|
|
mov temp_b,eax
|
|
|
|
add edx,work.pz.grad_x ; z += d_z_z
|
|
add edi,2 ; z_ptr++
|
|
inc esi ; ptr++
|
|
endif
|
|
|
|
CMP_&dirn esi,ecx
|
|
jb pixel_loop
|
|
no_pixels:
|
|
; Updates for next scanline:
|
|
;
|
|
pop edx
|
|
pop esi
|
|
mov edi,work.half.d_f
|
|
mov eax,work.main.d_f
|
|
add work.half.f,edi ; x_end += work.main.grad_end (fraction)
|
|
adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY
|
|
|
|
add work.main.f,eax ; x+= work.main.grad (fraction)
|
|
jc start_carried
|
|
|
|
add esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_nocarry
|
|
|
|
;; Per scanline parameter update - no carry
|
|
;;
|
|
mov ebp,work.pr.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pr.d_nocarry
|
|
add eax,work.pu.d_nocarry
|
|
add ebx,work.pv.d_nocarry
|
|
mov work.pr.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
mov ebp,work.pg.current
|
|
mov eax,work.pb.current
|
|
add ebp,work.pg.d_nocarry
|
|
add eax,work.pb.d_nocarry
|
|
mov work.pg.current,ebp
|
|
mov work.pb.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
jmp done_trapezoid
|
|
|
|
start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY
|
|
add edx,work.pz.d_carry
|
|
|
|
;; Per scanline parameter update - carry
|
|
;;
|
|
mov ebp,work.pr.current
|
|
mov eax,work.pu.current
|
|
mov ebx,work.pv.current
|
|
add ebp,work.pr.d_carry
|
|
add eax,work.pu.d_carry
|
|
add ebx,work.pv.d_carry
|
|
mov work.pr.current,ebp
|
|
mov work.pu.current,eax
|
|
mov work.pv.current,ebx
|
|
|
|
mov ebp,work.pg.current
|
|
mov eax,work.pb.current
|
|
add ebp,work.pg.d_carry
|
|
add eax,work.pb.d_carry
|
|
mov work.pg.current,ebp
|
|
mov work.pb.current,eax
|
|
|
|
dec work.half.count
|
|
jne scan_loop
|
|
done_trapezoid:
|
|
endm
|
|
|
|
|
|
; RawTriangle_PIZ2TIC
|
|
;
|
|
; Render a triangle into frame buffer
|
|
;
|
|
; Linear interpolated colour texture
|
|
; Linear interpolated shade r g and b for coloured lights
|
|
; Linear interpolated Z value
|
|
; Integer vertices
|
|
; Perfect point sampling
|
|
;
|
|
; esi = vertex 0 pointer
|
|
; edi = vertex 1 pointer
|
|
; ebp = vertex 2 pointer
|
|
;
|
|
RawTriangle_PIZ2TIC proc
|
|
|
|
SETUP_PI
|
|
jl reversed
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,f
|
|
PARAM_PI_DIRN comp[C_R*4],work.pr,f
|
|
PARAM_PI_DIRN comp[C_G*4],work.pg,f
|
|
PARAM_PI_DIRN comp[C_B*4],work.pb,f
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,f
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,f
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TIC top,f
|
|
TRAPEZOID_PIZ2TIC bot,f
|
|
quit: ret
|
|
|
|
; Scan backwards
|
|
;
|
|
reversed:
|
|
neg eax
|
|
mov g_divisor,eax
|
|
|
|
PARAM_PI_DIRN comp[C_SZ*4],work.pz,b
|
|
PARAM_PI_DIRN comp[C_R*4],work.pr,b
|
|
PARAM_PI_DIRN comp[C_G*4],work.pg,b
|
|
PARAM_PI_DIRN comp[C_B*4],work.pb,b
|
|
PARAM_PI_DIRN comp[C_U*4],work.pu,b
|
|
PARAM_PI_DIRN comp[C_V*4],work.pv,b
|
|
|
|
; Load up registers for first time around inner loop
|
|
;
|
|
mov esi,work.main.i
|
|
mov edx,work.pz.current
|
|
|
|
TRAPEZOID_PIZ2TIC top,b
|
|
TRAPEZOID_PIZ2TIC bot,b
|
|
ret
|
|
|
|
SHOW_CODESIZE <RawTriangle_PIZ2TIC>,<%($-_setup_start)>
|
|
RawTriangle_PIZ2TIC endp
|
|
|
|
endif
|
|
|
|
end
|