1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19*/ 20// 21// r_aliasa.s 22// x86 assembly-language Alias model transform and project code. 23// 24 25#include "asm_i386.h" 26#include "quakeasm.h" 27#include "asm_draw.h" 28#include "d_ifacea.h" 29 30#if id386 31 32 .data 33 34Lfloat_1: .single 1.0 35Ltemp: .long 0 36Lcoords: .long 0, 0, 0 37 38 .text 39 40#define fv 12+4 41#define pstverts 12+8 42 43.globl C(R_AliasTransformAndProjectFinalVerts) 44C(R_AliasTransformAndProjectFinalVerts): 45 pushl %ebp // preserve caller's stack frame 46 pushl %edi 47 pushl %esi // preserve register variables 48 49// int i, temp; 50// float lightcos, *plightnormal, zi; 51// trivertx_t *pverts; 52 53// pverts = r_apverts; 54 movl C(r_apverts),%esi 55 56// for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++) 57// { 58 movl pstverts(%esp),%ebp 59 movl fv(%esp),%edi 60 movl C(r_anumverts),%ecx 61 subl %edx,%edx 62 63Lloop: 64 65// // transform and project 66// zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) + 67// aliastransform[2][3]); 68 movb (%esi),%dl 69 movb %dl,Lcoords 70 fildl Lcoords // v[0] 71 movb 1(%esi),%dl 72 movb %dl,Lcoords+4 73 fildl Lcoords+4 // v[1] | v[0] 74 movb 2(%esi),%dl 75 movb %dl,Lcoords+8 76 fildl Lcoords+8 // v[2] | v[1] | v[0] 77 78 fld %st(2) // v[0] | v[2] | v[1] | v[0] 79 fmuls C(aliastransform)+32 // accum | v[2] | v[1] | v[0] 80 fld %st(2) // v[1] | accum | v[2] | v[1] | v[0] 81 fmuls C(aliastransform)+36 // accum2 | accum | v[2] | v[1] | v[0] 82 fxch %st(1) // accum | accum2 | v[2] | v[1] | v[0] 83 fadds C(aliastransform)+44 // accum | accum2 | v[2] | v[1] | v[0] 84 fld %st(2) // v[2] | accum | accum2 | v[2] | v[1] | v[0] 85 fmuls C(aliastransform)+40 // accum3 | accum | accum2 | v[2] | v[1] | 86 // v[0] 87 fxch %st(1) // accum | accum3 | accum2 | v[2] | v[1] | v[0] 88 faddp %st(0),%st(2) // accum3 | accum | v[2] | v[1] | v[0] 89 movb tv_lightnormalindex(%esi),%dl 90 movl stv_s(%ebp),%eax 91 movl %eax,fv_v+8(%edi) 92 faddp %st(0),%st(1) // z | v[2] | v[1] | v[0] 93 94 movl stv_t(%ebp),%eax 95 movl %eax,fv_v+12(%edi) 96 97// // lighting 98// plightnormal = r_avertexnormals[pverts->lightnormalindex]; 99 100 fdivrs Lfloat_1 // zi | v[2] | v[1] | v[0] 101 102// fv->v[2] = pstverts->s; 103// fv->v[3] = pstverts->t; 104// fv->flags = pstverts->onseam; 105 movl stv_onseam(%ebp),%eax 106 movl %eax,fv_flags(%edi) 107 108 movl fv_size(%edi),%eax 109 movl stv_size(%ebp),%eax 110 movl 4(%esi),%eax 111 112 leal (%edx,%edx,2),%eax // index*3 113 114 fxch %st(3) // v[0] | v[2] | v[1] | zi 115 116// lightcos = DotProduct (plightnormal, r_plightvec); 117 flds C(r_avertexnormals)(,%eax,4) 118 fmuls C(r_plightvec) 119 flds C(r_avertexnormals)+4(,%eax,4) 120 fmuls C(r_plightvec)+4 121 flds C(r_avertexnormals)+8(,%eax,4) 122 fmuls C(r_plightvec)+8 123 fxch %st(1) 124 faddp %st(0),%st(2) 125 fld %st(2) // v[0] | laccum | laccum2 | v[0] | v[2] | 126 // v[1] | zi 127 fmuls C(aliastransform)+0 // xaccum | laccum | laccum2 | v[0] | v[2] | 128 // v[1] | zi 129 fxch %st(2) // laccum2 | laccum | xaccum | v[0] | v[2] | 130 // v[1] | zi 131 faddp %st(0),%st(1) // laccum | xaccum | v[0] | v[2] | v[1] | zi 132 133// temp = r_ambientlight; 134// if (lightcos < 0) 135// { 136 fsts Ltemp 137 movl C(r_ambientlight),%eax 138 movb Ltemp+3,%dl 139 testb $0x80,%dl 140 jz Lsavelight // no need to clamp if only ambient lit, because 141 // r_ambientlight is preclamped 142 143// temp += (int)(r_shadelight * lightcos); 144 fmuls C(r_shadelight) 145// FIXME: fast float->int conversion? 146 fistpl Ltemp 147 addl Ltemp,%eax 148 149// // clamp; because we limited the minimum ambient and shading light, we 150// // don't have to clamp low light, just bright 151// if (temp < 0) 152// temp = 0; 153 jns Lp1 154 subl %eax,%eax 155 156// } 157 158Lp1: 159 160// fv->v[4] = temp; 161// 162// // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is 163// // scaled up by 1/2**31, and the scaling cancels out for x and y in the 164// // projection 165// fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + 166// aliastransform[0][3]) * zi) + aliasxcenter; 167// fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + 168// aliastransform[1][3]) * zi) + aliasycenter; 169// fv->v[5] = zi; 170 fxch %st(1) // v[0] | xaccum | v[2] | v[1] | zi 171 fmuls C(aliastransform)+16 // yaccum | xaccum | v[2] | v[1] | zi 172 fxch %st(3) // v[1] | xaccum | v[2] | yaccum | zi 173 fld %st(0) // v[1] | v[1] | xaccum | v[2] | yaccum | zi 174 fmuls C(aliastransform)+4 // xaccum2 | v[1] | xaccum | v[2] | yaccum |zi 175 fxch %st(1) // v[1] | xaccum2 | xaccum | v[2] | yaccum |zi 176 movl %eax,fv_v+16(%edi) 177 fmuls C(aliastransform)+20 // yaccum2 | xaccum2 | xaccum | v[2] | yaccum| 178 // zi 179 fxch %st(2) // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| 180 // zi 181 fadds C(aliastransform)+12 // xaccum | xaccum2 | yaccum2 | v[2] | yaccum| 182 // zi 183 fxch %st(4) // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| 184 // zi 185 fadds C(aliastransform)+28 // yaccum | xaccum2 | yaccum2 | v[2] | xaccum| 186 // zi 187 fxch %st(3) // v[2] | xaccum2 | yaccum2 | yaccum | xaccum| 188 // zi 189 fld %st(0) // v[2] | v[2] | xaccum2 | yaccum2 | yaccum | 190 // xaccum | zi 191 fmuls C(aliastransform)+8 // xaccum3 | v[2] | xaccum2 | yaccum2 |yaccum| 192 // xaccum | zi 193 fxch %st(1) // v[2] | xaccum3 | xaccum2 | yaccum2 |yaccum| 194 // xaccum | zi 195 fmuls C(aliastransform)+24 // yaccum3 | xaccum3 | xaccum2 | yaccum2 | 196 // yaccum | xaccum | zi 197 fxch %st(5) // xaccum | xaccum3 | xaccum2 | yaccum2 | 198 // yaccum | yaccum3 | zi 199 faddp %st(0),%st(2) // xaccum3 | xaccum | yaccum2 | yaccum | 200 // yaccum3 | zi 201 fxch %st(3) // yaccum | xaccum | yaccum2 | xaccum3 | 202 // yaccum3 | zi 203 faddp %st(0),%st(2) // xaccum | yaccum | xaccum3 | yaccum3 | zi 204 addl $(tv_size),%esi 205 faddp %st(0),%st(2) // yaccum | x | yaccum3 | zi 206 faddp %st(0),%st(2) // x | y | zi 207 addl $(stv_size),%ebp 208 fmul %st(2),%st(0) // x/z | y | zi 209 fxch %st(1) // y | x/z | zi 210 fmul %st(2),%st(0) // y/z | x/z | zi 211 fxch %st(1) // x/z | y/z | zi 212 fadds C(aliasxcenter) // u | y/z | zi 213 fxch %st(1) // y/z | u | zi 214 fadds C(aliasycenter) // v | u | zi 215 fxch %st(2) // zi | u | v 216// FIXME: fast float->int conversion? 217 fistpl fv_v+20(%edi) // u | v 218 fistpl fv_v+0(%edi) // v 219 fistpl fv_v+4(%edi) 220 221// } 222 223 addl $(fv_size),%edi 224 decl %ecx 225 jnz Lloop 226 227 popl %esi // restore register variables 228 popl %edi 229 popl %ebp // restore the caller's stack frame 230 ret 231 232Lsavelight: 233 fstp %st(0) 234 jmp Lp1 235 236#endif // id386 237 238