0,0 → 1,237 |
/* |
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_aliasa.s |
// x86 assembly-language Alias model transform and project code. |
// |
|
#include "asm_i386.h" |
#include "quakeasm.h" |
#include "asm_draw.h" |
#include "d_ifacea.h" |
|
#if id386 |
|
.data |
|
Lfloat_1: .single 1.0 |
Ltemp: .long 0 |
Lcoords: .long 0, 0, 0 |
|
.text |
|
#define fv 12+4 |
#define pstverts 12+8 |
|
.globl C(R_AliasTransformAndProjectFinalVerts) |
C(R_AliasTransformAndProjectFinalVerts): |
pushl %ebp // preserve caller's stack frame |
pushl %edi |
pushl %esi // preserve register variables |
|
// int i, temp; |
// float lightcos, *plightnormal, zi; |
// trivertx_t *pverts; |
|
// pverts = r_apverts; |
movl C(r_apverts),%esi |
|
// for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++) |
// { |
movl pstverts(%esp),%ebp |
movl fv(%esp),%edi |
movl C(r_anumverts),%ecx |
subl %edx,%edx |
|
Lloop: |
|
// // transform and project |
// zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) + |
// aliastransform[2][3]); |
movb (%esi),%dl |
movb %dl,Lcoords |
fildl Lcoords // v[0] |
movb 1(%esi),%dl |
movb %dl,Lcoords+4 |
fildl Lcoords+4 // v[1] | v[0] |
movb 2(%esi),%dl |
movb %dl,Lcoords+8 |
fildl Lcoords+8 // v[2] | v[1] | v[0] |
|
fld %st(2) // v[0] | v[2] | v[1] | v[0] |
fmuls C(aliastransform)+32 // accum | v[2] | v[1] | v[0] |
fld %st(2) // v[1] | accum | v[2] | v[1] | v[0] |
fmuls C(aliastransform)+36 // accum2 | accum | v[2] | v[1] | v[0] |
fxch %st(1) // accum | accum2 | v[2] | v[1] | v[0] |
fadds C(aliastransform)+44 // accum | accum2 | v[2] | v[1] | v[0] |
fld %st(2) // v[2] | accum | accum2 | v[2] | v[1] | v[0] |
fmuls C(aliastransform)+40 // accum3 | accum | accum2 | v[2] | v[1] | |
// v[0] |
fxch %st(1) // accum | accum3 | accum2 | v[2] | v[1] | v[0] |
faddp %st(0),%st(2) // accum3 | accum | v[2] | v[1] | v[0] |
movb tv_lightnormalindex(%esi),%dl |
movl stv_s(%ebp),%eax |
movl %eax,fv_v+8(%edi) |
faddp %st(0),%st(1) // z | v[2] | v[1] | v[0] |
|
movl stv_t(%ebp),%eax |
movl %eax,fv_v+12(%edi) |
|
// // lighting |
// plightnormal = r_avertexnormals[pverts->lightnormalindex]; |
|
fdivrs Lfloat_1 // zi | v[2] | v[1] | v[0] |
|
// fv->v[2] = pstverts->s; |
// fv->v[3] = pstverts->t; |
// fv->flags = pstverts->onseam; |
movl stv_onseam(%ebp),%eax |
movl %eax,fv_flags(%edi) |
|
movl fv_size(%edi),%eax |
movl stv_size(%ebp),%eax |
movl 4(%esi),%eax |
|
leal (%edx,%edx,2),%eax // index*3 |
|
fxch %st(3) // v[0] | v[2] | v[1] | zi |
|
// lightcos = DotProduct (plightnormal, r_plightvec); |
flds C(r_avertexnormals)(,%eax,4) |
fmuls C(r_plightvec) |
flds C(r_avertexnormals)+4(,%eax,4) |
fmuls C(r_plightvec)+4 |
flds C(r_avertexnormals)+8(,%eax,4) |
fmuls C(r_plightvec)+8 |
fxch %st(1) |
faddp %st(0),%st(2) |
fld %st(2) // v[0] | laccum | laccum2 | v[0] | v[2] | |
// v[1] | zi |
fmuls C(aliastransform)+0 // xaccum | laccum | laccum2 | v[0] | v[2] | |
// v[1] | zi |
fxch %st(2) // laccum2 | laccum | xaccum | v[0] | v[2] | |
// v[1] | zi |
faddp %st(0),%st(1) // laccum | xaccum | v[0] | v[2] | v[1] | zi |
|
// temp = r_ambientlight; |
// if (lightcos < 0) |
// { |
fsts Ltemp |
movl C(r_ambientlight),%eax |
movb Ltemp+3,%dl |
testb $0x80,%dl |
jz Lsavelight // no need to clamp if only ambient lit, because |
// r_ambientlight is preclamped |
|
// temp += (int)(r_shadelight * lightcos); |
fmuls C(r_shadelight) |
// FIXME: fast float->int conversion? |
fistpl Ltemp |
addl Ltemp,%eax |
|
// // clamp; because we limited the minimum ambient and shading light, we |
// // don't have to clamp low light, just bright |
// if (temp < 0) |
// temp = 0; |
jns Lp1 |
subl %eax,%eax |
|
// } |
|
Lp1: |
|
// fv->v[4] = temp; |
// |
// // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is |
// // scaled up by 1/2**31, and the scaling cancels out for x and y in the |
// // projection |
// fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + |
// aliastransform[0][3]) * zi) + aliasxcenter; |
// fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + |
// aliastransform[1][3]) * zi) + aliasycenter; |
// fv->v[5] = zi; |
fxch %st(1) // v[0] | xaccum | v[2] | v[1] | zi |
fmuls C(aliastransform)+16 // yaccum | xaccum | v[2] | v[1] | zi |
fxch %st(3) // v[1] | xaccum | v[2] | yaccum | zi |
fld %st(0) // v[1] | v[1] | xaccum | v[2] | yaccum | zi |
fmuls C(aliastransform)+4 // xaccum2 | v[1] | xaccum | v[2] | yaccum |zi |
fxch %st(1) // v[1] | xaccum2 | xaccum | v[2] | yaccum |zi |
movl %eax,fv_v+16(%edi) |
fmuls C(aliastransform)+20 // yaccum2 | xaccum2 | xaccum | v[2] | yaccum| |
// zi |
fxch %st(2) // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| |
// zi |
fadds C(aliastransform)+12 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| |
// zi |
fxch %st(4) // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| |
// zi |
fadds C(aliastransform)+28 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| |
// zi |
fxch %st(3) // v[2] | xaccum2 | yaccum2 | yaccum | xaccum| |
// zi |
fld %st(0) // v[2] | v[2] | xaccum2 | yaccum2 | yaccum | |
// xaccum | zi |
fmuls C(aliastransform)+8 // xaccum3 | v[2] | xaccum2 | yaccum2 |yaccum| |
// xaccum | zi |
fxch %st(1) // v[2] | xaccum3 | xaccum2 | yaccum2 |yaccum| |
// xaccum | zi |
fmuls C(aliastransform)+24 // yaccum3 | xaccum3 | xaccum2 | yaccum2 | |
// yaccum | xaccum | zi |
fxch %st(5) // xaccum | xaccum3 | xaccum2 | yaccum2 | |
// yaccum | yaccum3 | zi |
faddp %st(0),%st(2) // xaccum3 | xaccum | yaccum2 | yaccum | |
// yaccum3 | zi |
fxch %st(3) // yaccum | xaccum | yaccum2 | xaccum3 | |
// yaccum3 | zi |
faddp %st(0),%st(2) // xaccum | yaccum | xaccum3 | yaccum3 | zi |
addl $(tv_size),%esi |
faddp %st(0),%st(2) // yaccum | x | yaccum3 | zi |
faddp %st(0),%st(2) // x | y | zi |
addl $(stv_size),%ebp |
fmul %st(2),%st(0) // x/z | y | zi |
fxch %st(1) // y | x/z | zi |
fmul %st(2),%st(0) // y/z | x/z | zi |
fxch %st(1) // x/z | y/z | zi |
fadds C(aliasxcenter) // u | y/z | zi |
fxch %st(1) // y/z | u | zi |
fadds C(aliasycenter) // v | u | zi |
fxch %st(2) // zi | u | v |
// FIXME: fast float->int conversion? |
fistpl fv_v+20(%edi) // u | v |
fistpl fv_v+0(%edi) // v |
fistpl fv_v+4(%edi) |
|
// } |
|
addl $(fv_size),%edi |
decl %ecx |
jnz Lloop |
|
popl %esi // restore register variables |
popl %edi |
popl %ebp // restore the caller's stack frame |
ret |
|
Lsavelight: |
fstp %st(0) |
jmp Lp1 |
|
#endif // id386 |
|