mirror of
https://git.code.sf.net/p/quake/quakeforge-old
synced 2024-11-11 07:01:46 +00:00
c3f5581b0a
Unchained, Ultimate, Ultra, Up Yours, Underworld, Underground, Unified, Unity, etc. You know the drill. This takes care of the "standalone" problem with the wrong name, and the recent snafu with multiple developers working on the same files simultaneously...expect me (and probably others) to start locking dirs when updates are taking place. And yes, this update is really as large as it looks. Software only at the moment, but I will have the makefile updated to build the GL builds as well.
838 lines
18 KiB
ArmAsm
838 lines
18 KiB
ArmAsm
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
//
|
|
// r_drawa.s
|
|
// x86 assembly-language edge clipping and emission code
|
|
//
|
|
|
|
#include "asm_i386.h"
|
|
#include "quakeasm.h"
|
|
#include "asm_draw.h"
|
|
#include "d_ifacea.h"
|
|
|
|
#if id386
|
|
|
|
// !!! if these are changed, they must be changed in r_draw.c too !!!
|
|
#define FULLY_CLIPPED_CACHED 0x80000000
|
|
#define FRAMECOUNT_MASK 0x7FFFFFFF
|
|
|
|
.data
|
|
|
|
Ld0: .single 0.0
|
|
Ld1: .single 0.0
|
|
Lstack: .long 0
|
|
Lfp_near_clip: .single NEAR_CLIP
|
|
Lceilv0: .long 0
|
|
Lv: .long 0
|
|
Lu0: .long 0
|
|
Lv0: .long 0
|
|
Lzi0: .long 0
|
|
|
|
.text
|
|
|
|
//----------------------------------------------------------------------
|
|
// edge clipping code
|
|
//----------------------------------------------------------------------
|
|
|
|
#define pv0 4+12
|
|
#define pv1 8+12
|
|
#define clip 12+12
|
|
|
|
.align 4
|
|
.globl C(R_ClipEdge)
|
|
C(R_ClipEdge):
|
|
pushl %esi // preserve register variables
|
|
pushl %edi
|
|
pushl %ebx
|
|
movl %esp,Lstack // for clearing the stack later
|
|
|
|
// float d0, d1, f;
|
|
// mvertex_t clipvert;
|
|
|
|
movl clip(%esp),%ebx
|
|
movl pv0(%esp),%esi
|
|
movl pv1(%esp),%edx
|
|
|
|
// if (clip)
|
|
// {
|
|
testl %ebx,%ebx
|
|
jz Lemit
|
|
|
|
// do
|
|
// {
|
|
|
|
Lcliploop:
|
|
|
|
// d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
|
|
// d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
|
|
flds mv_position+0(%esi)
|
|
fmuls cp_normal+0(%ebx)
|
|
flds mv_position+4(%esi)
|
|
fmuls cp_normal+4(%ebx)
|
|
flds mv_position+8(%esi)
|
|
fmuls cp_normal+8(%ebx)
|
|
fxch %st(1)
|
|
faddp %st(0),%st(2) // d0mul2 | d0add0
|
|
|
|
flds mv_position+0(%edx)
|
|
fmuls cp_normal+0(%ebx)
|
|
flds mv_position+4(%edx)
|
|
fmuls cp_normal+4(%ebx)
|
|
flds mv_position+8(%edx)
|
|
fmuls cp_normal+8(%ebx)
|
|
fxch %st(1)
|
|
faddp %st(0),%st(2) // d1mul2 | d1add0 | d0mul2 | d0add0
|
|
fxch %st(3) // d0add0 | d1add0 | d0mul2 | d1mul2
|
|
|
|
faddp %st(0),%st(2) // d1add0 | dot0 | d1mul2
|
|
faddp %st(0),%st(2) // dot0 | dot1
|
|
|
|
fsubs cp_dist(%ebx) // d0 | dot1
|
|
fxch %st(1) // dot1 | d0
|
|
fsubs cp_dist(%ebx) // d1 | d0
|
|
fxch %st(1)
|
|
fstps Ld0
|
|
fstps Ld1
|
|
|
|
// if (d0 >= 0)
|
|
// {
|
|
movl Ld0,%eax
|
|
movl Ld1,%ecx
|
|
orl %eax,%ecx
|
|
js Lp2
|
|
|
|
// both points are unclipped
|
|
|
|
Lcontinue:
|
|
|
|
//
|
|
// R_ClipEdge (&clipvert, pv1, clip->next);
|
|
// return;
|
|
// }
|
|
// } while ((clip = clip->next) != NULL);
|
|
movl cp_next(%ebx),%ebx
|
|
testl %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 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)
|
|
// {
|
|
cmpl $0,C(r_lastvertvalid)
|
|
jz LCalcFirst
|
|
|
|
// u0 = r_u1;
|
|
// v0 = r_v1;
|
|
// lzi0 = r_lzi1;
|
|
// ceilv0 = r_ceilv1;
|
|
movl C(r_lzi1),%eax
|
|
movl C(r_u1),%ecx
|
|
movl %eax,Lzi0
|
|
movl %ecx,Lu0
|
|
movl C(r_v1),%ecx
|
|
movl C(r_ceilv1),%eax
|
|
movl %ecx,Lv0
|
|
movl %eax,Lceilv0
|
|
jmp LCalcSecond
|
|
|
|
// }
|
|
|
|
LCalcFirst:
|
|
|
|
// else
|
|
// {
|
|
// world = &pv0->position[0];
|
|
|
|
call LTransformAndProject // v0 | lzi0 | u0
|
|
|
|
fsts Lv0
|
|
fxch %st(2) // u0 | lzi0 | v0
|
|
fstps Lu0 // lzi0 | v0
|
|
fstps Lzi0 // v0
|
|
|
|
// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
|
|
fistpl Lceilv0
|
|
|
|
// }
|
|
|
|
LCalcSecond:
|
|
|
|
// world = &pv1->position[0];
|
|
movl %edx,%esi
|
|
|
|
call LTransformAndProject // v1 | lzi1 | u1
|
|
|
|
flds Lu0 // u0 | v1 | lzi1 | u1
|
|
fxch %st(3) // u1 | v1 | lzi1 | u0
|
|
flds Lzi0 // lzi0 | u1 | v1 | lzi1 | u0
|
|
fxch %st(3) // lzi1 | u1 | v1 | lzi0 | u0
|
|
flds 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);
|
|
fistl C(r_ceilv1)
|
|
|
|
fldcw single_cw // put back normal floating-point state
|
|
|
|
fsts C(r_v1)
|
|
fxch %st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0
|
|
|
|
// if (r_lzi1 > lzi0)
|
|
// lzi0 = r_lzi1;
|
|
fcom %st(1)
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LP0
|
|
fstp %st(0)
|
|
fld %st(0)
|
|
LP0:
|
|
|
|
fxch %st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0
|
|
fstps C(r_lzi1) // lzi0 | u1 | v0 | v1 | u0
|
|
fxch %st(1)
|
|
fsts C(r_u1)
|
|
fxch %st(1)
|
|
|
|
// if (lzi0 > r_nearzi) // for mipmap finding
|
|
// r_nearzi = lzi0;
|
|
fcoms C(r_nearzi)
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LP1
|
|
fsts C(r_nearzi)
|
|
LP1:
|
|
|
|
// // for right edges, all we want is the effect on 1/z
|
|
// if (r_nearzionly)
|
|
// return;
|
|
movl C(r_nearzionly),%eax
|
|
testl %eax,%eax
|
|
jz LP2
|
|
LPop5AndDone:
|
|
movl C(cacheoffset),%eax
|
|
movl C(r_framecount),%edx
|
|
cmpl $0x7FFFFFFF,%eax
|
|
jz LDoPop
|
|
andl $(FRAMECOUNT_MASK),%edx
|
|
orl $(FULLY_CLIPPED_CACHED),%edx
|
|
movl %edx,C(cacheoffset)
|
|
|
|
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
|
|
movl Lceilv0,%ebx
|
|
movl C(edge_p),%edi
|
|
movl C(r_ceilv1),%ecx
|
|
movl %edi,%edx
|
|
movl C(r_pedge),%esi
|
|
addl $(et_size),%edx
|
|
cmpl %ecx,%ebx
|
|
jz LPop5AndDone
|
|
|
|
movl C(r_pedge),%eax
|
|
movl %eax,et_owner(%edi)
|
|
|
|
// side = ceilv0 > r_ceilv1;
|
|
//
|
|
// edge->nearzi = lzi0;
|
|
fstps 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));
|
|
fsubrp %st(0),%st(3) // v0 | v1 | u0-u1
|
|
fsub %st(1),%st(0) // v0-v1 | v1 | u0-u1
|
|
fdivrp %st(0),%st(2) // v1 | ustep
|
|
|
|
// r_emitted = 1;
|
|
movl $1,C(r_emitted)
|
|
|
|
// edge = edge_p++;
|
|
movl %edx,C(edge_p)
|
|
|
|
// pretouch next edge
|
|
movl (%edx),%eax
|
|
|
|
// v2 = ceilv0 - 1;
|
|
// v = r_ceilv1;
|
|
movl %ecx,%eax
|
|
leal -1(%ebx),%ecx
|
|
movl %eax,%ebx
|
|
|
|
// edge->surfs[0] = 0;
|
|
// edge->surfs[1] = surface_p - surfaces;
|
|
movl C(surface_p),%eax
|
|
movl C(surfaces),%esi
|
|
subl %edx,%edx
|
|
subl %esi,%eax
|
|
shrl $(SURF_T_SHIFT),%eax
|
|
movl %edx,et_surfs(%edi)
|
|
movl %eax,et_surfs+2(%edi)
|
|
|
|
subl %esi,%esi
|
|
|
|
// u = r_u1 + ((float)v - r_v1) * u_step;
|
|
movl %ebx,Lv
|
|
fildl Lv // v | v1 | ustep
|
|
fsubp %st(0),%st(1) // v-v1 | ustep
|
|
fmul %st(1),%st(0) // (v-v1)*ustep | ustep
|
|
fadds C(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(3),%st(0) // u1-u0 | v0 | v1 | u0
|
|
fxch %st(2) // v1 | v0 | u1-u0 | u0
|
|
fsub %st(1),%st(0) // v1-v0 | v0 | u1-u0 | u0
|
|
fdivrp %st(0),%st(2) // v0 | ustep | u0
|
|
|
|
// r_emitted = 1;
|
|
movl $1,C(r_emitted)
|
|
|
|
// edge = edge_p++;
|
|
movl %edx,C(edge_p)
|
|
|
|
// pretouch next edge
|
|
movl (%edx),%eax
|
|
|
|
// v = ceilv0;
|
|
// v2 = r_ceilv1 - 1;
|
|
decl %ecx
|
|
|
|
// edge->surfs[0] = surface_p - surfaces;
|
|
// edge->surfs[1] = 0;
|
|
movl C(surface_p),%eax
|
|
movl C(surfaces),%esi
|
|
subl %edx,%edx
|
|
subl %esi,%eax
|
|
shrl $(SURF_T_SHIFT),%eax
|
|
movl %edx,et_surfs+2(%edi)
|
|
movl %eax,et_surfs(%edi)
|
|
|
|
movl $1,%esi
|
|
|
|
// u = u0 + ((float)v - v0) * u_step;
|
|
movl %ebx,Lv
|
|
fildl Lv // v | v0 | ustep | u0
|
|
fsubp %st(0),%st(1) // v-v0 | ustep | u0
|
|
fmul %st(1),%st(0) // (v-v0)*ustep | ustep | u0
|
|
faddp %st(0),%st(2) // ustep | u
|
|
fxch %st(1) // u | ustep
|
|
|
|
// }
|
|
|
|
LSideDone:
|
|
|
|
// edge->u_step = u_step*0x100000;
|
|
// edge->u = u*0x100000 + 0xFFFFF;
|
|
|
|
fmuls fp_1m // u*0x100000 | ustep
|
|
fxch %st(1) // ustep | u*0x100000
|
|
fmuls fp_1m // ustep*0x100000 | u*0x100000
|
|
fxch %st(1) // u*0x100000 | ustep*0x100000
|
|
fadds fp_1m_minus_1 // u*0x100000 + 0xFFFFF | ustep*0x100000
|
|
fxch %st(1) // ustep*0x100000 | u*0x100000 + 0xFFFFF
|
|
fistpl et_u_step(%edi) // u*0x100000 + 0xFFFFF
|
|
fistpl 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;
|
|
movl et_u(%edi),%eax
|
|
movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx
|
|
cmpl %edx,%eax
|
|
jl LP4
|
|
movl C(r_refdef)+rd_vrectright_adj_shift20,%edx
|
|
cmpl %edx,%eax
|
|
jng LP5
|
|
LP4:
|
|
movl %edx,et_u(%edi)
|
|
movl %edx,%eax
|
|
LP5:
|
|
|
|
// // sort the edge in normally
|
|
// u_check = edge->u;
|
|
//
|
|
// if (edge->surfs[0])
|
|
// u_check++; // sort trailers after leaders
|
|
addl %esi,%eax
|
|
|
|
// if (!newedges[v] || newedges[v]->u >= u_check)
|
|
// {
|
|
movl C(newedges)(,%ebx,4),%esi
|
|
testl %esi,%esi
|
|
jz LDoFirst
|
|
cmpl %eax,et_u(%esi)
|
|
jl LNotFirst
|
|
LDoFirst:
|
|
|
|
// edge->next = newedges[v];
|
|
// newedges[v] = edge;
|
|
movl %esi,et_next(%edi)
|
|
movl %edi,C(newedges)(,%ebx,4)
|
|
|
|
jmp LSetRemove
|
|
|
|
// }
|
|
|
|
LNotFirst:
|
|
|
|
// else
|
|
// {
|
|
// pcheck = newedges[v];
|
|
//
|
|
// while (pcheck->next && pcheck->next->u < u_check)
|
|
// pcheck = pcheck->next;
|
|
LFindInsertLoop:
|
|
movl %esi,%edx
|
|
movl et_next(%esi),%esi
|
|
testl %esi,%esi
|
|
jz LInsertFound
|
|
cmpl %eax,et_u(%esi)
|
|
jl LFindInsertLoop
|
|
|
|
LInsertFound:
|
|
|
|
// edge->next = pcheck->next;
|
|
// pcheck->next = edge;
|
|
movl %esi,et_next(%edi)
|
|
movl %edi,et_next(%edx)
|
|
|
|
// }
|
|
|
|
LSetRemove:
|
|
|
|
// edge->nextremove = removeedges[v2];
|
|
// removeedges[v2] = edge;
|
|
movl C(removeedges)(,%ecx,4),%eax
|
|
movl %edi,C(removeedges)(,%ecx,4)
|
|
movl %eax,et_nextremove(%edi)
|
|
|
|
Ldone:
|
|
movl Lstack,%esp // clear temporary variables from stack
|
|
|
|
popl %ebx // restore register variables
|
|
popl %edi
|
|
popl %esi
|
|
ret
|
|
|
|
// at least one point is clipped
|
|
|
|
Lp2:
|
|
testl %eax,%eax
|
|
jns Lp1
|
|
|
|
// else
|
|
// {
|
|
// // point 0 is clipped
|
|
|
|
// if (d1 < 0)
|
|
// {
|
|
movl Ld1,%eax
|
|
testl %eax,%eax
|
|
jns Lp3
|
|
|
|
// // both points are clipped
|
|
// // we do cache fully clipped edges
|
|
// if (!leftclipped)
|
|
movl C(r_leftclipped),%eax
|
|
movl C(r_pedge),%ecx
|
|
testl %eax,%eax
|
|
jnz Ldone
|
|
|
|
// r_pedge->framecount = r_framecount;
|
|
movl C(r_framecount),%eax
|
|
andl $(FRAMECOUNT_MASK),%eax
|
|
orl $(FULLY_CLIPPED_CACHED),%eax
|
|
movl %eax,C(cacheoffset)
|
|
|
|
// 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);
|
|
flds Ld0
|
|
flds Ld1
|
|
fsubr %st(1),%st(0)
|
|
|
|
// // we don't cache partially clipped edges
|
|
movl $0x7FFFFFFF,C(cacheoffset)
|
|
|
|
fdivrp %st(0),%st(1)
|
|
|
|
subl $(mv_size),%esp // 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]);
|
|
flds mv_position+8(%edx)
|
|
fsubs mv_position+8(%esi)
|
|
flds mv_position+4(%edx)
|
|
fsubs mv_position+4(%esi)
|
|
flds mv_position+0(%edx)
|
|
fsubs mv_position+0(%esi) // 0 | 1 | 2
|
|
|
|
// replace pv1 with the clip point
|
|
movl %esp,%edx
|
|
movl cp_leftedge(%ebx),%eax
|
|
testb %al,%al
|
|
|
|
fmul %st(3),%st(0)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fmul %st(3),%st(0)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fmulp %st(0),%st(3) // 0 | 1 | 2
|
|
fadds mv_position+0(%esi)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fadds mv_position+4(%esi)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fadds mv_position+8(%esi)
|
|
fxch %st(1) // 0 | 2 | 1
|
|
fstps mv_position+0(%esp) // 2 | 1
|
|
fstps mv_position+8(%esp) // 1
|
|
fstps mv_position+4(%esp)
|
|
|
|
// if (clip->leftedge)
|
|
// {
|
|
jz Ltestright
|
|
|
|
// r_leftclipped = true;
|
|
// r_leftexit = clipvert;
|
|
movl $1,C(r_leftclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_leftexit)+mv_position+8
|
|
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Ltestright:
|
|
// else if (clip->rightedge)
|
|
// {
|
|
testb %ah,%ah
|
|
jz Lcontinue
|
|
|
|
// r_rightclipped = true;
|
|
// r_rightexit = clipvert;
|
|
movl $1,C(r_rightclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_rightexit)+mv_position+8
|
|
|
|
// }
|
|
//
|
|
// R_ClipEdge (pv0, &clipvert, clip->next);
|
|
// return;
|
|
// }
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Lp3:
|
|
|
|
// // only point 0 is clipped
|
|
// r_lastvertvalid = false;
|
|
|
|
movl $0,C(r_lastvertvalid)
|
|
|
|
// f = d0 / (d0 - d1);
|
|
flds Ld0
|
|
flds Ld1
|
|
fsubr %st(1),%st(0)
|
|
|
|
// // we don't cache partially clipped edges
|
|
movl $0x7FFFFFFF,C(cacheoffset)
|
|
|
|
fdivrp %st(0),%st(1)
|
|
|
|
subl $(mv_size),%esp // 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]);
|
|
flds mv_position+8(%edx)
|
|
fsubs mv_position+8(%esi)
|
|
flds mv_position+4(%edx)
|
|
fsubs mv_position+4(%esi)
|
|
flds mv_position+0(%edx)
|
|
fsubs mv_position+0(%esi) // 0 | 1 | 2
|
|
|
|
movl cp_leftedge(%ebx),%eax
|
|
testb %al,%al
|
|
|
|
fmul %st(3),%st(0)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fmul %st(3),%st(0)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fmulp %st(0),%st(3) // 0 | 1 | 2
|
|
fadds mv_position+0(%esi)
|
|
fxch %st(1) // 1 | 0 | 2
|
|
fadds mv_position+4(%esi)
|
|
fxch %st(2) // 2 | 0 | 1
|
|
fadds mv_position+8(%esi)
|
|
fxch %st(1) // 0 | 2 | 1
|
|
fstps mv_position+0(%esp) // 2 | 1
|
|
fstps mv_position+8(%esp) // 1
|
|
fstps mv_position+4(%esp)
|
|
|
|
// replace pv0 with the clip point
|
|
movl %esp,%esi
|
|
|
|
// if (clip->leftedge)
|
|
// {
|
|
jz Ltestright2
|
|
|
|
// r_leftclipped = true;
|
|
// r_leftenter = clipvert;
|
|
movl $1,C(r_leftclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_leftenter)+mv_position+8
|
|
|
|
jmp Lcontinue
|
|
|
|
// }
|
|
|
|
Ltestright2:
|
|
// else if (clip->rightedge)
|
|
// {
|
|
testb %ah,%ah
|
|
jz Lcontinue
|
|
|
|
// r_rightclipped = true;
|
|
// r_rightenter = clipvert;
|
|
movl $1,C(r_rightclipped)
|
|
movl mv_position+0(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+0
|
|
movl mv_position+4(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+4
|
|
movl mv_position+8(%esp),%eax
|
|
movl %eax,C(r_rightenter)+mv_position+8
|
|
|
|
// }
|
|
jmp Lcontinue
|
|
|
|
// %esi = vec3_t point to transform and project
|
|
// %edx preserved
|
|
LTransformAndProject:
|
|
|
|
// // transform and project
|
|
// VectorSubtract (world, modelorg, local);
|
|
flds mv_position+0(%esi)
|
|
fsubs C(modelorg)+0
|
|
flds mv_position+4(%esi)
|
|
fsubs C(modelorg)+4
|
|
flds mv_position+8(%esi)
|
|
fsubs C(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]
|
|
fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2]
|
|
fld %st(1) // local[0] | zm0 | local[0] | local[1] |
|
|
// local[2]
|
|
fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2]
|
|
fxch %st(2) // local[0] | zm0 | xm0 | local[1] | local[2]
|
|
fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2]
|
|
fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] |
|
|
// local[2]
|
|
fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] |
|
|
// local[2]
|
|
fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 |
|
|
// local[1] | local[2]
|
|
fmuls C(vright)+4 // xm1 | zm1 | ym0 | zm0 | xm0 |
|
|
// local[1] | local[2]
|
|
fxch %st(5) // local[1] | zm1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
fmuls C(vup)+4 // ym1 | zm1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
fxch %st(1) // zm1 | ym1 | ym0 | zm0 | xm0 |
|
|
// xm1 | local[2]
|
|
faddp %st(0),%st(3) // ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
|
|
fxch %st(3) // xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
|
|
faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2]
|
|
faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2]
|
|
fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2]
|
|
fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
|
|
fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3
|
|
fmuls C(vup)+8 // ym3 | zm3 | zm2 | ym2 | xm2 | xm3
|
|
fxch %st(1) // zm3 | ym3 | zm2 | ym2 | xm2 | xm3
|
|
faddp %st(0),%st(2) // ym3 | zm4 | ym2 | xm2 | xm3
|
|
fxch %st(4) // xm3 | zm4 | ym2 | xm2 | ym3
|
|
faddp %st(0),%st(3) // zm4 | ym2 | xm4 | ym3
|
|
fxch %st(1) // ym2 | zm4 | xm4 | ym3
|
|
faddp %st(0),%st(3) // zm4 | xm4 | ym4
|
|
|
|
fcoms Lfp_near_clip
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LNoClip
|
|
fstp %st(0)
|
|
flds Lfp_near_clip
|
|
|
|
LNoClip:
|
|
|
|
fdivrs 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]);
|
|
flds C(xscale) // xscale | x | lzi0 | y
|
|
fmul %st(2),%st(0) // scale | x | lzi0 | y
|
|
fmulp %st(0),%st(1) // scale*x | lzi0 | y
|
|
fadds C(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?
|
|
fcoms C(r_refdef)+rd_fvrectx_adj
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LClampP0
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectx_adj
|
|
LClampP0:
|
|
fcoms C(r_refdef)+rd_fvrectright_adj
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LClampP1
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectright_adj
|
|
LClampP1:
|
|
|
|
fld %st(1) // lzi0 | u0 | lzi0 | y
|
|
|
|
// scale = yscale * lzi0;
|
|
// v0 = (ycenter - scale*transformed[1]);
|
|
fmuls C(yscale) // scale | u0 | lzi0 | y
|
|
fmulp %st(0),%st(3) // u0 | lzi0 | scale*y
|
|
fxch %st(2) // scale*y | lzi0 | u0
|
|
fsubrs C(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?
|
|
fcoms C(r_refdef)+rd_fvrecty_adj
|
|
fnstsw %ax
|
|
testb $1,%ah
|
|
jz LClampP2
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrecty_adj
|
|
LClampP2:
|
|
fcoms C(r_refdef)+rd_fvrectbottom_adj
|
|
fnstsw %ax
|
|
testb $0x45,%ah
|
|
jnz LClampP3
|
|
fstp %st(0)
|
|
flds C(r_refdef)+rd_fvrectbottom_adj
|
|
LClampP3:
|
|
ret
|
|
|
|
#endif // id386
|
|
|