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