1 /* 2 Copyright (C) 1996-1997 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 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 34 Lfloat_1: .single 1.0 35 Ltemp: .long 0 36 Lcoords: .long 0, 0, 0 37 38 .text 39 40 #define fv 12+4 41 #define pstverts 12+8 42 43 .globl C(R_AliasTransformAndProjectFinalVerts) 44 C(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 63 Lloop: 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 158 Lp1: 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 232 Lsavelight: 233 fstp %st(0) 234 jmp Lp1 235 236 #endif // id386 237 238