You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
822 lines
19 KiB
822 lines
19 KiB
.386P |
|
.model FLAT |
|
; |
|
; r_drawa.s |
|
; x86 assembly-language edge clipping and emission code |
|
; |
|
|
|
include qasm.inc |
|
include d_if.inc |
|
|
|
if id386 |
|
|
|
; !!! if these are changed, they must be changed in r_draw.c too !!! |
|
FULLY_CLIPPED_CACHED equ 080000000h |
|
FRAMECOUNT_MASK equ 07FFFFFFFh |
|
|
|
_DATA SEGMENT |
|
|
|
Ld0 dd 0.0 |
|
Ld1 dd 0.0 |
|
Lstack dd 0 |
|
Lfp_near_clip dd NEAR_CLIP |
|
Lceilv0 dd 0 |
|
Lv dd 0 |
|
Lu0 dd 0 |
|
Lv0 dd 0 |
|
Lzi0 dd 0 |
|
|
|
_DATA ENDS |
|
_TEXT SEGMENT |
|
|
|
;---------------------------------------------------------------------- |
|
; edge clipping code |
|
;---------------------------------------------------------------------- |
|
|
|
pv0 equ 4+12 |
|
pv1 equ 8+12 |
|
clip equ 12+12 |
|
|
|
align 4 |
|
public _R_ClipEdge |
|
_R_ClipEdge: |
|
push esi ; preserve register variables |
|
push edi |
|
push ebx |
|
mov ds:dword ptr[Lstack],esp ; for clearing the stack later |
|
|
|
; float d0, d1, f; |
|
; mvertex_t clipvert; |
|
|
|
mov ebx,ds:dword ptr[clip+esp] |
|
mov esi,ds:dword ptr[pv0+esp] |
|
mov edx,ds:dword ptr[pv1+esp] |
|
|
|
; if (clip) |
|
; { |
|
test ebx,ebx |
|
jz Lemit |
|
|
|
; do |
|
; { |
|
|
|
Lcliploop: |
|
|
|
; d0 = DotProduct (pv0->position, clip->normal) - clip->dist; |
|
; d1 = DotProduct (pv1->position, clip->normal) - clip->dist; |
|
fld ds:dword ptr[mv_position+0+esi] |
|
fmul ds:dword ptr[cp_normal+0+ebx] |
|
fld ds:dword ptr[mv_position+4+esi] |
|
fmul ds:dword ptr[cp_normal+4+ebx] |
|
fld ds:dword ptr[mv_position+8+esi] |
|
fmul ds:dword ptr[cp_normal+8+ebx] |
|
fxch st(1) |
|
faddp st(2),st(0) ; d0mul2 | d0add0 |
|
|
|
fld ds:dword ptr[mv_position+0+edx] |
|
fmul ds:dword ptr[cp_normal+0+ebx] |
|
fld ds:dword ptr[mv_position+4+edx] |
|
fmul ds:dword ptr[cp_normal+4+ebx] |
|
fld ds:dword ptr[mv_position+8+edx] |
|
fmul ds:dword ptr[cp_normal+8+ebx] |
|
fxch st(1) |
|
faddp st(2),st(0) ; d1mul2 | d1add0 | d0mul2 | d0add0 |
|
fxch st(3) ; d0add0 | d1add0 | d0mul2 | d1mul2 |
|
|
|
faddp st(2),st(0) ; d1add0 | dot0 | d1mul2 |
|
faddp st(2),st(0) ; dot0 | dot1 |
|
|
|
fsub ds:dword ptr[cp_dist+ebx] ; d0 | dot1 |
|
fxch st(1) ; dot1 | d0 |
|
fsub ds:dword ptr[cp_dist+ebx] ; d1 | d0 |
|
fxch st(1) |
|
fstp ds:dword ptr[Ld0] |
|
fstp ds:dword ptr[Ld1] |
|
|
|
; if (d0 >= 0) |
|
; { |
|
mov eax,ds:dword ptr[Ld0] |
|
mov ecx,ds:dword ptr[Ld1] |
|
or ecx,eax |
|
js Lp2 |
|
|
|
; both points are unclipped |
|
|
|
Lcontinue: |
|
|
|
; |
|
; R_ClipEdge (&clipvert, pv1, clip->next); |
|
; return; |
|
; } |
|
; } while ((clip = clip->next) != NULL); |
|
mov ebx,ds:dword ptr[cp_next+ebx] |
|
test ebx,ebx |
|
jnz Lcliploop |
|
|
|
; } |
|
|
|
;// add the edge |
|
; R_EmitEdge (pv0, pv1); |
|
Lemit: |
|
|
|
; |
|
; set integer rounding to ceil mode, set to single precision |
|
; |
|
; FIXME: do away with by manually extracting integers from floats? |
|
; FIXME: set less often |
|
fldcw ds:word ptr[_fpu_ceil_cw] |
|
|
|
; edge_t *edge, *pcheck; |
|
; int u_check; |
|
; float u, u_step; |
|
; vec3_t local, transformed; |
|
; float *world; |
|
; int v, v2, ceilv0; |
|
; float scale, lzi0, u0, v0; |
|
; int side; |
|
|
|
; if (r_lastvertvalid) |
|
; { |
|
cmp ds:dword ptr[_r_lastvertvalid],0 |
|
jz LCalcFirst |
|
|
|
; u0 = r_u1; |
|
; v0 = r_v1; |
|
; lzi0 = r_lzi1; |
|
; ceilv0 = r_ceilv1; |
|
mov eax,ds:dword ptr[_r_lzi1] |
|
mov ecx,ds:dword ptr[_r_u1] |
|
mov ds:dword ptr[Lzi0],eax |
|
mov ds:dword ptr[Lu0],ecx |
|
mov ecx,ds:dword ptr[_r_v1] |
|
mov eax,ds:dword ptr[_r_ceilv1] |
|
mov ds:dword ptr[Lv0],ecx |
|
mov ds:dword ptr[Lceilv0],eax |
|
jmp LCalcSecond |
|
|
|
; } |
|
|
|
LCalcFirst: |
|
|
|
; else |
|
; { |
|
; world = &pv0->position[0]; |
|
|
|
call near ptr LTransformAndProject ; v0 | lzi0 | u0 |
|
|
|
fst ds:dword ptr[Lv0] |
|
fxch st(2) ; u0 | lzi0 | v0 |
|
fstp ds:dword ptr[Lu0] ; lzi0 | v0 |
|
fstp ds:dword ptr[Lzi0] ; v0 |
|
|
|
; ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0); |
|
fistp ds:dword ptr[Lceilv0] |
|
|
|
; } |
|
|
|
LCalcSecond: |
|
|
|
; world = &pv1->position[0]; |
|
mov esi,edx |
|
|
|
call near ptr LTransformAndProject ; v1 | lzi1 | u1 |
|
|
|
fld ds:dword ptr[Lu0] ; u0 | v1 | lzi1 | u1 |
|
fxch st(3) ; u1 | v1 | lzi1 | u0 |
|
fld ds:dword ptr[Lzi0] ; lzi0 | u1 | v1 | lzi1 | u0 |
|
fxch st(3) ; lzi1 | u1 | v1 | lzi0 | u0 |
|
fld ds:dword ptr[Lv0] ; v0 | lzi1 | u1 | v1 | lzi0 | u0 |
|
fxch st(3) ; v1 | lzi1 | u1 | v0 | lzi0 | u0 |
|
|
|
; r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1); |
|
fist ds:dword ptr[_r_ceilv1] |
|
|
|
fldcw ds:word ptr[_fpu_chop_cw] ; put back normal floating-point state |
|
|
|
fst ds:dword ptr[_r_v1] |
|
fxch st(4) ; lzi0 | lzi1 | u1 | v0 | v1 | u0 |
|
|
|
; if (r_lzi1 > lzi0) |
|
; lzi0 = r_lzi1; |
|
fcom st(1) |
|
fnstsw ax |
|
test ah,1 |
|
jz LP0 |
|
fstp st(0) |
|
fld st(0) |
|
LP0: |
|
|
|
fxch st(1) ; lzi1 | lzi0 | u1 | v0 | v1 | u0 |
|
fstp ds:dword ptr[_r_lzi1] ; lzi0 | u1 | v0 | v1 | u0 |
|
fxch st(1) |
|
fst ds:dword ptr[_r_u1] |
|
fxch st(1) |
|
|
|
; if (lzi0 > r_nearzi) // for mipmap finding |
|
; r_nearzi = lzi0; |
|
fcom ds:dword ptr[_r_nearzi] |
|
fnstsw ax |
|
test ah,045h |
|
jnz LP1 |
|
fst ds:dword ptr[_r_nearzi] |
|
LP1: |
|
|
|
; // for right edges, all we want is the effect on 1/z |
|
; if (r_nearzionly) |
|
; return; |
|
mov eax,ds:dword ptr[_r_nearzionly] |
|
test eax,eax |
|
jz LP2 |
|
LPop5AndDone: |
|
mov eax,ds:dword ptr[_cacheoffset] |
|
mov edx,ds:dword ptr[_r_framecount] |
|
cmp eax,07FFFFFFFh |
|
jz LDoPop |
|
and edx,offset FRAMECOUNT_MASK |
|
or edx,offset FULLY_CLIPPED_CACHED |
|
mov ds:dword ptr[_cacheoffset],edx |
|
|
|
LDoPop: |
|
fstp st(0) ; u1 | v0 | v1 | u0 |
|
fstp st(0) ; v0 | v1 | u0 |
|
fstp st(0) ; v1 | u0 |
|
fstp st(0) ; u0 |
|
fstp st(0) |
|
jmp Ldone |
|
|
|
LP2: |
|
|
|
; // create the edge |
|
; if (ceilv0 == r_ceilv1) |
|
; return; // horizontal edge |
|
mov ebx,ds:dword ptr[Lceilv0] |
|
mov edi,ds:dword ptr[_edge_p] |
|
mov ecx,ds:dword ptr[_r_ceilv1] |
|
mov edx,edi |
|
mov esi,ds:dword ptr[_r_pedge] |
|
add edx,offset et_size |
|
cmp ebx,ecx |
|
jz LPop5AndDone |
|
|
|
mov eax,ds:dword ptr[_r_pedge] |
|
mov ds:dword ptr[et_owner+edi],eax |
|
|
|
; side = ceilv0 > r_ceilv1; |
|
; |
|
; edge->nearzi = lzi0; |
|
fstp ds:dword ptr[et_nearzi+edi] ; u1 | v0 | v1 | u0 |
|
|
|
; if (side == 1) |
|
; { |
|
jc LSide0 |
|
|
|
LSide1: |
|
|
|
; // leading edge (go from p2 to p1) |
|
|
|
; u_step = ((u0 - r_u1) / (v0 - r_v1)); |
|
fsubp st(3),st(0) ; v0 | v1 | u0-u1 |
|
fsub st(0),st(1) ; v0-v1 | v1 | u0-u1 |
|
fdivp st(2),st(0) ; v1 | ustep |
|
|
|
; r_emitted = 1; |
|
mov ds:dword ptr[_r_emitted],1 |
|
|
|
; edge = edge_p++; |
|
mov ds:dword ptr[_edge_p],edx |
|
|
|
; pretouch next edge |
|
mov eax,ds:dword ptr[edx] |
|
|
|
; v2 = ceilv0 - 1; |
|
; v = r_ceilv1; |
|
mov eax,ecx |
|
lea ecx,ds:dword ptr[-1+ebx] |
|
mov ebx,eax |
|
|
|
; edge->surfs[0] = 0; |
|
; edge->surfs[1] = surface_p - surfaces; |
|
mov eax,ds:dword ptr[_surface_p] |
|
mov esi,ds:dword ptr[_surfaces] |
|
sub edx,edx |
|
sub eax,esi |
|
shr eax,offset SURF_T_SHIFT |
|
mov ds:dword ptr[et_surfs+edi],edx |
|
mov ds:dword ptr[et_surfs+2+edi],eax |
|
|
|
sub esi,esi |
|
|
|
; u = r_u1 + ((float)v - r_v1) * u_step; |
|
mov ds:dword ptr[Lv],ebx |
|
fild ds:dword ptr[Lv] ; v | v1 | ustep |
|
fsubrp st(1),st(0) ; v-v1 | ustep |
|
fmul st(0),st(1) ; (v-v1)*ustep | ustep |
|
fadd ds:dword ptr[_r_u1] ; u | ustep |
|
|
|
jmp LSideDone |
|
|
|
; } |
|
|
|
LSide0: |
|
|
|
; else |
|
; { |
|
; // trailing edge (go from p1 to p2) |
|
|
|
; u_step = ((r_u1 - u0) / (r_v1 - v0)); |
|
fsub st(0),st(3) ; u1-u0 | v0 | v1 | u0 |
|
fxch st(2) ; v1 | v0 | u1-u0 | u0 |
|
fsub st(0),st(1) ; v1-v0 | v0 | u1-u0 | u0 |
|
fdivp st(2),st(0) ; v0 | ustep | u0 |
|
|
|
; r_emitted = 1; |
|
mov ds:dword ptr[_r_emitted],1 |
|
|
|
; edge = edge_p++; |
|
mov ds:dword ptr[_edge_p],edx |
|
|
|
; pretouch next edge |
|
mov eax,ds:dword ptr[edx] |
|
|
|
; v = ceilv0; |
|
; v2 = r_ceilv1 - 1; |
|
dec ecx |
|
|
|
; edge->surfs[0] = surface_p - surfaces; |
|
; edge->surfs[1] = 0; |
|
mov eax,ds:dword ptr[_surface_p] |
|
mov esi,ds:dword ptr[_surfaces] |
|
sub edx,edx |
|
sub eax,esi |
|
shr eax,offset SURF_T_SHIFT |
|
mov ds:dword ptr[et_surfs+2+edi],edx |
|
mov ds:dword ptr[et_surfs+edi],eax |
|
|
|
mov esi,1 |
|
|
|
; u = u0 + ((float)v - v0) * u_step; |
|
mov ds:dword ptr[Lv],ebx |
|
fild ds:dword ptr[Lv] ; v | v0 | ustep | u0 |
|
fsubrp st(1),st(0) ; v-v0 | ustep | u0 |
|
fmul st(0),st(1) ; (v-v0)*ustep | ustep | u0 |
|
faddp st(2),st(0) ; ustep | u |
|
fxch st(1) ; u | ustep |
|
|
|
; } |
|
|
|
LSideDone: |
|
|
|
; edge->u_step = u_step*0x100000; |
|
; edge->u = u*0x100000 + 0xFFFFF; |
|
|
|
fmul ds:dword ptr[fp_1m] ; u*0x100000 | ustep |
|
fxch st(1) ; ustep | u*0x100000 |
|
fmul ds:dword ptr[fp_1m] ; ustep*0x100000 | u*0x100000 |
|
fxch st(1) ; u*0x100000 | ustep*0x100000 |
|
fadd ds:dword ptr[fp_1m_minus_1] ; u*0x100000 + 0xFFFFF | ustep*0x100000 |
|
fxch st(1) ; ustep*0x100000 | u*0x100000 + 0xFFFFF |
|
fistp ds:dword ptr[et_u_step+edi] ; u*0x100000 + 0xFFFFF |
|
fistp ds:dword ptr[et_u+edi] |
|
|
|
; // we need to do this to avoid stepping off the edges if a very nearly |
|
; // horizontal edge is less than epsilon above a scan, and numeric error |
|
; // causes it to incorrectly extend to the scan, and the extension of the |
|
; // line goes off the edge of the screen |
|
; // FIXME: is this actually needed? |
|
; if (edge->u < r_refdef.vrect_x_adj_shift20) |
|
; edge->u = r_refdef.vrect_x_adj_shift20; |
|
; if (edge->u > r_refdef.vrectright_adj_shift20) |
|
; edge->u = r_refdef.vrectright_adj_shift20; |
|
mov eax,ds:dword ptr[et_u+edi] |
|
mov edx,ds:dword ptr[_r_refdef+rd_vrect_x_adj_shift20] |
|
cmp eax,edx |
|
jl LP4 |
|
mov edx,ds:dword ptr[_r_refdef+rd_vrectright_adj_shift20] |
|
cmp eax,edx |
|
jng LP5 |
|
LP4: |
|
mov ds:dword ptr[et_u+edi],edx |
|
mov eax,edx |
|
LP5: |
|
|
|
; // sort the edge in normally |
|
; u_check = edge->u; |
|
; |
|
; if (edge->surfs[0]) |
|
; u_check++; // sort trailers after leaders |
|
add eax,esi |
|
|
|
; if (!newedges[v] || newedges[v]->u >= u_check) |
|
; { |
|
mov esi,ds:dword ptr[_newedges+ebx*4] |
|
test esi,esi |
|
jz LDoFirst |
|
cmp ds:dword ptr[et_u+esi],eax |
|
jl LNotFirst |
|
LDoFirst: |
|
|
|
; edge->next = newedges[v]; |
|
; newedges[v] = edge; |
|
mov ds:dword ptr[et_next+edi],esi |
|
mov ds:dword ptr[_newedges+ebx*4],edi |
|
|
|
jmp LSetRemove |
|
|
|
; } |
|
|
|
LNotFirst: |
|
|
|
; else |
|
; { |
|
; pcheck = newedges[v]; |
|
; |
|
; while (pcheck->next && pcheck->next->u < u_check) |
|
; pcheck = pcheck->next; |
|
LFindInsertLoop: |
|
mov edx,esi |
|
mov esi,ds:dword ptr[et_next+esi] |
|
test esi,esi |
|
jz LInsertFound |
|
cmp ds:dword ptr[et_u+esi],eax |
|
jl LFindInsertLoop |
|
|
|
LInsertFound: |
|
|
|
; edge->next = pcheck->next; |
|
; pcheck->next = edge; |
|
mov ds:dword ptr[et_next+edi],esi |
|
mov ds:dword ptr[et_next+edx],edi |
|
|
|
; } |
|
|
|
LSetRemove: |
|
|
|
; edge->nextremove = removeedges[v2]; |
|
; removeedges[v2] = edge; |
|
mov eax,ds:dword ptr[_removeedges+ecx*4] |
|
mov ds:dword ptr[_removeedges+ecx*4],edi |
|
mov ds:dword ptr[et_nextremove+edi],eax |
|
|
|
Ldone: |
|
mov esp,ds:dword ptr[Lstack] ; clear temporary variables from stack |
|
|
|
pop ebx ; restore register variables |
|
pop edi |
|
pop esi |
|
ret |
|
|
|
; at least one point is clipped |
|
|
|
Lp2: |
|
test eax,eax |
|
jns Lp1 |
|
|
|
; else |
|
; { |
|
; // point 0 is clipped |
|
|
|
; if (d1 < 0) |
|
; { |
|
mov eax,ds:dword ptr[Ld1] |
|
test eax,eax |
|
jns Lp3 |
|
|
|
; // both points are clipped |
|
; // we do cache fully clipped edges |
|
; if (!leftclipped) |
|
mov eax,ds:dword ptr[_r_leftclipped] |
|
mov ecx,ds:dword ptr[_r_pedge] |
|
test eax,eax |
|
jnz Ldone |
|
|
|
; r_pedge->framecount = r_framecount; |
|
mov eax,ds:dword ptr[_r_framecount] |
|
and eax,offset FRAMECOUNT_MASK |
|
or eax,offset FULLY_CLIPPED_CACHED |
|
mov ds:dword ptr[_cacheoffset],eax |
|
|
|
; return; |
|
jmp Ldone |
|
|
|
; } |
|
|
|
Lp1: |
|
|
|
; // point 0 is unclipped |
|
; if (d1 >= 0) |
|
; { |
|
; // both points are unclipped |
|
; continue; |
|
|
|
; // only point 1 is clipped |
|
|
|
; f = d0 / (d0 - d1); |
|
fld ds:dword ptr[Ld0] |
|
fld ds:dword ptr[Ld1] |
|
fsubr st(0),st(1) |
|
|
|
; // we don't cache partially clipped edges |
|
mov ds:dword ptr[_cacheoffset],07FFFFFFFh |
|
|
|
fdivp st(1),st(0) |
|
|
|
sub esp,offset mv_size ; allocate space for clipvert |
|
|
|
; clipvert.position[0] = pv0->position[0] + |
|
; f * (pv1->position[0] - pv0->position[0]); |
|
; clipvert.position[1] = pv0->position[1] + |
|
; f * (pv1->position[1] - pv0->position[1]); |
|
; clipvert.position[2] = pv0->position[2] + |
|
; f * (pv1->position[2] - pv0->position[2]); |
|
fld ds:dword ptr[mv_position+8+edx] |
|
fsub ds:dword ptr[mv_position+8+esi] |
|
fld ds:dword ptr[mv_position+4+edx] |
|
fsub ds:dword ptr[mv_position+4+esi] |
|
fld ds:dword ptr[mv_position+0+edx] |
|
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2 |
|
|
|
; replace pv1 with the clip point |
|
mov edx,esp |
|
mov eax,ds:dword ptr[cp_leftedge+ebx] |
|
test al,al |
|
|
|
fmul st(0),st(3) |
|
fxch st(1) ; 1 | 0 | 2 |
|
fmul st(0),st(3) |
|
fxch st(2) ; 2 | 0 | 1 |
|
fmulp st(3),st(0) ; 0 | 1 | 2 |
|
fadd ds:dword ptr[mv_position+0+esi] |
|
fxch st(1) ; 1 | 0 | 2 |
|
fadd ds:dword ptr[mv_position+4+esi] |
|
fxch st(2) ; 2 | 0 | 1 |
|
fadd ds:dword ptr[mv_position+8+esi] |
|
fxch st(1) ; 0 | 2 | 1 |
|
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1 |
|
fstp ds:dword ptr[mv_position+8+esp] ; 1 |
|
fstp ds:dword ptr[mv_position+4+esp] |
|
|
|
; if (clip->leftedge) |
|
; { |
|
jz Ltestright |
|
|
|
; r_leftclipped = true; |
|
; r_leftexit = clipvert; |
|
mov ds:dword ptr[_r_leftclipped],1 |
|
mov eax,ds:dword ptr[mv_position+0+esp] |
|
mov ds:dword ptr[_r_leftexit+mv_position+0],eax |
|
mov eax,ds:dword ptr[mv_position+4+esp] |
|
mov ds:dword ptr[_r_leftexit+mv_position+4],eax |
|
mov eax,ds:dword ptr[mv_position+8+esp] |
|
mov ds:dword ptr[_r_leftexit+mv_position+8],eax |
|
|
|
jmp Lcontinue |
|
|
|
; } |
|
|
|
Ltestright: |
|
; else if (clip->rightedge) |
|
; { |
|
test ah,ah |
|
jz Lcontinue |
|
|
|
; r_rightclipped = true; |
|
; r_rightexit = clipvert; |
|
mov ds:dword ptr[_r_rightclipped],1 |
|
mov eax,ds:dword ptr[mv_position+0+esp] |
|
mov ds:dword ptr[_r_rightexit+mv_position+0],eax |
|
mov eax,ds:dword ptr[mv_position+4+esp] |
|
mov ds:dword ptr[_r_rightexit+mv_position+4],eax |
|
mov eax,ds:dword ptr[mv_position+8+esp] |
|
mov ds:dword ptr[_r_rightexit+mv_position+8],eax |
|
|
|
; } |
|
; |
|
; R_ClipEdge (pv0, &clipvert, clip->next); |
|
; return; |
|
; } |
|
jmp Lcontinue |
|
|
|
; } |
|
|
|
Lp3: |
|
|
|
; // only point 0 is clipped |
|
; r_lastvertvalid = false; |
|
|
|
mov ds:dword ptr[_r_lastvertvalid],0 |
|
|
|
; f = d0 / (d0 - d1); |
|
fld ds:dword ptr[Ld0] |
|
fld ds:dword ptr[Ld1] |
|
fsubr st(0),st(1) |
|
|
|
; // we don't cache partially clipped edges |
|
mov ds:dword ptr[_cacheoffset],07FFFFFFFh |
|
|
|
fdivp st(1),st(0) |
|
|
|
sub esp,offset mv_size ; allocate space for clipvert |
|
|
|
; clipvert.position[0] = pv0->position[0] + |
|
; f * (pv1->position[0] - pv0->position[0]); |
|
; clipvert.position[1] = pv0->position[1] + |
|
; f * (pv1->position[1] - pv0->position[1]); |
|
; clipvert.position[2] = pv0->position[2] + |
|
; f * (pv1->position[2] - pv0->position[2]); |
|
fld ds:dword ptr[mv_position+8+edx] |
|
fsub ds:dword ptr[mv_position+8+esi] |
|
fld ds:dword ptr[mv_position+4+edx] |
|
fsub ds:dword ptr[mv_position+4+esi] |
|
fld ds:dword ptr[mv_position+0+edx] |
|
fsub ds:dword ptr[mv_position+0+esi] ; 0 | 1 | 2 |
|
|
|
mov eax,ds:dword ptr[cp_leftedge+ebx] |
|
test al,al |
|
|
|
fmul st(0),st(3) |
|
fxch st(1) ; 1 | 0 | 2 |
|
fmul st(0),st(3) |
|
fxch st(2) ; 2 | 0 | 1 |
|
fmulp st(3),st(0) ; 0 | 1 | 2 |
|
fadd ds:dword ptr[mv_position+0+esi] |
|
fxch st(1) ; 1 | 0 | 2 |
|
fadd ds:dword ptr[mv_position+4+esi] |
|
fxch st(2) ; 2 | 0 | 1 |
|
fadd ds:dword ptr[mv_position+8+esi] |
|
fxch st(1) ; 0 | 2 | 1 |
|
fstp ds:dword ptr[mv_position+0+esp] ; 2 | 1 |
|
fstp ds:dword ptr[mv_position+8+esp] ; 1 |
|
fstp ds:dword ptr[mv_position+4+esp] |
|
|
|
; replace pv0 with the clip point |
|
mov esi,esp |
|
|
|
; if (clip->leftedge) |
|
; { |
|
jz Ltestright2 |
|
|
|
; r_leftclipped = true; |
|
; r_leftenter = clipvert; |
|
mov ds:dword ptr[_r_leftclipped],1 |
|
mov eax,ds:dword ptr[mv_position+0+esp] |
|
mov ds:dword ptr[_r_leftenter+mv_position+0],eax |
|
mov eax,ds:dword ptr[mv_position+4+esp] |
|
mov ds:dword ptr[_r_leftenter+mv_position+4],eax |
|
mov eax,ds:dword ptr[mv_position+8+esp] |
|
mov ds:dword ptr[_r_leftenter+mv_position+8],eax |
|
|
|
jmp Lcontinue |
|
|
|
; } |
|
|
|
Ltestright2: |
|
; else if (clip->rightedge) |
|
; { |
|
test ah,ah |
|
jz Lcontinue |
|
|
|
; r_rightclipped = true; |
|
; r_rightenter = clipvert; |
|
mov ds:dword ptr[_r_rightclipped],1 |
|
mov eax,ds:dword ptr[mv_position+0+esp] |
|
mov ds:dword ptr[_r_rightenter+mv_position+0],eax |
|
mov eax,ds:dword ptr[mv_position+4+esp] |
|
mov ds:dword ptr[_r_rightenter+mv_position+4],eax |
|
mov eax,ds:dword ptr[mv_position+8+esp] |
|
mov ds:dword ptr[_r_rightenter+mv_position+8],eax |
|
|
|
; } |
|
jmp Lcontinue |
|
|
|
; %esi = vec3_t point to transform and project |
|
; %edx preserved |
|
LTransformAndProject: |
|
|
|
; // transform and project |
|
; VectorSubtract (world, modelorg, local); |
|
fld ds:dword ptr[mv_position+0+esi] |
|
fsub ds:dword ptr[_modelorg+0] |
|
fld ds:dword ptr[mv_position+4+esi] |
|
fsub ds:dword ptr[_modelorg+4] |
|
fld ds:dword ptr[mv_position+8+esi] |
|
fsub ds:dword ptr[_modelorg+8] |
|
fxch st(2) ; local[0] | local[1] | local[2] |
|
|
|
; TransformVector (local, transformed); |
|
; |
|
; if (transformed[2] < NEAR_CLIP) |
|
; transformed[2] = NEAR_CLIP; |
|
; |
|
; lzi0 = 1.0 / transformed[2]; |
|
fld st(0) ; local[0] | local[0] | local[1] | local[2] |
|
fmul ds:dword ptr[_vpn+0] ; zm0 | local[0] | local[1] | local[2] |
|
fld st(1) ; local[0] | zm0 | local[0] | local[1] | |
|
; local[2] |
|
fmul ds:dword ptr[_vright+0] ; xm0 | zm0 | local[0] | local[1] | local[2] |
|
fxch st(2) ; local[0] | zm0 | xm0 | local[1] | local[2] |
|
fmul ds:dword ptr[_vup+0] ; ym0 | zm0 | xm0 | local[1] | local[2] |
|
fld st(3) ; local[1] | ym0 | zm0 | xm0 | local[1] | |
|
; local[2] |
|
fmul ds:dword ptr[_vpn+4] ; zm1 | ym0 | zm0 | xm0 | local[1] | |
|
; local[2] |
|
fld st(4) ; local[1] | zm1 | ym0 | zm0 | xm0 | |
|
; local[1] | local[2] |
|
fmul ds:dword ptr[_vright+4] ; xm1 | zm1 | ym0 | zm0 | xm0 | |
|
; local[1] | local[2] |
|
fxch st(5) ; local[1] | zm1 | ym0 | zm0 | xm0 | |
|
; xm1 | local[2] |
|
fmul ds:dword ptr[_vup+4] ; ym1 | zm1 | ym0 | zm0 | xm0 | |
|
; xm1 | local[2] |
|
fxch st(1) ; zm1 | ym1 | ym0 | zm0 | xm0 | |
|
; xm1 | local[2] |
|
faddp st(3),st(0) ; ym1 | ym0 | zm2 | xm0 | xm1 | local[2] |
|
fxch st(3) ; xm0 | ym0 | zm2 | ym1 | xm1 | local[2] |
|
faddp st(4),st(0) ; ym0 | zm2 | ym1 | xm2 | local[2] |
|
faddp st(2),st(0) ; zm2 | ym2 | xm2 | local[2] |
|
fld st(3) ; local[2] | zm2 | ym2 | xm2 | local[2] |
|
fmul ds:dword ptr[_vpn+8] ; zm3 | zm2 | ym2 | xm2 | local[2] |
|
fld st(4) ; local[2] | zm3 | zm2 | ym2 | xm2 | local[2] |
|
fmul ds:dword ptr[_vright+8] ; xm3 | zm3 | zm2 | ym2 | xm2 | local[2] |
|
fxch st(5) ; local[2] | zm3 | zm2 | ym2 | xm2 | xm3 |
|
fmul ds:dword ptr[_vup+8] ; ym3 | zm3 | zm2 | ym2 | xm2 | xm3 |
|
fxch st(1) ; zm3 | ym3 | zm2 | ym2 | xm2 | xm3 |
|
faddp st(2),st(0) ; ym3 | zm4 | ym2 | xm2 | xm3 |
|
fxch st(4) ; xm3 | zm4 | ym2 | xm2 | ym3 |
|
faddp st(3),st(0) ; zm4 | ym2 | xm4 | ym3 |
|
fxch st(1) ; ym2 | zm4 | xm4 | ym3 |
|
faddp st(3),st(0) ; zm4 | xm4 | ym4 |
|
|
|
fcom ds:dword ptr[Lfp_near_clip] |
|
fnstsw ax |
|
test ah,1 |
|
jz LNoClip |
|
fstp st(0) |
|
fld ds:dword ptr[Lfp_near_clip] |
|
|
|
LNoClip: |
|
|
|
fdivr ds:dword ptr[float_1] ; lzi0 | x | y |
|
fxch st(1) ; x | lzi0 | y |
|
|
|
; // FIXME: build x/yscale into transform? |
|
; scale = xscale * lzi0; |
|
; u0 = (xcenter + scale*transformed[0]); |
|
fld ds:dword ptr[_xscale] ; xscale | x | lzi0 | y |
|
fmul st(0),st(2) ; scale | x | lzi0 | y |
|
fmulp st(1),st(0) ; scale*x | lzi0 | y |
|
fadd ds:dword ptr[_xcenter] ; u0 | lzi0 | y |
|
|
|
; if (u0 < r_refdef.fvrectx_adj) |
|
; u0 = r_refdef.fvrectx_adj; |
|
; if (u0 > r_refdef.fvrectright_adj) |
|
; u0 = r_refdef.fvrectright_adj; |
|
; FIXME: use integer compares of floats? |
|
fcom ds:dword ptr[_r_refdef+rd_fvrectx_adj] |
|
fnstsw ax |
|
test ah,1 |
|
jz LClampP0 |
|
fstp st(0) |
|
fld ds:dword ptr[_r_refdef+rd_fvrectx_adj] |
|
LClampP0: |
|
fcom ds:dword ptr[_r_refdef+rd_fvrectright_adj] |
|
fnstsw ax |
|
test ah,045h |
|
jnz LClampP1 |
|
fstp st(0) |
|
fld ds:dword ptr[_r_refdef+rd_fvrectright_adj] |
|
LClampP1: |
|
|
|
fld st(1) ; lzi0 | u0 | lzi0 | y |
|
|
|
; scale = yscale * lzi0; |
|
; v0 = (ycenter - scale*transformed[1]); |
|
fmul ds:dword ptr[_yscale] ; scale | u0 | lzi0 | y |
|
fmulp st(3),st(0) ; u0 | lzi0 | scale*y |
|
fxch st(2) ; scale*y | lzi0 | u0 |
|
fsubr ds:dword ptr[_ycenter] ; v0 | lzi0 | u0 |
|
|
|
; if (v0 < r_refdef.fvrecty_adj) |
|
; v0 = r_refdef.fvrecty_adj; |
|
; if (v0 > r_refdef.fvrectbottom_adj) |
|
; v0 = r_refdef.fvrectbottom_adj; |
|
; FIXME: use integer compares of floats? |
|
fcom ds:dword ptr[_r_refdef+rd_fvrecty_adj] |
|
fnstsw ax |
|
test ah,1 |
|
jz LClampP2 |
|
fstp st(0) |
|
fld ds:dword ptr[_r_refdef+rd_fvrecty_adj] |
|
LClampP2: |
|
fcom ds:dword ptr[_r_refdef+rd_fvrectbottom_adj] |
|
fnstsw ax |
|
test ah,045h |
|
jnz LClampP3 |
|
fstp st(0) |
|
fld ds:dword ptr[_r_refdef+rd_fvrectbottom_adj] |
|
LClampP3: |
|
ret |
|
|
|
|
|
_TEXT ENDS |
|
endif ;id386 |
|
END
|
|
|