1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  *
26  */
27 
28 #include "engines/icb/common/px_common.h"
29 #include "engines/icb/gfx/psx_pcdefines.h"
30 #include "engines/icb/gfx/psx_pcdefines.h"
31 #include "engines/icb/gfx/psx_scrn.h"
32 #include "engines/icb/common/px_capri_maths.h"
33 #include "engines/icb/gfx/psx_poly.h"
34 #include "engines/icb/global_objects_psx.h"
35 #include "engines/icb/light_pc.h"
36 
37 namespace ICB {
38 
39 #if _PSX_ON_PC == 1
40 
41 extern uint32 selFace;
42 extern CVECTOR unlitPoly;
43 extern CVECTOR deadObjectColour;
44 extern uint32 deadObject;
45 
46 extern uint32 _drawBface;
47 
48 extern uint8 selWRed;
49 extern uint8 selWGreen;
50 extern uint8 selWBlue;
51 
52 extern uint8 selPRed;
53 extern uint8 selPGreen;
54 extern uint8 selPBlue;
55 extern uint8 selPAlpha;
56 
57 #else // #if _PSX_ON_PC == 1
58 
59 uint32 selFace = 65537;
60 CVECTOR unlitPoly = {255, 255, 255, 0};
61 CVECTOR deadObjectColour = {0, 0, 0, 0};
62 uint32 deadObject = 0;
63 
64 uint32 _drawBface = 0;
65 
66 uint8 selWRed = 0;
67 uint8 selWGreen = 255;
68 uint8 selWBlue = 255;
69 
70 uint8 selPRed = 255;
71 uint8 selPGreen = 255;
72 uint8 selPBlue = 0;
73 uint8 selPAlpha = 0;
74 
75 #endif // #if _PSX_ON_PC == 1
76 
77 // Specialist lighting routines for polygons
78 // support for bounce & width
LightPolygon(SVECTOR * n0,CVECTOR * rgbIn,CVECTOR * rgb0)79 inline void LightPolygon(SVECTOR *n0, CVECTOR *rgbIn, CVECTOR *rgb0) {
80 	SVECTORPC lightEffect;
81 	// Normal line vector(local) -> light source effect
82 	ApplyMatrixSV_pc(gtelight_pc, n0, &lightEffect);
83 
84 	if (useLampWidth) {
85 		lightEffect.vx = (int16)(lightEffect.vx + lampWidth[0]);
86 		lightEffect.vy = (int16)(lightEffect.vy + lampWidth[1]);
87 		lightEffect.vz = (int16)(lightEffect.vy + lampWidth[2]);
88 	}
89 	if (useLampBounce) {
90 		if (lightEffect.vx < 0) {
91 			lightEffect.vx = (int16)-lightEffect.vx;
92 			if (lightEffect.vx > lampBounce[0])
93 				lightEffect.vx = (int16)lampBounce[0];
94 		}
95 		if (lightEffect.vy < 0) {
96 			lightEffect.vy = (int16)-lightEffect.vy;
97 			if (lightEffect.vy > lampBounce[1])
98 				lightEffect.vy = (int16)lampBounce[1];
99 		}
100 		if (lightEffect.vz < 0) {
101 			lightEffect.vz = (int16)-lightEffect.vz;
102 			if (lightEffect.vz > lampBounce[2])
103 				lightEffect.vz = (int16)lampBounce[2];
104 		}
105 	} else {
106 		if (lightEffect.vx < 0)
107 			lightEffect.vx = 0;
108 		if (lightEffect.vy < 0)
109 			lightEffect.vy = 0;
110 		if (lightEffect.vz < 0)
111 			lightEffect.vz = 0;
112 	}
113 
114 	// Light source effect -> Colour effect(local colour matrix+back colour)
115 	SVECTORPC colourEffect;
116 	ApplyMatrixSV_pc(gtecolour_pc, &lightEffect, &colourEffect);
117 	if (colourEffect.vx < 0)
118 		colourEffect.vx = 0;
119 	if (colourEffect.vy < 0)
120 		colourEffect.vy = 0;
121 	if (colourEffect.vz < 0)
122 		colourEffect.vz = 0;
123 
124 	// colourEffect is 0-4095 (2^12)
125 	// gteback is 0-255 (2^8)
126 	colourEffect.vx = (int16)((colourEffect.vx >> 4) + gteback_pc[0]);
127 	colourEffect.vy = (int16)((colourEffect.vy >> 4) + gteback_pc[1]);
128 	colourEffect.vz = (int16)((colourEffect.vz >> 4) + gteback_pc[2]);
129 
130 	// 256 = 1.0 in colourEffect
131 	// 128 = 1.0 in in0
132 	int32 red = (rgbIn->r * colourEffect.vx);
133 	int32 green = (rgbIn->g * colourEffect.vy);
134 	int32 blue = (rgbIn->b * colourEffect.vz);
135 
136 	red = red >> 8;
137 	green = green >> 8;
138 	blue = blue >> 8;
139 
140 	if (red > 255)
141 		red = 255;
142 	if (green > 255)
143 		green = 255;
144 	if (blue > 255)
145 		blue = 255;
146 
147 	rgb0->r = (uint8)(red);
148 	rgb0->g = (uint8)(green);
149 	rgb0->b = (uint8)(blue);
150 }
151 
152 // Specialist lighting routines for polygons
153 // support for bounce & width
LightPolygon3(SVECTOR * n0,SVECTOR * n1,SVECTOR * n2,CVECTOR * rgbIn,CVECTOR * rgb0,CVECTOR * rgb1,CVECTOR * rgb2)154 inline void LightPolygon3(SVECTOR *n0, SVECTOR *n1, SVECTOR *n2, CVECTOR *rgbIn, CVECTOR *rgb0, CVECTOR *rgb1, CVECTOR *rgb2) {
155 	LightPolygon(n0, rgbIn, rgb0);
156 	LightPolygon(n1, rgbIn, rgb1);
157 	LightPolygon(n2, rgbIn, rgb2);
158 }
159 
160 #define LIGHTPOLYGON(n0, rgbIn, rgb0)                                                                                                                                              \
161 	{                                                                                                                                                                          \
162 		if (useLampWidth || useLampBounce)                                                                                                                                 \
163 			LightPolygon(n0, rgbIn, rgb0);                                                                                                                             \
164 		else                                                                                                                                                               \
165 			gte_NormalColorCol_pc(n0, rgbIn, rgb0);                                                                                                                    \
166 	}
167 
168 #define LIGHTPOLYGON3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2)                                                                                                                         \
169 	{                                                                                                                                                                          \
170 		if (useLampWidth || useLampBounce)                                                                                                                                 \
171 			LightPolygon3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2);                                                                                                        \
172 		else                                                                                                                                                               \
173 			gte_NormalColorCol3_pc(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2);                                                                                               \
174 	}
175 
176 //----------------------------------------------------------------
177 
178 /*
179 gte_ll();
180 gte_llv0();
181 gte_llv1();
182 gte_llv2();
183 gte_llir();
184 gte_llv0tr();
185 gte_llv1tr();
186 gte_llv2tr();
187 gte_llirtr();
188 gte_llv0bk();
189 gte_llv1bk();
190 gte_llv2bk();
191 gte_llirbk();
192 gte_lc();
193 gte_lcv0();
194 gte_lcv1();
195 gte_lcv2();
196 gte_lcir();
197 gte_lcv0tr();
198 gte_lcv1tr();
199 gte_lcv2tr();
200 gte_lcirtr();
201 gte_lcv0bk();
202 gte_lcv1bk();
203 gte_lcv2bk();
204 gte_lcirbk();
205 */
206 
207 //------------------------------------------------------------------------
208 
209 #if CD_MODE == 0
210 
211 //------------------------------------------------------------------------
212 
213 // Flat, Un-Textured, Self-Luminous, triangles
drawFUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)214 void drawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
215 	SVECTORPC *v0;
216 	SVECTORPC *v1;
217 	SVECTORPC *v2;
218 
219 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
220 	uint32 num = n;
221 	int32 p, flag;
222 	uint32 i;
223 	uint32 *pPoly;
224 	int32 z0, z1, z2;
225 	SVECTORPC sxy0, sxy1, sxy2, stemp;
226 	CVECTOR *rgbIn;
227 	uint32 tmp;
228 
229 	pPoly = polyStart;
230 	// Loop over each polygon
231 	for (i = 0; i < num; i++) {
232 		// Structure is :
233 		// 0x20 | B | G | R
234 		// v1       | v0
235 		// pad      | v2
236 		rgbIn = (CVECTOR *)pPoly++;
237 
238 		if (deadObject) {
239 			rgbIn = &deadObjectColour;
240 		}
241 
242 		tmp = *pPoly++;
243 		v0 = pVertex + (tmp & 0xFFFF);
244 		v1 = pVertex + (tmp >> 16);
245 
246 		tmp = *pPoly++;
247 		v2 = pVertex + (tmp & 0xFFFF);
248 
249 		// Now do RotTransPers3 on the vectors
250 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
251 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
252 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
253 
254 		// test the return value of flag
255 		if (flag & 0x80000000)
256 			continue;
257 
258 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
259 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
260 		// test the return value of flag
261 		if (flag & 0x80000000)
262 			continue;
263 
264 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
265 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
266 		// test the return value of flag
267 		if (flag & 0x80000000)
268 			continue;
269 
270 		// Give the GTE some time to recover
271 		int32 avgz;
272 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
273 
274 		// Do we want to do back face removal ?
275 		if (_removeBackface) {
276 			// use winding order of the polygons
277 			// e.g. NormalClip which is cross product of screen vectors
278 			if (_useWindingOrder) {
279 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
280 				// Drawing back facings polys requires making them have
281 				// clockwise winding order as by definition they have
282 				// anti-clockwise winding order
283 				if (flag < 0) {
284 					if (_drawBface) {
285 						stemp = sxy1;
286 						sxy1 = sxy2;
287 						sxy2 = stemp;
288 					} else {
289 						// Skip this polygon
290 						continue;
291 					}
292 				} else if (flag == 0)
293 					continue; // ignore zero-area polygons
294 			}
295 
296 			// TODO
297 			// dot product of viewing direction and polygon normal
298 			// will require generation of polygon normal from vertex normals
299 			// and transformation of the normal to world space
300 		}
301 
302 		// Put wireframe triangles in list before textured ones
303 		// so should be in front of textured ones
304 		if ((_drawWfrm) || (selFace == i)) {
305 			LINE_F4 *line = (LINE_F4 *)drawpacket;
306 			setLineF4(line);
307 			// set XY's in the GPU packet 0-1-2-3
308 			line->x0 = sxy0.vx;
309 			line->y0 = sxy0.vy;
310 			line->x1 = sxy1.vx;
311 			line->y1 = sxy1.vy;
312 			line->x2 = sxy2.vx;
313 			line->y2 = sxy2.vy;
314 			line->x3 = sxy0.vx;
315 			line->y3 = sxy0.vy;
316 			if (selFace == i)
317 				setRGB0(line, selWRed, selWGreen, selWBlue);
318 			else
319 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
320 			// Put it into the global ot at the correct place
321 			myAddPrimClip(avgz, drawpacket);
322 			// advance the global packet pointer by correct amount
323 			myAddPacket(sizeof(LINE_F4));
324 		}
325 
326 		// Draw polygon version behind the wireframe
327 		if ((_drawPolys) || (selFace == i)) {
328 			// Draw untextured polygons
329 			POLY_F3 *poly = (POLY_F3 *)drawpacket;
330 			setPolyF3(poly);
331 			// set XY's in the GPU packet 0-1-2
332 			poly->x0 = sxy0.vx;
333 			poly->y0 = sxy0.vy;
334 			poly->x1 = sxy1.vx;
335 			poly->y1 = sxy1.vy;
336 			poly->x2 = sxy2.vx;
337 			poly->y2 = sxy2.vy;
338 
339 			// Set the RGB colours
340 			// No light source calculation
341 			// So just set base colour
342 			if (selFace == i)
343 				setRGB0(poly, selPRed, selPGreen, selPBlue);
344 			else
345 				setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
346 			// Put it into the global ot at the correct place
347 			myAddPrimClip(avgz, drawpacket);
348 			// advance the global packet pointer by correct amount
349 			myAddPacket(sizeof(POLY_F3));
350 		}
351 	}
352 }
353 
354 //------------------------------------------------------------------------
355 
356 // Gouraud, Un-Textured, Self-Luminous, triangles
drawGUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)357 void drawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
358 	SVECTORPC *v0;
359 	SVECTORPC *v1;
360 	SVECTORPC *v2;
361 
362 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
363 	uint32 num = n;
364 	uint32 tmp;
365 	int32 p, flag;
366 	uint32 i;
367 	uint32 *pPoly;
368 	int32 z0, z1, z2;
369 	SVECTORPC sxy0, sxy1, sxy2, stemp;
370 
371 	// Base colour for gouraud shading computation
372 	CVECTOR *rgb0;
373 	CVECTOR *rgb1;
374 	CVECTOR *rgb2;
375 	CVECTOR *rgbTemp;
376 
377 	pPoly = polyStart;
378 	// Loop over each polygon
379 	for (i = 0; i < num; i++) {
380 		// Structure is :
381 		// 8-bits | 8-bits | 8-bits | 8-bits
382 		// 0x30   | Blue0  | Green0 | Red0
383 		// 0x30   | Blue1  | Green1 | Red1
384 		// 0x30   | Blue2  | Green2 | Red2
385 		// 16-bits | 8-bits | 8-bits
386 		// --------------------------
387 		//  v1              | v0
388 		//  pad             | v2
389 		rgb0 = (CVECTOR *)pPoly++;
390 		rgb1 = (CVECTOR *)pPoly++;
391 		rgb2 = (CVECTOR *)pPoly++;
392 
393 		if (deadObject) {
394 			rgb0 = &deadObjectColour;
395 			rgb1 = &deadObjectColour;
396 			rgb2 = &deadObjectColour;
397 		}
398 
399 		tmp = *pPoly++;
400 		v0 = pVertex + (tmp & 0xFFFF);
401 		v1 = pVertex + (tmp >> 16);
402 
403 		tmp = *pPoly++;
404 		v2 = pVertex + (tmp & 0xFFFF);
405 
406 		// Now do RotTransPers3 on the vectors
407 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
408 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
409 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
410 
411 		// test the return value of flag
412 		if (flag & 0x80000000)
413 			continue;
414 
415 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
416 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
417 		// test the return value of flag
418 		if (flag & 0x80000000)
419 			continue;
420 
421 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
422 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
423 		// test the return value of flag
424 		if (flag & 0x80000000)
425 			continue;
426 
427 		// Give the GTE some time to recover
428 		int32 avgz;
429 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
430 
431 		// Do we want to do back face removal ?
432 		if (_removeBackface) {
433 			// use winding order of the polygons
434 			// e.g. NormalClip which is cross product of screen vectors
435 			if (_useWindingOrder) {
436 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
437 				// Drawing back facings polys requires making them have
438 				// clockwise winding order as by definition they have
439 				// anti-clockwise winding order
440 				if (flag < 0) {
441 					if (_drawBface) {
442 						stemp = sxy1;
443 						sxy1 = sxy2;
444 						sxy2 = stemp;
445 						rgbTemp = rgb1;
446 						rgb1 = rgb2;
447 						rgb2 = rgbTemp;
448 					} else {
449 						// Skip this polygon
450 						continue;
451 					}
452 				} else if (flag == 0)
453 					continue; // ignore zero-area polygons
454 			}
455 
456 			// TODO
457 			// dot product of viewing direction and polygon normal
458 			// will require generation of polygon normal from vertex normals
459 			// and transformation of the normal to world space
460 		}
461 
462 		// Put wireframe triangles in list before textured ones
463 		// so should be in front of textured ones
464 		if ((_drawWfrm) || (selFace == i)) {
465 			LINE_F4 *line = (LINE_F4 *)drawpacket;
466 			setLineF4(line);
467 			if (selFace == i)
468 				setRGB0(line, selWRed, selWGreen, selWBlue);
469 			else
470 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
471 			// set XY's in the GPU packet 0-1-2-3
472 			line->x0 = sxy0.vx;
473 			line->y0 = sxy0.vy;
474 			line->x1 = sxy1.vx;
475 			line->y1 = sxy1.vy;
476 			line->x2 = sxy2.vx;
477 			line->y2 = sxy2.vy;
478 			line->x3 = sxy0.vx;
479 			line->y3 = sxy0.vy;
480 			// Put it into the global ot at the correct place
481 			myAddPrimClip(avgz, drawpacket);
482 			// advance the global packet pointer by correct amount
483 			myAddPacket(sizeof(LINE_F4));
484 		}
485 
486 		// Draw textured version behind the wireframe
487 		if ((_drawPolys) || (selFace == i)) {
488 			POLY_G3 *poly = (POLY_G3 *)drawpacket;
489 			// Draw untextured polygons
490 			setPolyG3(poly);
491 			// set XY's in the GPU packet 0-1-2
492 			poly->x0 = sxy0.vx;
493 			poly->y0 = sxy0.vy;
494 			poly->x1 = sxy1.vx;
495 			poly->y1 = sxy1.vy;
496 			poly->x2 = sxy2.vx;
497 			poly->y2 = sxy2.vy;
498 
499 			// No light source calculation
500 			// So just set base colour
501 			if (selFace == i) {
502 				setRGB0(poly, selPRed, selPGreen, selPBlue);
503 				setRGB1(poly, selPRed, selPGreen, selPBlue);
504 				setRGB2(poly, selPRed, selPGreen, selPBlue);
505 			} else {
506 				setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
507 				setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
508 				setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
509 			}
510 			// Put it into the global ot at the correct place
511 			myAddPrimClip(avgz, drawpacket);
512 			// advance the global packet pointer by correct amount
513 			myAddPacket(sizeof(POLY_G3));
514 		}
515 	}
516 }
517 
518 // Flat, Textured, Self-Luminous Triangles
drawFTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)519 void drawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
520 	SVECTORPC *v0;
521 	SVECTORPC *v1;
522 	SVECTORPC *v2;
523 
524 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
525 	uint32 num = n;
526 	uint16 uu0, uu1, uu2;
527 	uint16 vv0, vv1, vv2;
528 	uint32 tmp;
529 	int32 p, flag;
530 	uint32 i;
531 	uint32 *pPoly;
532 	int32 z0, z1, z2;
533 	SVECTORPC sxy0, sxy1, sxy2, stemp;
534 	uint32 uv0, uv1, uv2;
535 
536 	// Base colour for shading computation
537 	// Could easily be specified per polygon
538 	CVECTOR *rgbIn;
539 
540 	pPoly = polyStart;
541 	// Loop over each polygon
542 	for (i = 0; i < num; i++) {
543 		// Structure is :
544 		// Bit 31 ----> Bit 0
545 		//
546 		// 8-bits | 8-bits | 8-bits | 8-bits
547 		// 0x24   | Blue   | Green  | Red
548 		// 16-bits | 16-bits
549 		// --------------------------
550 		// v0      | u0
551 		// v1      | u1
552 		// v2      | u2
553 		// --------------------------
554 		// pad     | v0
555 		//  v2     | v1
556 		rgbIn = (CVECTOR *)pPoly++;
557 
558 		if (deadObject) {
559 			rgbIn = &deadObjectColour;
560 		}
561 
562 		uv0 = *pPoly++;
563 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
564 		uu0 = (uint16)(uv0 & 0xFFFF);
565 
566 		uv1 = *pPoly++;
567 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
568 		uu1 = (uint16)(uv1 & 0xFFFF);
569 
570 		uv2 = *pPoly++;
571 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
572 		uu2 = (uint16)(uv2 & 0xFFFF);
573 
574 		tmp = *pPoly++;
575 		v0 = pVertex + (tmp & 0xFFFF);
576 
577 		tmp = *pPoly++;
578 		v1 = pVertex + (uint)(tmp & 0xFFFF);
579 		v2 = pVertex + (uint)(tmp >> 16);
580 
581 		// Now do RotTransPers3 on the vectors
582 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
583 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
584 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
585 
586 		// test the return value of flag
587 		if (flag & 0x80000000)
588 			continue;
589 
590 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
591 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
592 		// test the return value of flag
593 		if (flag & 0x80000000)
594 			continue;
595 
596 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
597 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
598 		// test the return value of flag
599 		if (flag & 0x80000000)
600 			continue;
601 
602 		// Give the GTE some time to recover
603 		int32 avgz;
604 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
605 
606 		// Do we want to do back face removal ?
607 		if (_removeBackface) {
608 			// use winding order of the polygons
609 			// e.g. NormalClip which is cross product of screen vectors
610 			if (_useWindingOrder) {
611 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
612 				// Drawing back facings polys requires making them have
613 				// clockwise winding order as by definition they have
614 				// anti-clockwise winding order
615 				if (flag < 0) {
616 					if (_drawBface) {
617 						stemp = sxy1;
618 						sxy1 = sxy2;
619 						sxy2 = stemp;
620 						flag = uv1;
621 						uv1 = uv2;
622 						uv2 = flag;
623 					} else {
624 						// Skip this polygon
625 						continue;
626 					}
627 				} else if (flag == 0)
628 					continue; // ignore zero-area polygons
629 			}
630 
631 			// TODO
632 			// dot product of viewing direction and polygon normal
633 			// will require generation of polygon normal from vertex normals
634 			// and transformation of the normal to world space
635 		}
636 
637 		// Put wireframe triangles in list before textured ones
638 		// so should be in front of textured ones
639 		if ((_drawWfrm) || (selFace == i)) {
640 			LINE_F4 *line = (LINE_F4 *)drawpacket;
641 			setLineF4(line);
642 			if (selFace == i)
643 				setRGB0(line, selWRed, selWGreen, selWBlue);
644 			else
645 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
646 			// set XY's in the GPU packet 0-1-2-3
647 			line->x0 = sxy0.vx;
648 			line->y0 = sxy0.vy;
649 			line->x1 = sxy1.vx;
650 			line->y1 = sxy1.vy;
651 			line->x2 = sxy2.vx;
652 			line->y2 = sxy2.vy;
653 			line->x3 = sxy0.vx;
654 			line->y3 = sxy0.vy;
655 			// Put it into the global ot at the correct place
656 			myAddPrimClip(avgz, drawpacket);
657 			// advance the global packet pointer by correct amount
658 			myAddPacket(sizeof(LINE_F4));
659 		}
660 
661 		// Draw textured version behind the wireframe
662 		if ((_drawPolys) || (selFace == i)) {
663 			if (_drawTxture) {
664 				POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
665 				setPolyFT3(poly);
666 				// set XY's in the GPU packet 0-1-2
667 				poly->x0 = sxy0.vx;
668 				poly->y0 = sxy0.vy;
669 				poly->x1 = sxy1.vx;
670 				poly->y1 = sxy1.vy;
671 				poly->x2 = sxy2.vx;
672 				poly->y2 = sxy2.vy;
673 
674 				setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
675 
676 				// No light source calculation
677 				// So just set base colour
678 				if (selFace == i)
679 					setRGB0(poly, selPRed, selPGreen, selPBlue);
680 				else
681 					setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
682 
683 				// Put it into the global ot at the correct place
684 				myAddPrimClip(avgz, drawpacket);
685 				// advance the global packet pointer by correct amount
686 				myAddPacket(sizeof(POLY_FT3));
687 			} else {
688 				// Set the RGB colours
689 				POLY_F3 *poly = (POLY_F3 *)drawpacket;
690 				// Draw untextured polygons
691 				setPolyF3(poly);
692 				// set XY's in the GPU packet 0-1-2
693 				poly->x0 = sxy0.vx;
694 				poly->y0 = sxy0.vy;
695 				poly->x1 = sxy1.vx;
696 				poly->y1 = sxy1.vy;
697 				poly->x2 = sxy2.vx;
698 				poly->y2 = sxy2.vy;
699 
700 				// No light source calculation
701 				// So just set base colour
702 				if (selFace == i)
703 					setRGB0(poly, selPRed, selPGreen, selPBlue);
704 				else
705 					setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
706 				// Put it into the global ot at the correct place
707 				myAddPrimClip(avgz, drawpacket);
708 				// advance the global packet pointer by correct amount
709 				myAddPacket(sizeof(POLY_F3));
710 			}
711 		}
712 	}
713 }
714 
715 // Gouraud, Textured, Self-Luminous Triangles
drawGTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)716 void drawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
717 	SVECTORPC *v0;
718 	SVECTORPC *v1;
719 	SVECTORPC *v2;
720 
721 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
722 	uint32 num = n;
723 	uint16 uu0, uu1, uu2;
724 	uint16 vv0, vv1, vv2;
725 	uint32 tmp;
726 	int32 p, flag;
727 	uint32 i;
728 	uint32 *pPoly;
729 	int32 z0, z1, z2;
730 	SVECTORPC sxy0, sxy1, sxy2, stemp;
731 	uint32 uv0, uv1, uv2;
732 
733 	// gouraud colours
734 	CVECTOR *rgb0;
735 	CVECTOR *rgb1;
736 	CVECTOR *rgb2;
737 	CVECTOR *rgbTemp;
738 
739 	pPoly = polyStart;
740 	// Loop over each polygon
741 	for (i = 0; i < num; i++) {
742 		// Structure is :
743 		// 8-bits | 8-bits | 8-bits | 8-bits
744 		// 0x34   | Blue0  | Green0 | Red0
745 		// 0x34   | Blue1  | Green1 | Red1
746 		// 0x34   | Blue2  | Green2 | Red2
747 		// 16-bits | 16-bits
748 		// --------------------------
749 		// v0      | u0
750 		// v1      | u1
751 		// v2      | u2
752 		// --------------------------
753 		// pad     | v0
754 		//  v2     | v1
755 		rgb0 = (CVECTOR *)pPoly++;
756 		rgb1 = (CVECTOR *)pPoly++;
757 		rgb2 = (CVECTOR *)pPoly++;
758 
759 		if (deadObject) {
760 			rgb0 = &deadObjectColour;
761 			rgb1 = &deadObjectColour;
762 			rgb2 = &deadObjectColour;
763 		}
764 
765 		uv0 = *pPoly++;
766 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
767 		uu0 = (uint16)(uv0 & 0xFFFF);
768 
769 		uv1 = *pPoly++;
770 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
771 		uu1 = (uint16)(uv1 & 0xFFFF);
772 
773 		uv2 = *pPoly++;
774 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
775 		uu2 = (uint16)(uv2 & 0xFFFF);
776 
777 		tmp = *pPoly++;
778 		v0 = pVertex + (tmp & 0xFFFF);
779 
780 		tmp = *pPoly++;
781 		v1 = pVertex + (tmp & 0xFFFF);
782 		v2 = pVertex + (tmp >> 16);
783 
784 		// Now do RotTransPers3 on the vectors
785 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
786 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
787 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
788 
789 		// test the return value of flag
790 		if (flag & 0x80000000)
791 			continue;
792 
793 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
794 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
795 		// test the return value of flag
796 		if (flag & 0x80000000)
797 			continue;
798 
799 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
800 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
801 		// test the return value of flag
802 		if (flag & 0x80000000)
803 			continue;
804 
805 		// Give the GTE some time to recover
806 		int32 avgz;
807 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
808 
809 		// Do we want to do back face removal ?
810 		if (_removeBackface) {
811 			// use winding order of the polygons
812 			// e.g. NormalClip which is cross product of screen vectors
813 			if (_useWindingOrder) {
814 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
815 				// Drawing back facings polys requires making them have
816 				// clockwise winding order as by definition they have
817 				// anti-clockwise winding order
818 				if (flag < 0) {
819 					if (_drawBface) {
820 						stemp = sxy1;
821 						sxy1 = sxy2;
822 						sxy2 = stemp;
823 						rgbTemp = rgb1;
824 						rgb1 = rgb2;
825 						rgb2 = rgbTemp;
826 						flag = uv1;
827 						uv1 = uv2;
828 						uv2 = flag;
829 					} else {
830 						// Skip this polygon
831 						continue;
832 					}
833 				} else if (flag == 0)
834 					continue; // ignore zero-area polygons
835 			}
836 
837 			// TODO
838 			// dot product of viewing direction and polygon normal
839 			// will require generation of polygon normal from vertex normals
840 			// and transformation of the normal to world space
841 		}
842 
843 		// Put wireframe triangles in list before textured ones
844 		// so should be in front of textured ones
845 		if ((_drawWfrm) || (selFace == i)) {
846 			LINE_F4 *line = (LINE_F4 *)drawpacket;
847 			setLineF4(line);
848 			if (selFace == i)
849 				setRGB0(line, selWRed, selWGreen, selWBlue);
850 			else
851 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
852 			// set XY's in the GPU packet 0-1-2-3
853 			line->x0 = sxy0.vx;
854 			line->y0 = sxy0.vy;
855 			line->x1 = sxy1.vx;
856 			line->y1 = sxy1.vy;
857 			line->x2 = sxy2.vx;
858 			line->y2 = sxy2.vy;
859 			line->x3 = sxy0.vx;
860 			line->y3 = sxy0.vy;
861 
862 			// Put it into the global ot at the correct place
863 			myAddPrimClip(avgz, drawpacket);
864 			// advance the global packet pointer by correct amount
865 			myAddPacket(sizeof(LINE_F4));
866 		}
867 
868 		// Draw textured version behind the wireframe
869 		if ((_drawPolys) || (selFace == i)) {
870 			if (_drawTxture) {
871 				// Set the RGB colours
872 				POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
873 				setPolyGT3(poly);
874 				// set XY's in the GPU packet 0-1-2
875 				poly->x0 = sxy0.vx;
876 				poly->y0 = sxy0.vy;
877 				poly->x1 = sxy1.vx;
878 				poly->y1 = sxy1.vy;
879 				poly->x2 = sxy2.vx;
880 				poly->y2 = sxy2.vy;
881 
882 				setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
883 
884 				// No light source calculation
885 				// So just set base colour
886 				if (selFace == i) {
887 					setRGB0(poly, selPRed, selPGreen, selPBlue);
888 					setRGB1(poly, selPRed, selPGreen, selPBlue);
889 					setRGB2(poly, selPRed, selPGreen, selPBlue);
890 				} else {
891 					setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
892 					setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
893 					setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
894 				}
895 
896 				// Put it into the global ot at the correct place
897 				myAddPrimClip(avgz, drawpacket);
898 				// advance the global packet pointer by correct amount
899 				myAddPacket(sizeof(POLY_GT3));
900 			} else {
901 				// Set the RGB colours
902 				POLY_G3 *poly = (POLY_G3 *)drawpacket;
903 				// Draw untextured polygons
904 				setPolyG3(poly);
905 				// set XY's in the GPU packet 0-1-2
906 				poly->x0 = sxy0.vx;
907 				poly->y0 = sxy0.vy;
908 				poly->x1 = sxy1.vx;
909 				poly->y1 = sxy1.vy;
910 				poly->x2 = sxy2.vx;
911 				poly->y2 = sxy2.vy;
912 
913 				// No light source calculation
914 				// So just set base colour
915 				if (selFace == i) {
916 					setRGB0(poly, selPRed, selPGreen, selPBlue);
917 					setRGB1(poly, selPRed, selPGreen, selPBlue);
918 					setRGB2(poly, selPRed, selPGreen, selPBlue);
919 				} else {
920 					setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
921 					setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
922 					setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
923 				}
924 
925 				// Put it into the global ot at the correct place
926 				myAddPrimClip(avgz, drawpacket);
927 				// advance the global packet pointer by correct amount
928 				myAddPacket(sizeof(POLY_G3));
929 			}
930 		}
931 	}
932 }
933 
934 // Flat, Un-Textured, Lit, triangles
drawFUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)935 void drawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
936 	SVECTOR *n0;
937 	SVECTORPC *v0;
938 	SVECTORPC *v1;
939 	SVECTORPC *v2;
940 
941 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
942 	uint32 num = n;
943 	int32 p, flag;
944 	uint32 i;
945 	uint32 *pPoly;
946 	int32 z0, z1, z2;
947 	SVECTORPC sxy0, sxy1, sxy2, stemp;
948 	SVECTORPC sxyn0;
949 	SVECTORPC sn0;
950 	CVECTOR *rgbIn;
951 	CVECTOR rgb0 = {0, 0, 0, 0};
952 	uint32 tmp;
953 	uint8 ctmp;
954 
955 	pPoly = polyStart;
956 	// Loop over each polygon
957 	for (i = 0; i < num; i++) {
958 		// Structure is :
959 		// 0x20 | B | G | R
960 		// v0       | n0
961 		// v2       | v1
962 		rgbIn = (CVECTOR *)pPoly++;
963 
964 		tmp = *pPoly++;
965 		v0 = pVertex + (tmp >> 16);
966 		n0 = pNormal + (tmp & 0xFFFF);
967 
968 		tmp = *pPoly++;
969 		v2 = pVertex + (tmp >> 16);
970 		v1 = pVertex + (tmp & 0xFFFF);
971 
972 		// Now do RotTransPers3 on the vectors
973 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
974 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
975 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
976 
977 		// test the return value of flag
978 		if (flag & 0x80000000)
979 			continue;
980 
981 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
982 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
983 		// test the return value of flag
984 		if (flag & 0x80000000)
985 			continue;
986 
987 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
988 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
989 		// test the return value of flag
990 		if (flag & 0x80000000)
991 			continue;
992 
993 		// Give the GTE some time to recover
994 		int32 avgz;
995 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
996 
997 		// Do we want to do back face removal ?
998 		if (_removeBackface) {
999 			// use winding order of the polygons
1000 			// e.g. NormalClip which is cross product of screen vectors
1001 			if (_useWindingOrder) {
1002 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1003 				// Drawing back facings polys requires making them have
1004 				// clockwise winding order as by definition they have
1005 				// anti-clockwise winding order
1006 				if (flag < 0) {
1007 					if (_drawBface) {
1008 						stemp = sxy1;
1009 						sxy1 = sxy2;
1010 						sxy2 = stemp;
1011 					} else {
1012 						// Skip this polygon
1013 						continue;
1014 					}
1015 				} else if (flag == 0)
1016 					continue; // ignore zero-area polygons
1017 			}
1018 
1019 			// TODO
1020 			// dot product of viewing direction and polygon normal
1021 			// will require generation of polygon normal from vertex normals
1022 			// and transformation of the normal to world space
1023 		}
1024 
1025 		// Set the RGB colours
1026 		if (_drawLit) {
1027 			// Do the flat lighting computation
1028 			LIGHTPOLYGON(n0, rgbIn, &rgb0);
1029 		}
1030 
1031 		// Put normal lines in list before wireframe
1032 		// so should be drawn in front of wireframe triangles
1033 		if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1034 			// Do coord transform on the scaled normal vectors + v0
1035 			sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1036 			sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1037 			sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1038 			// z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
1039 			gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
1040 			// Normal 0 : scale the normal and add to vertex scrn pos
1041 			LINE_G2 *line = (LINE_G2 *)drawpacket;
1042 			setLineG2(line);
1043 			line->x0 = sxy0.vx;
1044 			line->y0 = sxy0.vy;
1045 			line->x1 = sxyn0.vx;
1046 			line->y1 = sxyn0.vy;
1047 			if (selFace == i) {
1048 				// from bright red
1049 				setRGB0(line, 255, 0, 0);
1050 				// to bright white
1051 				setRGB1(line, 255, 255, 255);
1052 			} else {
1053 				// from bright blue
1054 				setRGB0(line, 0, 0, 255);
1055 				// to bright white
1056 				setRGB1(line, 255, 255, 255);
1057 			}
1058 			// Put it into the global ot at the correct place
1059 			myAddPrimClip(avgz, drawpacket);
1060 			// advance the global packet pointer by correct amount
1061 			myAddPacket(sizeof(LINE_G2));
1062 		}
1063 
1064 		// Put wireframe triangles in list before textured ones
1065 		// so should be in front of textured ones
1066 		if ((_drawWfrm) || (selFace == i)) {
1067 			LINE_F4 *line = (LINE_F4 *)drawpacket;
1068 			setLineF4(line);
1069 			// set XY's in the GPU packet 0-1-2-3
1070 			line->x0 = sxy0.vx;
1071 			line->y0 = sxy0.vy;
1072 			line->x1 = sxy1.vx;
1073 			line->y1 = sxy1.vy;
1074 			line->x2 = sxy2.vx;
1075 			line->y2 = sxy2.vy;
1076 			line->x3 = sxy0.vx;
1077 			line->y3 = sxy0.vy;
1078 			// Draw a wireframe that responds to lighting
1079 			if (_drawLit) {
1080 				int32 cval;
1081 				// Compute the colour scaling and clip it
1082 				// Flat shading so give the same colour to each vertex
1083 				if (rgbIn->r != 0) {
1084 					cval = ((wfrmRed * rgb0.r) / rgbIn->r);
1085 					if (cval > 255)
1086 						cval = 255;
1087 					ctmp = (uint8)cval;
1088 				} else
1089 					ctmp = 0;
1090 				line->r0 = ctmp;
1091 
1092 				if (rgbIn->g != 0) {
1093 					cval = ((wfrmGreen * rgb0.g) / rgbIn->g);
1094 					if (cval > 255)
1095 						cval = 255;
1096 					ctmp = (uint8)cval;
1097 				} else
1098 					ctmp = 0;
1099 				line->g0 = ctmp;
1100 
1101 				if (rgbIn->b != 0) {
1102 					cval = ((wfrmBlue * rgb0.b) / rgbIn->b);
1103 					if (cval > 255)
1104 						cval = 255;
1105 					ctmp = (uint8)cval;
1106 				} else
1107 					ctmp = 0;
1108 				line->b0 = ctmp;
1109 			} else {
1110 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1111 			}
1112 			if (selFace == i)
1113 				setRGB0(line, selWRed, selWGreen, selWBlue);
1114 
1115 			// Put it into the global ot at the correct place
1116 			myAddPrimClip(avgz, drawpacket);
1117 			// advance the global packet pointer by correct amount
1118 			myAddPacket(sizeof(LINE_F4));
1119 		}
1120 
1121 		// Draw polygon version behind the wireframe
1122 		if ((_drawPolys) || (selFace == i)) {
1123 			// Draw untextured polygons
1124 			POLY_F3 *poly = (POLY_F3 *)drawpacket;
1125 			setPolyF3(poly);
1126 			// set XY's in the GPU packet 0-1-2
1127 			poly->x0 = sxy0.vx;
1128 			poly->y0 = sxy0.vy;
1129 			poly->x1 = sxy1.vx;
1130 			poly->y1 = sxy1.vy;
1131 			poly->x2 = sxy2.vx;
1132 			poly->y2 = sxy2.vy;
1133 
1134 			// Set the RGB colours
1135 			if (_drawLit) {
1136 				// Flat shaded so give each vertex the same colour
1137 				setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1138 			} else {
1139 				// No light source calculation
1140 				// So just set base colour
1141 				setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
1142 			}
1143 			if (selFace == i) {
1144 				setRGB0(poly, selPRed, selPGreen, selPBlue);
1145 			}
1146 			// Put it into the global ot at the correct place
1147 			myAddPrimClip(avgz, drawpacket);
1148 			// advance the global packet pointer by correct amount
1149 			myAddPacket(sizeof(POLY_F3));
1150 		}
1151 	}
1152 }
1153 
1154 // Gouraud, Un-Textured, Lit, triangles
drawGUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1155 void drawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1156 	SVECTOR *n0;
1157 	SVECTOR *n1;
1158 	SVECTOR *n2;
1159 	SVECTORPC *v0;
1160 	SVECTORPC *v1;
1161 	SVECTORPC *v2;
1162 	SVECTOR *ntemp;
1163 
1164 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1165 	uint32 num = n;
1166 	uint32 tmp;
1167 	uint8 ctmp;
1168 	int32 p, flag;
1169 	uint32 i;
1170 	uint32 *pPoly;
1171 	int32 z0, z1, z2;
1172 	SVECTORPC sxy0, sxy1, sxy2, stemp;
1173 	SVECTORPC sxyn0, sxyn1, sxyn2;
1174 	SVECTORPC sn0, sn1, sn2;
1175 
1176 	// Base colour for gouraud shading computation
1177 	// Could easily be specified per polygon
1178 	CVECTOR rgbIn;
1179 	CVECTOR rgb0 = {0, 0, 0, 0};
1180 	CVECTOR rgb1 = {0, 0, 0, 0};
1181 	CVECTOR rgb2 = {0, 0, 0, 0};
1182 
1183 	pPoly = polyStart;
1184 	// Loop over each polygon
1185 	for (i = 0; i < num; i++) {
1186 		// Structure is :
1187 		// 8-bits | 8-bits | 8-bits | 8-bits
1188 		// 0x20   | Blue   | Green  | Red
1189 		// 16-bits | 8-bits | 8-bits
1190 		// --------------------------
1191 		//  v0              | n0
1192 		//  v1              | n1
1193 		//  v2              | n2
1194 		tmp = *pPoly++;
1195 		// code0 = tmp >> 24;
1196 		rgbIn.r = (uint8)(tmp & 0xFF);
1197 		rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
1198 		rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
1199 
1200 		tmp = *pPoly++;
1201 		v0 = pVertex + (tmp >> 16);
1202 		n0 = pNormal + (tmp & 0xFFFF);
1203 
1204 		tmp = *pPoly++;
1205 		v1 = pVertex + (tmp >> 16);
1206 		n1 = pNormal + (tmp & 0xFFFF);
1207 
1208 		tmp = *pPoly++;
1209 		v2 = pVertex + (tmp >> 16);
1210 		n2 = pNormal + (tmp & 0xFFFF);
1211 
1212 		// Now do RotTransPers3 on the vectors
1213 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
1214 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
1215 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1216 
1217 		// test the return value of flag
1218 		if (flag & 0x80000000)
1219 			continue;
1220 
1221 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
1222 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1223 		// test the return value of flag
1224 		if (flag & 0x80000000)
1225 			continue;
1226 
1227 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
1228 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1229 		// test the return value of flag
1230 		if (flag & 0x80000000)
1231 			continue;
1232 
1233 		// Give the GTE some time to recover
1234 		int32 avgz;
1235 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
1236 
1237 		// Do we want to do back face removal ?
1238 		if (_removeBackface) {
1239 			// use winding order of the polygons
1240 			// e.g. NormalClip which is cross product of screen vectors
1241 			if (_useWindingOrder) {
1242 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1243 				// Drawing back facings polys requires making them have
1244 				// clockwise winding order as by definition they have
1245 				// anti-clockwise winding order
1246 				if (flag < 0) {
1247 					if (_drawBface) {
1248 						stemp = sxy1;
1249 						sxy1 = sxy2;
1250 						sxy2 = stemp;
1251 						ntemp = n1;
1252 						n1 = n2;
1253 						n2 = ntemp;
1254 					} else {
1255 						// Skip this polygon
1256 						continue;
1257 					}
1258 				} else if (flag == 0)
1259 					continue; // ignore zero-area polygons
1260 			}
1261 
1262 			// TODO
1263 			// dot product of viewing direction and polygon normal
1264 			// will require generation of polygon normal from vertex normals
1265 			// and transformation of the normal to world space
1266 		}
1267 
1268 		// Set the RGB colours
1269 		if (_drawLit) {
1270 			// Do the full gouraud computation
1271 			// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
1272 			LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
1273 
1274 			int32 cval;
1275 
1276 			if (!_drawGouraud) {
1277 				// For flat shading mode take the average RGB for the face
1278 				// Could/should use something like AVSZ3
1279 				// but hell whats a divide by 3 between friends (~30 cycles?)
1280 				cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
1281 				if (cval > 255)
1282 					cval = 255;
1283 				rgb0.r = (uint8)cval;
1284 
1285 				cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
1286 				if (cval > 255)
1287 					cval = 255;
1288 				rgb0.g = (uint8)cval;
1289 
1290 				cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
1291 				if (cval > 255)
1292 					cval = 255;
1293 				rgb0.b = (uint8)cval;
1294 			}
1295 		} else {
1296 			rgbIn.r = unlitPoly.r;
1297 			rgbIn.g = unlitPoly.g;
1298 			rgbIn.b = unlitPoly.b;
1299 		}
1300 
1301 		// Put normal lines in list before wireframe
1302 		// so should be drawn in front of wireframe triangles
1303 		if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1304 			// Do coord transform on the scaled normal vectors + v0
1305 			sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1306 			sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1307 			sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1308 			sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
1309 			sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
1310 			sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
1311 			sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
1312 			sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
1313 			sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
1314 
1315 			// z0 = RotTransPers3( &sn0, &sn1, &sn2,
1316 			//                    &sxyn0, &sxyn1, &sxyn2, &p, &flag );
1317 			gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
1318 			// Normal 0
1319 			LINE_G2 *line = (LINE_G2 *)drawpacket;
1320 			setLineG2(line);
1321 			line->x0 = sxy0.vx;
1322 			line->y0 = sxy0.vy;
1323 			line->x1 = sxy1.vx;
1324 			line->y1 = sxy1.vy;
1325 			if (selFace == i) {
1326 				// Bright red
1327 				setRGB0(line, 255, 0, 0);
1328 				// Bright white
1329 				setRGB1(line, 255, 255, 255);
1330 			} else {
1331 				// Bright blue
1332 				setRGB0(line, 0, 0, 255);
1333 				// Bright white
1334 				setRGB1(line, 255, 255, 255);
1335 			}
1336 			// Put it into the global ot at the correct place
1337 			myAddPrimClip(avgz, drawpacket);
1338 			// advance the global packet pointer by correct amount
1339 			myAddPacket(sizeof(LINE_G2));
1340 
1341 			// Normal 1
1342 			line = (LINE_G2 *)drawpacket;
1343 			setLineG2(line);
1344 			line->x0 = sxy0.vx;
1345 			line->y0 = sxy0.vy;
1346 			line->x1 = sxyn1.vx;
1347 			line->y1 = sxyn1.vy;
1348 			if (selFace == i) {
1349 				// Bright red
1350 				setRGB0(line, 255, 0, 0);
1351 				// Bright white
1352 				setRGB1(line, 255, 255, 255);
1353 			} else {
1354 				// Bright blue
1355 				setRGB0(line, 0, 0, 255);
1356 				// Bright white
1357 				setRGB1(line, 255, 255, 255);
1358 			}
1359 			// Put it into the global ot at the correct place
1360 			myAddPrimClip(avgz, drawpacket);
1361 			// advance the global packet pointer by correct amount
1362 			myAddPacket(sizeof(LINE_G2));
1363 
1364 			// Normal 2
1365 			line = (LINE_G2 *)drawpacket;
1366 			setLineG2(line);
1367 			line->x0 = sxy0.vx;
1368 			line->y0 = sxy0.vy;
1369 			line->x1 = sxyn2.vx;
1370 			line->y1 = sxyn2.vy;
1371 			if (selFace == i) {
1372 				// Bright red
1373 				setRGB0(line, 255, 0, 0);
1374 				// Bright white
1375 				setRGB1(line, 255, 255, 255);
1376 			} else {
1377 				// Bright blue
1378 				setRGB0(line, 0, 0, 255);
1379 				// Bright white
1380 				setRGB1(line, 255, 255, 255);
1381 			}
1382 			// Put it into the global ot at the correct place
1383 			myAddPrimClip(avgz, drawpacket);
1384 			// advance the global packet pointer by correct amount
1385 			myAddPacket(sizeof(LINE_G2));
1386 		}
1387 
1388 		// Put wireframe triangles in list before textured ones
1389 		// so should be in front of textured ones
1390 		if ((_drawWfrm) || (selFace == i)) {
1391 			// Draw a wireframe that responds to lighting
1392 			if (_drawLit) {
1393 				LINE_G4 *line = (LINE_G4 *)drawpacket;
1394 				setLineG4(line);
1395 				int32 cval;
1396 				if (_drawGouraud) {
1397 					// Give each vertex a seperate colour
1398 					// Compute the colour scaling and clip it
1399 					if (rgbIn.r != 0) {
1400 						cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1401 						if (cval > 255)
1402 							cval = 255;
1403 						ctmp = (uint8)cval;
1404 						line->r0 = ctmp;
1405 						line->r3 = ctmp;
1406 
1407 						cval = ((wfrmRed * rgb1.r) / rgbIn.r);
1408 						if (cval > 255)
1409 							cval = 255;
1410 						ctmp = (uint8)cval;
1411 						line->r1 = ctmp;
1412 
1413 						cval = ((wfrmRed * rgb2.r) / rgbIn.r);
1414 						if (cval > 255)
1415 							cval = 255;
1416 						ctmp = (uint8)cval;
1417 						line->r2 = ctmp;
1418 					} else {
1419 						line->r0 = 0;
1420 						line->r3 = 0;
1421 						line->r1 = 0;
1422 						line->r2 = 0;
1423 					}
1424 
1425 					if (rgbIn.g != 0) {
1426 						cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1427 						if (cval > 255)
1428 							cval = 255;
1429 						ctmp = (uint8)cval;
1430 						line->g0 = ctmp;
1431 						line->g3 = ctmp;
1432 
1433 						cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
1434 						if (cval > 255)
1435 							cval = 255;
1436 						ctmp = (uint8)cval;
1437 						line->g1 = ctmp;
1438 
1439 						cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
1440 						if (cval > 255)
1441 							cval = 255;
1442 						ctmp = (uint8)cval;
1443 						line->g2 = ctmp;
1444 					} else {
1445 						line->g0 = 0;
1446 						line->g3 = 0;
1447 						line->g1 = 0;
1448 						line->g2 = 0;
1449 					}
1450 					if (rgbIn.b != 0) {
1451 						cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1452 						if (cval > 255)
1453 							cval = 255;
1454 						ctmp = (uint8)cval;
1455 						line->b0 = ctmp;
1456 						line->b3 = ctmp;
1457 
1458 						cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
1459 						if (cval > 255)
1460 							cval = 255;
1461 						ctmp = (uint8)cval;
1462 						line->b1 = ctmp;
1463 
1464 						cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
1465 						if (cval > 255)
1466 							cval = 255;
1467 						ctmp = (uint8)cval;
1468 						line->b2 = ctmp;
1469 					} else {
1470 						line->b0 = 0;
1471 						line->b3 = 0;
1472 						line->b1 = 0;
1473 						line->b2 = 0;
1474 					}
1475 				} else {
1476 					// Compute the colour scaling and clip it
1477 					// Flat shading so give the same colour to each vertex
1478 					if (rgbIn.r != 0) {
1479 						cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1480 						if (cval > 255)
1481 							cval = 255;
1482 						ctmp = (uint8)cval;
1483 					} else
1484 						ctmp = 0;
1485 					line->r0 = ctmp;
1486 					line->r1 = ctmp;
1487 					line->r2 = ctmp;
1488 					line->r3 = ctmp;
1489 
1490 					if (rgbIn.g != 0) {
1491 						cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1492 						if (cval > 255)
1493 							cval = 255;
1494 						ctmp = (uint8)cval;
1495 					} else
1496 						ctmp = 0;
1497 					line->g0 = ctmp;
1498 					line->g1 = ctmp;
1499 					line->g2 = ctmp;
1500 					line->g3 = ctmp;
1501 
1502 					if (rgbIn.b != 0) {
1503 						cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1504 						if (cval > 255)
1505 							cval = 255;
1506 						ctmp = (uint8)cval;
1507 					} else
1508 						ctmp = 0;
1509 
1510 					line->b0 = ctmp;
1511 					line->b1 = ctmp;
1512 					line->b2 = ctmp;
1513 					line->b3 = ctmp;
1514 				}
1515 				if (selFace == i) {
1516 					setRGB0(line, selWRed, selWGreen, selWBlue);
1517 					setRGB1(line, selWRed, selWGreen, selWBlue);
1518 					setRGB2(line, selWRed, selWGreen, selWBlue);
1519 					setRGB3(line, selWRed, selWGreen, selWBlue);
1520 				}
1521 
1522 				// set XY's in the GPU packet 0-1-2-3
1523 				line->x0 = sxy0.vx;
1524 				line->y0 = sxy0.vy;
1525 				line->x1 = sxy1.vx;
1526 				line->y1 = sxy1.vy;
1527 				line->x2 = sxy2.vx;
1528 				line->y2 = sxy2.vy;
1529 				line->x3 = sxy0.vx;
1530 				line->y3 = sxy0.vy;
1531 				// Put it into the global ot at the correct place
1532 				myAddPrimClip(avgz, drawpacket);
1533 				// advance the global packet pointer by correct amount
1534 				myAddPacket(sizeof(LINE_G4));
1535 			} else {
1536 				LINE_F4 *line = (LINE_F4 *)drawpacket;
1537 				setLineF4(line);
1538 				if (selFace == i)
1539 					setRGB0(line, selWRed, selWGreen, selWBlue);
1540 				else
1541 					setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1542 				// set XY's in the GPU packet 0-1-2-3
1543 				line->x0 = sxy0.vx;
1544 				line->y0 = sxy0.vy;
1545 				line->x1 = sxy1.vx;
1546 				line->y1 = sxy1.vy;
1547 				line->x2 = sxy2.vx;
1548 				line->y2 = sxy2.vy;
1549 				line->x3 = sxy0.vx;
1550 				line->y3 = sxy0.vy;
1551 				// Put it into the global ot at the correct place
1552 				myAddPrimClip(avgz, drawpacket);
1553 				// advance the global packet pointer by correct amount
1554 				myAddPacket(sizeof(LINE_F4));
1555 			}
1556 		}
1557 
1558 		// Draw textured version behind the wireframe
1559 		if ((_drawPolys) || (selFace == i)) {
1560 			// Set the RGB colours
1561 			if (_drawLit) {
1562 				if (_drawGouraud) {
1563 					POLY_G3 *poly = (POLY_G3 *)drawpacket;
1564 					// Draw untextured polygons
1565 					setPolyG3(poly);
1566 					// set XY's in the GPU packet 0-1-2
1567 					poly->x0 = sxy0.vx;
1568 					poly->y0 = sxy0.vy;
1569 					poly->x1 = sxy1.vx;
1570 					poly->y1 = sxy1.vy;
1571 					poly->x2 = sxy2.vx;
1572 					poly->y2 = sxy2.vy;
1573 
1574 					if (selFace == i) {
1575 						setRGB0(poly, selPRed, selPGreen, selPBlue);
1576 						setRGB1(poly, selPRed, selPGreen, selPBlue);
1577 						setRGB2(poly, selPRed, selPGreen, selPBlue);
1578 					} else {
1579 						setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1580 						setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
1581 						setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
1582 					}
1583 
1584 					// Put it into the global ot at the correct place
1585 					myAddPrimClip(avgz, drawpacket);
1586 					// advance the global packet pointer by correct amount
1587 					myAddPacket(sizeof(POLY_G3));
1588 				} else {
1589 					POLY_F3 *poly = (POLY_F3 *)drawpacket;
1590 					// Draw untextured polygons
1591 					setPolyF3(poly);
1592 					// set XY's in the GPU packet 0-1-2
1593 					poly->x0 = sxy0.vx;
1594 					poly->y0 = sxy0.vy;
1595 					poly->x1 = sxy1.vx;
1596 					poly->y1 = sxy1.vy;
1597 					poly->x2 = sxy2.vx;
1598 					poly->y2 = sxy2.vy;
1599 
1600 					// Flat shaded so give each vertex the same colour
1601 					setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1602 
1603 					// Put it into the global ot at the correct place
1604 					myAddPrimClip(avgz, drawpacket);
1605 					// advance the global packet pointer by correct amount
1606 					myAddPacket(sizeof(POLY_F3));
1607 				}
1608 			} else {
1609 				POLY_F3 *poly = (POLY_F3 *)drawpacket;
1610 				// Draw untextured polygons
1611 				setPolyF3(poly);
1612 				// set XY's in the GPU packet 0-1-2
1613 				poly->x0 = sxy0.vx;
1614 				poly->y0 = sxy0.vy;
1615 				poly->x1 = sxy1.vx;
1616 				poly->y1 = sxy1.vy;
1617 				poly->x2 = sxy2.vx;
1618 				poly->y2 = sxy2.vy;
1619 
1620 				// No light source calculation
1621 				// So just set base colour
1622 				setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
1623 				// Put it into the global ot at the correct place
1624 				myAddPrimClip(avgz, drawpacket);
1625 				// advance the global packet pointer by correct amount
1626 				myAddPacket(sizeof(POLY_F3));
1627 			}
1628 		}
1629 	}
1630 }
1631 
1632 // Flat, Textured, Lit Triangles
drawFTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1633 void drawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1634 	SVECTOR *n0;
1635 	SVECTORPC *v0;
1636 	SVECTORPC *v1;
1637 	SVECTORPC *v2;
1638 
1639 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1640 	uint32 num = n;
1641 	uint16 uu0, uu1, uu2;
1642 	uint16 vv0, vv1, vv2;
1643 	uint32 tmp;
1644 	uint8 ctmp;
1645 	int32 p, flag;
1646 	uint32 i;
1647 	uint32 *pPoly;
1648 	int32 z0, z1, z2;
1649 	SVECTORPC sxy0, sxy1, sxy2, stemp;
1650 	SVECTORPC sxyn0;
1651 	SVECTORPC sn0;
1652 	uint32 uv0, uv1, uv2;
1653 
1654 	// Base colour for shading computation
1655 	// Could easily be specified per polygon
1656 	CVECTOR rgbIn = {128, 128, 128, 0};
1657 	CVECTOR rgb0 = {0, 0, 0, 0};
1658 
1659 	pPoly = polyStart;
1660 	// Loop over each polygon
1661 	for (i = 0; i < num; i++) {
1662 		// Structure is :
1663 		// Bit 31 ----> Bit 0
1664 		//
1665 		// 16-bits | 16-bits
1666 		// --------------------------
1667 		// v0      | u0
1668 		// v1      | u1
1669 		// v2      | u2
1670 		// --------------------------
1671 		//  v0              | n0
1672 		//  v2              | v1
1673 		uv0 = *pPoly++;
1674 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
1675 		uu0 = (uint16)(uv0 & 0xFFFF);
1676 
1677 		uv1 = *pPoly++;
1678 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
1679 		uu1 = (uint16)(uv1 & 0xFFFF);
1680 
1681 		uv2 = *pPoly++;
1682 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
1683 		uu2 = (uint16)(uv2 & 0xFFFF);
1684 
1685 		tmp = *pPoly++;
1686 		v0 = pVertex + (tmp >> 16);
1687 		n0 = pNormal + (tmp & 0xFFFF);
1688 
1689 		tmp = *pPoly++;
1690 		v1 = pVertex + (tmp & 0xFFFF);
1691 		v2 = pVertex + (tmp >> 16);
1692 
1693 		// Now do RotTransPers3 on the vectors
1694 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
1695 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
1696 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1697 
1698 		// test the return value of flag
1699 		if (flag & 0x80000000)
1700 			continue;
1701 
1702 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
1703 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1704 		// test the return value of flag
1705 		if (flag & 0x80000000)
1706 			continue;
1707 
1708 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
1709 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1710 		// test the return value of flag
1711 		if (flag & 0x80000000)
1712 			continue;
1713 
1714 		// Give the GTE some time to recover
1715 		int32 avgz;
1716 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
1717 
1718 		// Do we want to do back face removal ?
1719 		if (_removeBackface) {
1720 			// use winding order of the polygons
1721 			// e.g. NormalClip which is cross product of screen vectors
1722 			if (_useWindingOrder) {
1723 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1724 				// Drawing back facings polys requires making them have
1725 				// clockwise winding order as by definition they have
1726 				// anti-clockwise winding order
1727 				if (flag < 0) {
1728 					if (_drawBface) {
1729 						stemp = sxy1;
1730 						sxy1 = sxy2;
1731 						sxy2 = stemp;
1732 						flag = uv1;
1733 						uv1 = uv2;
1734 						uv2 = flag;
1735 					} else {
1736 						// Skip this polygon
1737 						continue;
1738 					}
1739 				} else if (flag == 0)
1740 					continue; // ignore zero-area polygons
1741 			}
1742 
1743 			// TODO
1744 			// dot product of viewing direction and polygon normal
1745 			// will require generation of polygon normal from vertex normals
1746 			// and transformation of the normal to world space
1747 		}
1748 
1749 		// Set the RGB colours
1750 		if (_drawLit) {
1751 			// Do the full gouraud computation
1752 			// NormalColorCol( n0, &rgbIn, &rgb0 );
1753 			LIGHTPOLYGON(n0, &rgbIn, &rgb0);
1754 		}
1755 
1756 		// Put normal lines in list before wireframe
1757 		// so should be drawn in front of wireframe triangles
1758 		if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1759 			// Do coord transform on the scaled normal vectors + v0
1760 			sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1761 			sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1762 			sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1763 			// z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
1764 			gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
1765 			// Normal 0
1766 			LINE_G2 *line = (LINE_G2 *)drawpacket;
1767 			setLineG2(line);
1768 			line->x0 = sxy0.vx;
1769 			line->y0 = sxy0.vy;
1770 			line->x1 = sxyn0.vx;
1771 			line->y1 = sxyn0.vy;
1772 			if (selFace == i) {
1773 				// Bright red
1774 				setRGB0(line, 255, 0, 0);
1775 				// Bright white
1776 				setRGB1(line, 255, 255, 255);
1777 			} else {
1778 				// Bright blue
1779 				setRGB0(line, 0, 0, 255);
1780 				// Bright white
1781 				setRGB1(line, 255, 255, 255);
1782 			}
1783 			// Put it into the global ot at the correct place
1784 			myAddPrimClip(avgz, drawpacket);
1785 			// advance the global packet pointer by correct amount
1786 			myAddPacket(sizeof(LINE_G2));
1787 		}
1788 
1789 		// Put wireframe triangles in list before textured ones
1790 		// so should be in front of textured ones
1791 		if ((_drawWfrm) || (selFace == i)) {
1792 			// Draw a wireframe that responds to lighting
1793 			if (_drawLit) {
1794 				int32 cval;
1795 				LINE_G4 *line = (LINE_G4 *)drawpacket;
1796 				setLineG4(line);
1797 				// Compute the colour scaling and clip it
1798 				// Flat shading so give the same colour to each vertex
1799 				cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1800 				if (cval > 255)
1801 					cval = 255;
1802 				ctmp = (uint8)cval;
1803 				line->r0 = ctmp;
1804 				line->r1 = ctmp;
1805 				line->r2 = ctmp;
1806 				line->r3 = ctmp;
1807 				cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1808 				if (cval > 255)
1809 					cval = 255;
1810 				ctmp = (uint8)cval;
1811 				line->g0 = ctmp;
1812 				line->g1 = ctmp;
1813 				line->g2 = ctmp;
1814 				line->g3 = ctmp;
1815 				cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1816 				if (cval > 255)
1817 					cval = 255;
1818 				ctmp = (uint8)cval;
1819 				line->b0 = ctmp;
1820 				line->b1 = ctmp;
1821 				line->b2 = ctmp;
1822 				line->b3 = ctmp;
1823 
1824 				if (selFace == i) {
1825 					setRGB0(line, selWRed, selWGreen, selWBlue);
1826 					setRGB1(line, selWRed, selWGreen, selWBlue);
1827 					setRGB2(line, selWRed, selWGreen, selWBlue);
1828 					setRGB3(line, selWRed, selWGreen, selWBlue);
1829 				}
1830 				// set XY's in the GPU packet 0-1-2-3
1831 				line->x0 = sxy0.vx;
1832 				line->y0 = sxy0.vy;
1833 				line->x1 = sxy1.vx;
1834 				line->y1 = sxy1.vy;
1835 				line->x2 = sxy2.vx;
1836 				line->y2 = sxy2.vy;
1837 				line->x3 = sxy0.vx;
1838 				line->y3 = sxy0.vy;
1839 				// Put it into the global ot at the correct place
1840 				myAddPrimClip(avgz, drawpacket);
1841 				// advance the global packet pointer by correct amount
1842 				myAddPacket(sizeof(LINE_G4));
1843 			} else {
1844 				LINE_F4 *line = (LINE_F4 *)drawpacket;
1845 				setLineF4(line);
1846 				if (selFace == i)
1847 					setRGB0(line, selWRed, selWGreen, selWBlue);
1848 				else
1849 					setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1850 				// set XY's in the GPU packet 0-1-2-3
1851 				line->x0 = sxy0.vx;
1852 				line->y0 = sxy0.vy;
1853 				line->x1 = sxy1.vx;
1854 				line->y1 = sxy1.vy;
1855 				line->x2 = sxy2.vx;
1856 				line->y2 = sxy2.vy;
1857 				line->x3 = sxy0.vx;
1858 				line->y3 = sxy0.vy;
1859 				// Put it into the global ot at the correct place
1860 				myAddPrimClip(avgz, drawpacket);
1861 				// advance the global packet pointer by correct amount
1862 				myAddPacket(sizeof(LINE_F4));
1863 			}
1864 		}
1865 
1866 		// Draw textured version behind the wireframe
1867 		if ((_drawPolys) || (selFace == i)) {
1868 			if (_drawTxture) {
1869 				POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
1870 				setPolyFT3(poly);
1871 				// set XY's in the GPU packet 0-1-2
1872 				poly->x0 = sxy0.vx;
1873 				poly->y0 = sxy0.vy;
1874 				poly->x1 = sxy1.vx;
1875 				poly->y1 = sxy1.vy;
1876 				poly->x2 = sxy2.vx;
1877 				poly->y2 = sxy2.vy;
1878 
1879 				setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
1880 
1881 				if (_drawLit) {
1882 					setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1883 				} else {
1884 					// No light source calculation
1885 					// So just set base colour
1886 					setRGB0(poly, rgbIn.r, rgbIn.b, rgbIn.b);
1887 				}
1888 				if (selFace == i) {
1889 					setRGB0(poly, selPRed, selPGreen, selPBlue);
1890 				}
1891 
1892 				// Put it into the global ot at the correct place
1893 				myAddPrimClip(avgz, drawpacket);
1894 				// advance the global packet pointer by correct amount
1895 				myAddPacket(sizeof(POLY_FT3));
1896 			} else {
1897 				// Set the RGB colours
1898 				if (_drawLit) {
1899 					POLY_F3 *poly = (POLY_F3 *)drawpacket;
1900 					// Draw untextured polygons
1901 					setPolyF3(poly);
1902 					// set XY's in the GPU packet 0-1-2
1903 					poly->x0 = sxy0.vx;
1904 					poly->y0 = sxy0.vy;
1905 					poly->x1 = sxy1.vx;
1906 					poly->y1 = sxy1.vy;
1907 					poly->x2 = sxy2.vx;
1908 					poly->y2 = sxy2.vy;
1909 
1910 					// Flat shaded so give each vertex the same colour
1911 					if (selFace == i) {
1912 						setRGB0(poly, selPRed, selPGreen, selPBlue);
1913 					} else {
1914 						setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1915 					}
1916 
1917 					// Put it into the global ot at the correct place
1918 					myAddPrimClip(avgz, drawpacket);
1919 					// advance the global packet pointer by correct amount
1920 					myAddPacket(sizeof(POLY_F3));
1921 				} else {
1922 					POLY_F3 *poly = (POLY_F3 *)drawpacket;
1923 					// Draw untextured polygons
1924 					setPolyF3(poly);
1925 					// set XY's in the GPU packet 0-1-2
1926 					poly->x0 = sxy0.vx;
1927 					poly->y0 = sxy0.vy;
1928 					poly->x1 = sxy1.vx;
1929 					poly->y1 = sxy1.vy;
1930 					poly->x2 = sxy2.vx;
1931 					poly->y2 = sxy2.vy;
1932 
1933 					// No light source calculation
1934 					// So just set base colour
1935 					setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
1936 					// Put it into the global ot at the correct place
1937 					myAddPrimClip(avgz, drawpacket);
1938 					// advance the global packet pointer by correct amount
1939 					myAddPacket(sizeof(POLY_F3));
1940 				}
1941 			}
1942 		}
1943 	}
1944 }
1945 
1946 // Gouraud, Textured, Lit Triangles
drawGTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1947 void drawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1948 	SVECTOR *n0;
1949 	SVECTOR *n1;
1950 	SVECTOR *n2;
1951 	SVECTORPC *v0;
1952 	SVECTORPC *v1;
1953 	SVECTORPC *v2;
1954 	SVECTOR *ntemp;
1955 
1956 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1957 	uint32 num = n;
1958 	uint16 uu0, uu1, uu2;
1959 	uint16 vv0, vv1, vv2;
1960 	uint32 tmp;
1961 	uint8 ctmp;
1962 	int32 p, flag;
1963 	uint32 i;
1964 	uint32 *pPoly;
1965 	int32 z0, z1, z2;
1966 	SVECTORPC sxy0, sxy1, sxy2, stemp;
1967 	SVECTORPC sxyn0, sxyn1, sxyn2;
1968 	SVECTORPC sn0, sn1, sn2;
1969 	uint32 uv0, uv1, uv2;
1970 
1971 	// Base colour for gouraud shading computation
1972 	// Could easily be specified per polygon
1973 	CVECTOR rgbIn = {128, 128, 128, 0};
1974 	CVECTOR rgb0 = {0, 0, 0, 0};
1975 	CVECTOR rgb1 = {0, 0, 0, 0};
1976 	CVECTOR rgb2 = {0, 0, 0, 0};
1977 
1978 	pPoly = polyStart;
1979 	// Loop over each polygon
1980 	for (i = 0; i < num; i++) {
1981 		// Structure is :
1982 		// v0, u0
1983 		// v1, u1
1984 		// v2, u2
1985 		// v0     | n0
1986 		// v1     | n1
1987 		// v2     | n2
1988 		uv0 = *pPoly++;
1989 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
1990 		uu0 = (uint16)(uv0 & 0xFFFF);
1991 
1992 		uv1 = *pPoly++;
1993 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
1994 		uu1 = (uint16)(uv1 & 0xFFFF);
1995 
1996 		uv2 = *pPoly++;
1997 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
1998 		uu2 = (uint16)(uv2 & 0xFFFF);
1999 
2000 		tmp = *pPoly++;
2001 		v0 = pVertex + (tmp >> 16);
2002 		n0 = pNormal + (tmp & 0xFFFF);
2003 
2004 		tmp = *pPoly++;
2005 		v1 = pVertex + (tmp >> 16);
2006 		n1 = pNormal + (tmp & 0xFFFF);
2007 
2008 		tmp = *pPoly++;
2009 		v2 = pVertex + (tmp >> 16);
2010 		n2 = pNormal + (tmp & 0xFFFF);
2011 
2012 		// Now do RotTransPers3 on the vectors
2013 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2014 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
2015 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2016 
2017 		// test the return value of flag
2018 		if (flag & 0x80000000)
2019 			continue;
2020 
2021 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
2022 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2023 		// test the return value of flag
2024 		if (flag & 0x80000000)
2025 			continue;
2026 
2027 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
2028 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2029 		// test the return value of flag
2030 		if (flag & 0x80000000)
2031 			continue;
2032 
2033 		// Give the GTE some time to recover
2034 		int32 avgz;
2035 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
2036 
2037 		// Do we want to do back face removal ?
2038 		if (_removeBackface) {
2039 			// use winding order of the polygons
2040 			// e.g. NormalClip which is cross product of screen vectors
2041 			if (_useWindingOrder) {
2042 				gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2043 				// Drawing back facings polys requires making them have
2044 				// clockwise winding order as by definition they have
2045 				// anti-clockwise winding order
2046 				if (flag < 0) {
2047 					if (_drawBface) {
2048 						stemp = sxy1;
2049 						sxy1 = sxy2;
2050 						sxy2 = stemp;
2051 						ntemp = n1;
2052 						n1 = n2;
2053 						n2 = ntemp;
2054 						flag = uv1;
2055 						uv1 = uv2;
2056 						uv2 = flag;
2057 					} else {
2058 						// Skip this polygon
2059 						continue;
2060 					}
2061 				} else if (flag == 0)
2062 					continue; // ignore zero-area polygons
2063 			}
2064 
2065 			// TODO
2066 			// dot product of viewing direction and polygon normal
2067 			// will require generation of polygon normal from vertex normals
2068 			// and transformation of the normal to world space
2069 		}
2070 
2071 		// Set the RGB colours
2072 		if (_drawLit) {
2073 			// Do the full gouraud computation
2074 			// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
2075 			LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
2076 			int32 cval;
2077 
2078 			if (!_drawGouraud) {
2079 				// For flat shading mode take the average RGB for the face
2080 				// Could/should use something like AVSZ3
2081 				// but hell whats a divide by 3 between friends (~30 cycles?)
2082 				cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
2083 				if (cval > 255)
2084 					cval = 255;
2085 				rgb0.r = (uint8)cval;
2086 
2087 				cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
2088 				if (cval > 255)
2089 					cval = 255;
2090 				rgb0.g = (uint8)cval;
2091 
2092 				cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
2093 				if (cval > 255)
2094 					cval = 255;
2095 				rgb0.b = (uint8)cval;
2096 			}
2097 		}
2098 
2099 		// Put normal lines in list before wireframe
2100 		// so should be drawn in front of wireframe triangles
2101 		if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
2102 			// Do coord transform on the scaled normal vectors + v0
2103 			sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
2104 			sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
2105 			sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
2106 			sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
2107 			sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
2108 			sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
2109 			sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
2110 			sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
2111 			sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
2112 			// z0 = RotTransPers3( &sn0, &sn1, &sn2,
2113 			//                    &sxyn0, &sxyn1, &sxyn2, &p, &flag );
2114 			gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
2115 			// Normal 0
2116 			LINE_G2 *line = (LINE_G2 *)drawpacket;
2117 			setLineG2(line);
2118 			line->x0 = sxy0.vx;
2119 			line->y0 = sxy0.vy;
2120 			line->x1 = sxyn0.vx;
2121 			line->y1 = sxyn0.vy;
2122 			if (selFace == i) {
2123 				// Bright red
2124 				setRGB0(line, 255, 0, 0);
2125 				// Bright white
2126 				setRGB1(line, 255, 255, 255);
2127 			} else {
2128 				// Bright blue
2129 				setRGB0(line, 0, 0, 255);
2130 				// Bright white
2131 				setRGB1(line, 255, 255, 255);
2132 			}
2133 			// Put it into the global ot at the correct place
2134 			myAddPrimClip(avgz, drawpacket);
2135 			// advance the global packet pointer by correct amount
2136 			myAddPacket(sizeof(LINE_G2));
2137 
2138 			// Normal 1
2139 			line = (LINE_G2 *)drawpacket;
2140 			setLineG2(line);
2141 			line->x0 = sxy0.vx;
2142 			line->y0 = sxy0.vy;
2143 			line->x1 = sxyn1.vx;
2144 			line->y1 = sxyn1.vy;
2145 			if (selFace == i) {
2146 				// Bright red
2147 				setRGB0(line, 255, 0, 0);
2148 				// Bright white
2149 				setRGB1(line, 255, 255, 255);
2150 			} else {
2151 				// Bright blue
2152 				setRGB0(line, 0, 0, 255);
2153 				// Bright white
2154 				setRGB1(line, 255, 255, 255);
2155 			}
2156 			// Put it into the global ot at the correct place
2157 			myAddPrimClip(avgz, drawpacket);
2158 			// advance the global packet pointer by correct amount
2159 			myAddPacket(sizeof(LINE_G2));
2160 
2161 			// Normal 2
2162 			line = (LINE_G2 *)drawpacket;
2163 			setLineG2(line);
2164 			line->x0 = sxy0.vx;
2165 			line->y0 = sxy0.vy;
2166 			line->x1 = sxyn2.vx;
2167 			line->y1 = sxyn2.vy;
2168 			if (selFace == i) {
2169 				// Bright red
2170 				setRGB0(line, 255, 0, 0);
2171 				// Bright white
2172 				setRGB1(line, 255, 255, 255);
2173 			} else {
2174 				// Bright blue
2175 				setRGB0(line, 0, 0, 255);
2176 				// Bright white
2177 				setRGB1(line, 255, 255, 255);
2178 			}
2179 			// Put it into the global ot at the correct place
2180 			myAddPrimClip(avgz, drawpacket);
2181 			// advance the global packet pointer by correct amount
2182 			myAddPacket(sizeof(LINE_G2));
2183 		}
2184 
2185 		// Put wireframe triangles in list before textured ones
2186 		// so should be in front of textured ones
2187 		if ((_drawWfrm) || (selFace == i)) {
2188 			// Draw a wireframe that responds to lighting
2189 			if (_drawLit) {
2190 				LINE_G4 *line = (LINE_G4 *)drawpacket;
2191 				setLineG4(line);
2192 				int32 cval;
2193 				if (_drawGouraud) {
2194 					// Give each vertex a seperate colour
2195 					// Compute the colour scaling and clip it
2196 					if (rgbIn.r != 0) {
2197 						cval = ((wfrmRed * rgb0.r) / rgbIn.r);
2198 						if (cval > 255)
2199 							cval = 255;
2200 						ctmp = (uint8)cval;
2201 						line->r0 = ctmp;
2202 						line->r3 = ctmp;
2203 
2204 						cval = ((wfrmRed * rgb1.r) / rgbIn.r);
2205 						if (cval > 255)
2206 							cval = 255;
2207 						ctmp = (uint8)cval;
2208 						line->r1 = ctmp;
2209 
2210 						cval = ((wfrmRed * rgb2.r) / rgbIn.r);
2211 						if (cval > 255)
2212 							cval = 255;
2213 						ctmp = (uint8)cval;
2214 						line->r2 = ctmp;
2215 					} else {
2216 						line->r0 = 0;
2217 						line->r3 = 0;
2218 						line->r1 = 0;
2219 						line->r2 = 0;
2220 					}
2221 
2222 					if (rgbIn.g != 0) {
2223 						cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
2224 						if (cval > 255)
2225 							cval = 255;
2226 						ctmp = (uint8)cval;
2227 						line->g0 = ctmp;
2228 						line->g3 = ctmp;
2229 						cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
2230 						if (cval > 255)
2231 							cval = 255;
2232 						ctmp = (uint8)cval;
2233 						line->g1 = ctmp;
2234 						cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
2235 						if (cval > 255)
2236 							cval = 255;
2237 						ctmp = (uint8)cval;
2238 						line->g2 = ctmp;
2239 					} else {
2240 						line->g0 = 0;
2241 						line->g3 = 0;
2242 						line->g1 = 0;
2243 						line->g2 = 0;
2244 					}
2245 					if (rgbIn.b != 0) {
2246 						cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
2247 						if (cval > 255)
2248 							cval = 255;
2249 						ctmp = (uint8)cval;
2250 						line->b0 = ctmp;
2251 						line->b3 = ctmp;
2252 						cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
2253 						if (cval > 255)
2254 							cval = 255;
2255 						ctmp = (uint8)cval;
2256 						line->b1 = ctmp;
2257 						cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
2258 						if (cval > 255)
2259 							cval = 255;
2260 						ctmp = (uint8)cval;
2261 						line->b2 = ctmp;
2262 					} else {
2263 						line->b0 = 0;
2264 						line->b3 = 0;
2265 						line->b1 = 0;
2266 						line->b2 = 0;
2267 					}
2268 				} else {
2269 					// Compute the colour scaling and clip it
2270 					// Flat shading so give the same colour to each vertex
2271 					if (rgbIn.r != 0) {
2272 						cval = ((wfrmRed * rgb0.r) / rgbIn.r);
2273 						if (cval > 255)
2274 							cval = 255;
2275 						ctmp = (uint8)cval;
2276 					} else
2277 						ctmp = 0;
2278 					line->r0 = ctmp;
2279 					line->r1 = ctmp;
2280 					line->r2 = ctmp;
2281 					line->r3 = ctmp;
2282 
2283 					if (rgbIn.g != 0) {
2284 						cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
2285 						if (cval > 255)
2286 							cval = 255;
2287 						ctmp = (uint8)cval;
2288 					} else
2289 						ctmp = 0;
2290 					line->g0 = ctmp;
2291 					line->g1 = ctmp;
2292 					line->g2 = ctmp;
2293 					line->g3 = ctmp;
2294 
2295 					if (rgbIn.b != 0) {
2296 						cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
2297 						if (cval > 255)
2298 							cval = 255;
2299 						ctmp = (uint8)cval;
2300 					} else
2301 						ctmp = 0;
2302 
2303 					line->b0 = ctmp;
2304 					line->b1 = ctmp;
2305 					line->b2 = ctmp;
2306 					line->b3 = ctmp;
2307 				}
2308 
2309 				if (selFace == i) {
2310 					setRGB0(line, selWRed, selWGreen, selWBlue);
2311 					setRGB1(line, selWRed, selWGreen, selWBlue);
2312 					setRGB2(line, selWRed, selWGreen, selWBlue);
2313 					setRGB3(line, selWRed, selWGreen, selWBlue);
2314 				}
2315 				// set XY's in the GPU packet 0-1-2-3
2316 				line->x0 = sxy0.vx;
2317 				line->y0 = sxy0.vy;
2318 				line->x1 = sxy1.vx;
2319 				line->y1 = sxy1.vy;
2320 				line->x2 = sxy2.vx;
2321 				line->y2 = sxy2.vy;
2322 				line->x3 = sxy0.vx;
2323 				line->y3 = sxy0.vy;
2324 				// Put it into the global ot at the correct place
2325 				myAddPrimClip(avgz, drawpacket);
2326 				// advance the global packet pointer by correct amount
2327 				myAddPacket(sizeof(LINE_G4));
2328 			} else {
2329 				LINE_F4 *line = (LINE_F4 *)drawpacket;
2330 				setLineF4(line);
2331 				if (selFace == i)
2332 					setRGB0(line, selWRed, selWGreen, selWBlue);
2333 				else
2334 					setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
2335 				// set XY's in the GPU packet 0-1-2-3
2336 				line->x0 = sxy0.vx;
2337 				line->y0 = sxy0.vy;
2338 				line->x1 = sxy1.vx;
2339 				line->y1 = sxy1.vy;
2340 				line->x2 = sxy2.vx;
2341 				line->y2 = sxy2.vy;
2342 				line->x3 = sxy0.vx;
2343 				line->y3 = sxy0.vy;
2344 				// Put it into the global ot at the correct place
2345 				myAddPrimClip(avgz, drawpacket);
2346 				// advance the global packet pointer by correct amount
2347 				myAddPacket(sizeof(LINE_F4));
2348 			}
2349 		}
2350 
2351 		// Draw textured version behind the wireframe
2352 		if ((_drawPolys) || (selFace == i)) {
2353 			if (_drawTxture) {
2354 				// Set the RGB colours
2355 				if ((_drawLit) && (_drawGouraud)) {
2356 					POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
2357 					setPolyGT3(poly);
2358 					// set XY's in the GPU packet 0-1-2
2359 					poly->x0 = sxy0.vx;
2360 					poly->y0 = sxy0.vy;
2361 					poly->x1 = sxy1.vx;
2362 					poly->y1 = sxy1.vy;
2363 					poly->x2 = sxy2.vx;
2364 					poly->y2 = sxy2.vy;
2365 
2366 					setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2367 					if (selFace == i) {
2368 						setRGB0(poly, selPRed, selPGreen, selPBlue);
2369 						setRGB1(poly, selPRed, selPGreen, selPBlue);
2370 						setRGB2(poly, selPRed, selPGreen, selPBlue);
2371 					} else {
2372 						setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2373 						setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
2374 						setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
2375 					}
2376 
2377 					// Put it into the global ot at the correct place
2378 					myAddPrimClip(avgz, drawpacket);
2379 					// advance the global packet pointer by correct amount
2380 					myAddPacket(sizeof(POLY_GT3));
2381 				} else {
2382 					POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
2383 					setPolyFT3(poly);
2384 					// set XY's in the GPU packet 0-1-2
2385 					poly->x0 = sxy0.vx;
2386 					poly->y0 = sxy0.vy;
2387 					poly->x1 = sxy1.vx;
2388 					poly->y1 = sxy1.vy;
2389 					poly->x2 = sxy2.vx;
2390 					poly->y2 = sxy2.vy;
2391 
2392 					setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2393 
2394 					if (_drawLit) {
2395 						setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2396 					} else {
2397 						// No light source calculation
2398 						// So just set base colour
2399 						setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
2400 					}
2401 					if (selFace == i) {
2402 						setRGB0(poly, selPRed, selPGreen, selPBlue);
2403 					}
2404 
2405 					// Put it into the global ot at the correct place
2406 					myAddPrimClip(avgz, drawpacket);
2407 					// advance the global packet pointer by correct amount
2408 					myAddPacket(sizeof(POLY_FT3));
2409 				}
2410 			} else {
2411 				// Set the RGB colours
2412 				if (_drawLit) {
2413 					if (_drawGouraud) {
2414 						POLY_G3 *poly = (POLY_G3 *)drawpacket;
2415 						// Draw untextured polygons
2416 						setPolyG3(poly);
2417 						// set XY's in the GPU packet 0-1-2
2418 						poly->x0 = sxy0.vx;
2419 						poly->y0 = sxy0.vy;
2420 						poly->x1 = sxy1.vx;
2421 						poly->y1 = sxy1.vy;
2422 						poly->x2 = sxy2.vx;
2423 						poly->y2 = sxy2.vy;
2424 
2425 						if (selFace == i) {
2426 							setRGB0(poly, selPRed, selPGreen, selPBlue);
2427 							setRGB1(poly, selPRed, selPGreen, selPBlue);
2428 							setRGB2(poly, selPRed, selPGreen, selPBlue);
2429 						} else {
2430 							setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2431 							setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
2432 							setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
2433 						}
2434 
2435 						// Put it into the global ot at the correct place
2436 						myAddPrimClip(avgz, drawpacket);
2437 						// advance the global packet pointer by correct amount
2438 						myAddPacket(sizeof(POLY_G3));
2439 					} else {
2440 						POLY_F3 *poly = (POLY_F3 *)drawpacket;
2441 						// Draw untextured polygons
2442 						setPolyF3(poly);
2443 						// set XY's in the GPU packet 0-1-2
2444 						poly->x0 = sxy0.vx;
2445 						poly->y0 = sxy0.vy;
2446 						poly->x1 = sxy1.vx;
2447 						poly->y1 = sxy1.vy;
2448 						poly->x2 = sxy2.vx;
2449 						poly->y2 = sxy2.vy;
2450 
2451 						// Flat shaded so give each vertex the same colour
2452 						if (selFace == i) {
2453 							setRGB0(poly, selPRed, selPGreen, selPBlue);
2454 						} else {
2455 							setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2456 						}
2457 
2458 						// Put it into the global ot at the correct place
2459 						myAddPrimClip(avgz, drawpacket);
2460 						// advance the global packet pointer by correct amount
2461 						myAddPacket(sizeof(POLY_F3));
2462 					}
2463 				} else {
2464 					POLY_F3 *poly = (POLY_F3 *)drawpacket;
2465 					// Draw untextured polygons
2466 					setPolyF3(poly);
2467 					// set XY's in the GPU packet 0-1-2
2468 					poly->x0 = sxy0.vx;
2469 					poly->y0 = sxy0.vy;
2470 					poly->x1 = sxy1.vx;
2471 					poly->y1 = sxy1.vy;
2472 					poly->x2 = sxy2.vx;
2473 					poly->y2 = sxy2.vy;
2474 
2475 					// No light source calculation
2476 					// So just set base colour
2477 					if (selFace == i) {
2478 						setRGB0(poly, selPRed, selPGreen, selPBlue);
2479 					} else {
2480 						setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
2481 						poly->code = unlitPoly.cd;
2482 					}
2483 					// Put it into the global ot at the correct place
2484 					myAddPrimClip(avgz, drawpacket);
2485 					// advance the global packet pointer by correct amount
2486 					myAddPacket(sizeof(POLY_F3));
2487 				}
2488 			}
2489 		}
2490 	}
2491 }
2492 
2493 // Simple flat untextured triangles
2494 // draw backfacing triangles as well
2495 // the colour is set by a global variable
2496 
drawTRI3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2497 void drawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2498 	SVECTORPC *v0;
2499 	SVECTORPC *v1;
2500 	SVECTORPC *v2;
2501 
2502 	// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
2503 	uint32 num = n;
2504 	int32 p, flag;
2505 	uint32 i;
2506 	uint32 *pPoly;
2507 	int32 z0, z1, z2;
2508 	SVECTORPC sxy0, sxy1, sxy2, stemp;
2509 	uint32 tmp;
2510 
2511 	pPoly = polyStart;
2512 	// Loop over each polygon
2513 	for (i = 0; i < num; i++) {
2514 		// Each polygon is 2 32-bit WORDS
2515 		// Bit 31 ----> Bit 0
2516 		//
2517 		// 16-bits | 16-bits
2518 		// --------------------------
2519 		//  v1     | v0
2520 		//  pad    | v2
2521 
2522 		tmp = *pPoly++;
2523 		v0 = pVertex + (tmp & 0xFFFF);
2524 		v1 = pVertex + (tmp >> 16);
2525 
2526 		tmp = *pPoly++;
2527 		v2 = pVertex + (tmp & 0xFFFF);
2528 
2529 		// Now do RotTransPers3 on the vectors
2530 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2531 		gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
2532 		z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2533 
2534 		// test the return value of flag
2535 		if (flag & 0x80000000)
2536 			continue;
2537 
2538 		gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
2539 		z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2540 		// test the return value of flag
2541 		if (flag & 0x80000000)
2542 			continue;
2543 
2544 		gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
2545 		z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2546 		// test the return value of flag
2547 		if (flag & 0x80000000)
2548 			continue;
2549 
2550 		// Give the GTE some time to recover
2551 		int32 avgz;
2552 		gte_AverageZ3_pc(z0, z1, z2, &avgz);
2553 
2554 		// See what winding order this polygon is ?
2555 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2556 
2557 		// Drawing back facing polys requires making them have
2558 		// clockwise winding order as by definition they have
2559 		// anti-clockwise winding order
2560 		if (flag < 0) {
2561 			stemp = sxy1;
2562 			sxy1 = sxy2;
2563 			sxy2 = stemp;
2564 		}
2565 
2566 		// Put wireframe triangles in list before textured ones
2567 		// so should be in front of textured ones
2568 		if ((_drawWfrm) || (selFace == i)) {
2569 			LINE_F4 *line = (LINE_F4 *)drawpacket;
2570 			setLineF4(line);
2571 			// set XY's in the GPU packet 0-1-2-3
2572 			line->x0 = sxy0.vx;
2573 			line->y0 = sxy0.vy;
2574 			line->x1 = sxy1.vx;
2575 			line->y1 = sxy1.vy;
2576 			line->x2 = sxy2.vx;
2577 			line->y2 = sxy2.vy;
2578 			line->x3 = sxy0.vx;
2579 			line->y3 = sxy0.vy;
2580 			if (selFace == i)
2581 				setRGB0(line, selWRed, selWGreen, selWBlue);
2582 			else
2583 				setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
2584 			// Put it into the global ot at the correct place
2585 			myAddPrimClip(avgz, drawpacket);
2586 			// advance the global packet pointer by correct amount
2587 			myAddPacket(sizeof(LINE_F4));
2588 		}
2589 
2590 		// Draw polygon version behind the wireframe
2591 		if ((_drawPolys) || (selFace == i)) {
2592 			// Draw untextured polygons
2593 			TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
2594 			setTPolyF3(poly);
2595 			setTABRMode(poly, 2);   // 2 = back - front
2596 			setTSemiTrans(poly, 1); // 1 = enable semi-transparency
2597 
2598 			// set XY's in the GPU packet 0-1-2
2599 			poly->x0 = sxy0.vx;
2600 			poly->y0 = sxy0.vy;
2601 			poly->x1 = sxy1.vx;
2602 			poly->y1 = sxy1.vy;
2603 			poly->x2 = sxy2.vx;
2604 			poly->y2 = sxy2.vy;
2605 
2606 			// Set the RGB colours
2607 			// No light source calculation
2608 			// So just set base colour
2609 			if (selFace == i) {
2610 				setRGB0(poly, selPRed, selPGreen, selPBlue);
2611 				poly->code = selPAlpha;
2612 			} else {
2613 				setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
2614 				poly->code = unlitPoly.cd;
2615 			}
2616 
2617 			// Put it into the global ot at the correct place
2618 			myAddPrimClip(avgz, drawpacket);
2619 			// advance the global packet pointer by correct amount
2620 			myAddPacket(sizeof(TPOLY_F3));
2621 		}
2622 	}
2623 }
2624 
2625 #endif // #if CD_MODE == 0
2626 
2627 // Flat, Un-Textured, Self-Luminous, triangles
fastDrawFUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2628 void fastDrawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2629 	SVECTORPC *v0;
2630 	SVECTORPC *v1;
2631 	SVECTORPC *v2;
2632 
2633 	int32 flag;
2634 	uint32 i;
2635 	uint32 *pPoly;
2636 	int32 z0;
2637 	SVECTORPC sxy0, sxy1, sxy2;
2638 	CVECTOR *rgbIn;
2639 	uint32 tmp;
2640 
2641 	pPoly = polyStart;
2642 	// Loop over each polygon
2643 	for (i = 0; i < n; i++) {
2644 		// Structure is :
2645 		// 0x20 | B | G | R
2646 		// v1       | v0
2647 		// pad      | v2
2648 		rgbIn = (CVECTOR *)pPoly++;
2649 
2650 		if (deadObject) {
2651 			rgbIn = &deadObjectColour;
2652 		}
2653 
2654 		tmp = *pPoly++;
2655 		v0 = pVertex + (tmp & 0xFFFF);
2656 		v1 = pVertex + (tmp >> 16);
2657 
2658 		tmp = *pPoly++;
2659 		v2 = pVertex + (tmp & 0xFFFF);
2660 
2661 		// Now do RotTransPers3 on the vectors
2662 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2663 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2664 
2665 		// test the return value of flag
2666 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
2667 		// The flag value is set to 0x8000 or 0 in the pad structure
2668 		if (v0->pad != 0)
2669 			continue;
2670 		if (v1->pad != 0)
2671 			continue;
2672 		if (v2->pad != 0)
2673 			continue;
2674 
2675 		// use winding order of the polygons
2676 		// e.g. NormalClip which is cross product of screen vectors
2677 		sxy0.vx = v0->vx;
2678 		sxy0.vy = v0->vy;
2679 		sxy1.vx = v1->vx;
2680 		sxy1.vy = v1->vy;
2681 		sxy2.vx = v2->vx;
2682 		sxy2.vy = v2->vy;
2683 
2684 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2685 		if (flag <= 0)
2686 			continue;
2687 
2688 		// Draw untextured polygons
2689 		POLY_F3 *poly = (POLY_F3 *)drawpacket;
2690 		setPolyF3(poly);
2691 		// set XY's in the GPU packet 0-1-2
2692 		poly->x0 = sxy0.vx;
2693 		poly->y0 = sxy0.vy;
2694 		poly->x1 = sxy1.vx;
2695 		poly->y1 = sxy1.vy;
2696 		poly->x2 = sxy2.vx;
2697 		poly->y2 = sxy2.vy;
2698 
2699 		// Set the RGB colours
2700 		// No light source calculation
2701 		// So just set base colour
2702 		setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
2703 
2704 		// Give the GTE some time to recover
2705 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2706 
2707 		// Put it into the global ot at the correct place
2708 		myAddPrimClip(z0, drawpacket);
2709 		// advance the global packet pointer by correct amount
2710 		myAddPacket(sizeof(POLY_F3));
2711 	}
2712 }
2713 
2714 // Fast: no options, Gouraud, Un-Textured, Self-Luminous, triangles
fastDrawGUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2715 void fastDrawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2716 	SVECTORPC *v0;
2717 	SVECTORPC *v1;
2718 	SVECTORPC *v2;
2719 
2720 	uint32 tmp;
2721 	int32 flag;
2722 	uint32 i;
2723 	uint32 *pPoly;
2724 	int32 z0;
2725 	SVECTORPC sxy0, sxy1, sxy2;
2726 
2727 	// Base colour for gouraud shading computation
2728 	// Could easily be specified per polygon
2729 	CVECTOR *rgb0;
2730 	CVECTOR *rgb1;
2731 	CVECTOR *rgb2;
2732 
2733 	pPoly = polyStart;
2734 	// Loop over each polygon
2735 	for (i = 0; i < n; i++) {
2736 		// Structure is :
2737 		// 8-bits | 8-bits | 8-bits | 8-bits
2738 		// 0x30   | Blue0  | Green0 | Red0
2739 		// 0x30   | Blue1  | Green1 | Red1
2740 		// 0x30   | Blue2  | Green2 | Red2
2741 		// 16-bits | 8-bits | 8-bits
2742 		// --------------------------
2743 		//  v1              | v0
2744 		//  pad             | v2
2745 		rgb0 = (CVECTOR *)pPoly++;
2746 		rgb1 = (CVECTOR *)pPoly++;
2747 		rgb2 = (CVECTOR *)pPoly++;
2748 
2749 		if (deadObject) {
2750 			rgb0 = &deadObjectColour;
2751 			rgb1 = &deadObjectColour;
2752 			rgb2 = &deadObjectColour;
2753 		}
2754 
2755 		tmp = *pPoly++;
2756 		v0 = pVertex + (tmp & 0xFFFF);
2757 		v1 = pVertex + (tmp >> 16);
2758 
2759 		tmp = *pPoly++;
2760 		v2 = pVertex + (tmp & 0xFFFF);
2761 
2762 		// Now do RotTransPers3 on the vectors
2763 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2764 		// gte_RotTransPers3(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2765 
2766 		// test the return value of flag
2767 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
2768 		// The flag value is set to 0x8000 or 0 in the pad structure
2769 		if (v0->pad != 0)
2770 			continue;
2771 		if (v1->pad != 0)
2772 			continue;
2773 		if (v2->pad != 0)
2774 			continue;
2775 
2776 		// use winding order of the polygons
2777 		// e.g. NormalClip which is cross product of screen vectors
2778 		sxy0.vx = v0->vx;
2779 		sxy0.vy = v0->vy;
2780 		sxy1.vx = v1->vx;
2781 		sxy1.vy = v1->vy;
2782 		sxy2.vx = v2->vx;
2783 		sxy2.vy = v2->vy;
2784 
2785 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2786 		if (flag <= 0)
2787 			continue;
2788 
2789 		POLY_G3 *poly = (POLY_G3 *)drawpacket;
2790 		// Draw untextured polygons
2791 		setPolyG3(poly);
2792 		// set XY's in the GPU packet 0-1-2
2793 		poly->x0 = sxy0.vx;
2794 		poly->y0 = sxy0.vy;
2795 		poly->x1 = sxy1.vx;
2796 		poly->y1 = sxy1.vy;
2797 		poly->x2 = sxy2.vx;
2798 		poly->y2 = sxy2.vy;
2799 
2800 		setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
2801 		setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
2802 		setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
2803 
2804 		// Give the GTE some time to recover
2805 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2806 
2807 		// Put it into the global ot at the correct place
2808 		myAddPrimClip(z0, drawpacket);
2809 		// advance the global packet pointer by correct amount
2810 		myAddPacket(sizeof(POLY_G3));
2811 	}
2812 }
2813 
2814 // Fast: no options, Flat, Textured, Self-Luminous Triangles
fastDrawFTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2815 void fastDrawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2816 	SVECTORPC *v0;
2817 	SVECTORPC *v1;
2818 	SVECTORPC *v2;
2819 
2820 	uint16 uu0, uu1, uu2;
2821 	uint16 vv0, vv1, vv2;
2822 	uint32 tmp;
2823 	int32 flag;
2824 	uint32 i;
2825 	uint32 *pPoly;
2826 	int32 z0;
2827 	SVECTORPC sxy0, sxy1, sxy2;
2828 	uint32 uv0, uv1, uv2;
2829 
2830 	// Base colour for shading computation
2831 	// Could easily be specified per polygon
2832 	CVECTOR *rgbIn;
2833 
2834 	pPoly = polyStart;
2835 	// Loop over each polygon
2836 	for (i = 0; i < n; i++) {
2837 		// Structure is :
2838 		// Bit 31 ----> Bit 0
2839 		//
2840 		// 8-bits | 8-bits | 8-bits | 8-bits
2841 		// 0x24   | Blue   | Green  | Red
2842 		// 16-bits | 16-bits
2843 		// --------------------------
2844 		// v0      | u0
2845 		// v1      | u1
2846 		// v2      | u2
2847 		// --------------------------
2848 		// pad     | v0
2849 		//  v2     | v1
2850 		rgbIn = (CVECTOR *)pPoly++;
2851 
2852 		if (deadObject == 1) {
2853 			rgbIn = &deadObjectColour;
2854 		}
2855 
2856 		uv0 = *pPoly++;
2857 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
2858 		uu0 = (uint16)(uv0 & 0xFFFF);
2859 
2860 		uv1 = *pPoly++;
2861 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
2862 		uu1 = (uint16)(uv1 & 0xFFFF);
2863 
2864 		uv2 = *pPoly++;
2865 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
2866 		uu2 = (uint16)(uv2 & 0xFFFF);
2867 
2868 		tmp = *pPoly++;
2869 		v0 = pVertex + (tmp & 0xFFFF);
2870 
2871 		tmp = *pPoly++;
2872 		v1 = pVertex + (uint)(tmp & 0xFFFF);
2873 		v2 = pVertex + (uint)(tmp >> 16);
2874 
2875 		// Now do RotTransPers3 on the vectors
2876 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2877 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2878 
2879 		// test the return value of flag
2880 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
2881 		// The flag value is set to 0x8000 or 0 in the pad structure
2882 		if (v0->pad != 0)
2883 			continue;
2884 		if (v1->pad != 0)
2885 			continue;
2886 		if (v2->pad != 0)
2887 			continue;
2888 
2889 		// use winding order of the polygons
2890 		// e.g. NormalClip which is cross product of screen vectors
2891 		sxy0.vx = v0->vx;
2892 		sxy0.vy = v0->vy;
2893 		sxy1.vx = v1->vx;
2894 		sxy1.vy = v1->vy;
2895 		sxy2.vx = v2->vx;
2896 		sxy2.vy = v2->vy;
2897 
2898 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2899 		if (flag <= 0)
2900 			continue;
2901 
2902 		POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
2903 		setPolyFT3(poly);
2904 		// set XY's in the GPU packet 0-1-2
2905 		poly->x0 = sxy0.vx;
2906 		poly->y0 = sxy0.vy;
2907 		poly->x1 = sxy1.vx;
2908 		poly->y1 = sxy1.vy;
2909 		poly->x2 = sxy2.vx;
2910 		poly->y2 = sxy2.vy;
2911 
2912 		setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2913 
2914 		// No light source calculation so just set base colour
2915 		setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
2916 
2917 		// Give the GTE some time to recover
2918 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2919 
2920 		// Put it into the global ot at the correct place
2921 		myAddPrimClip(z0, drawpacket);
2922 		// advance the global packet pointer by correct amount
2923 		myAddPacket(sizeof(POLY_FT3));
2924 	}
2925 }
2926 
2927 // Fast: no options, Gouraud, Textured, Self-Luminous Triangles
fastDrawGTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2928 void fastDrawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2929 	SVECTORPC *v0;
2930 	SVECTORPC *v1;
2931 	SVECTORPC *v2;
2932 
2933 	uint16 uu0, uu1, uu2;
2934 	uint16 vv0, vv1, vv2;
2935 	uint32 tmp;
2936 	int32 flag;
2937 	uint32 i;
2938 	uint32 *pPoly;
2939 	int32 z0;
2940 	SVECTORPC sxy0, sxy1, sxy2;
2941 	uint32 uv0, uv1, uv2;
2942 
2943 	// gouraud colours
2944 	CVECTOR *rgb0;
2945 	CVECTOR *rgb1;
2946 	CVECTOR *rgb2;
2947 
2948 	pPoly = polyStart;
2949 	// Loop over each polygon
2950 	for (i = 0; i < n; i++) {
2951 		// Structure is :
2952 		// 8-bits | 8-bits | 8-bits | 8-bits
2953 		// 0x34   | Blue0  | Green0 | Red0
2954 		// 0x34   | Blue1  | Green1 | Red1
2955 		// 0x34   | Blue2  | Green2 | Red2
2956 		// 16-bits | 16-bits
2957 		// --------------------------
2958 		// v0      | u0
2959 		// v1      | u1
2960 		// v2      | u2
2961 		// --------------------------
2962 		// pad     | v0
2963 		//  v2     | v1
2964 		rgb0 = (CVECTOR *)pPoly++;
2965 		rgb1 = (CVECTOR *)pPoly++;
2966 		rgb2 = (CVECTOR *)pPoly++;
2967 
2968 		if (deadObject) {
2969 			rgb0 = &deadObjectColour;
2970 			rgb1 = &deadObjectColour;
2971 			rgb2 = &deadObjectColour;
2972 		}
2973 
2974 		uv0 = *pPoly++;
2975 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
2976 		uu0 = (uint16)(uv0 & 0xFFFF);
2977 
2978 		uv1 = *pPoly++;
2979 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
2980 		uu1 = (uint16)(uv1 & 0xFFFF);
2981 
2982 		uv2 = *pPoly++;
2983 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
2984 		uu2 = (uint16)(uv2 & 0xFFFF);
2985 
2986 		tmp = *pPoly++;
2987 		v0 = pVertex + (tmp & 0xFFFF);
2988 
2989 		tmp = *pPoly++;
2990 		v1 = pVertex + (tmp & 0xFFFF);
2991 		v2 = pVertex + (tmp >> 16);
2992 
2993 		// Now do RotTransPers3 on the vectors
2994 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2995 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2996 
2997 		// test the return value of flag
2998 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
2999 		// The flag value is set to 0x8000 or 0 in the pad structure
3000 		if (v0->pad != 0)
3001 			continue;
3002 		if (v1->pad != 0)
3003 			continue;
3004 		if (v2->pad != 0)
3005 			continue;
3006 
3007 		// use winding order of the polygons
3008 		// e.g. NormalClip which is cross product of screen vectors
3009 		sxy0.vx = v0->vx;
3010 		sxy0.vy = v0->vy;
3011 		sxy1.vx = v1->vx;
3012 		sxy1.vy = v1->vy;
3013 		sxy2.vx = v2->vx;
3014 		sxy2.vy = v2->vy;
3015 
3016 		// use winding order of the polygons
3017 		// e.g. NormalClip which is cross product of screen vectors
3018 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3019 		if (flag <= 0)
3020 			continue;
3021 
3022 		// Set the RGB colours
3023 		POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
3024 		setPolyGT3(poly);
3025 		// set XY's in the GPU packet 0-1-2
3026 		poly->x0 = sxy0.vx;
3027 		poly->y0 = sxy0.vy;
3028 		poly->x1 = sxy1.vx;
3029 		poly->y1 = sxy1.vy;
3030 		poly->x2 = sxy2.vx;
3031 		poly->y2 = sxy2.vy;
3032 
3033 		setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3034 
3035 		setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
3036 		setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
3037 		setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
3038 
3039 		// Give the GTE some time to recover
3040 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3041 
3042 		// Put it into the global ot at the correct place
3043 		myAddPrimClip(z0, drawpacket);
3044 
3045 		// advance the global packet pointer by correct amount
3046 		myAddPacket(sizeof(POLY_GT3));
3047 	}
3048 }
3049 
3050 // Fast: no options, Flat, Un-Textured, Lit, triangles
fastDrawFUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3051 void fastDrawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3052 	SVECTOR *n0;
3053 	SVECTORPC *v0;
3054 	SVECTORPC *v1;
3055 	SVECTORPC *v2;
3056 
3057 	int32 flag;
3058 	uint32 i;
3059 	uint32 *pPoly;
3060 	int32 z0;
3061 	SVECTORPC sxy0, sxy1, sxy2;
3062 	CVECTOR *rgbIn;
3063 	CVECTOR rgb0;
3064 	uint32 tmp;
3065 
3066 	pPoly = polyStart;
3067 	// Loop over each polygon
3068 	for (i = 0; i < n; i++) {
3069 		// Structure is :
3070 		// 0x20 | B | G | R
3071 		// v0       | n0
3072 		// v2       | v1
3073 		rgbIn = (CVECTOR *)pPoly++;
3074 
3075 		tmp = *pPoly++;
3076 		v0 = pVertex + (tmp >> 16);
3077 		n0 = pNormal + (tmp & 0xFFFF);
3078 
3079 		tmp = *pPoly++;
3080 		v2 = pVertex + (tmp >> 16);
3081 		v1 = pVertex + (tmp & 0xFFFF);
3082 
3083 		// Now do RotTransPers3 on the vectors
3084 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3085 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3086 
3087 		// test the return value of flag
3088 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
3089 		// The flag value is set to 0x8000 or 0 in the pad structure
3090 		if (v0->pad != 0)
3091 			continue;
3092 		if (v1->pad != 0)
3093 			continue;
3094 		if (v2->pad != 0)
3095 			continue;
3096 
3097 		// use winding order of the polygons
3098 		// e.g. NormalClip which is cross product of screen vectors
3099 		sxy0.vx = v0->vx;
3100 		sxy0.vy = v0->vy;
3101 		sxy1.vx = v1->vx;
3102 		sxy1.vy = v1->vy;
3103 		sxy2.vx = v2->vx;
3104 		sxy2.vy = v2->vy;
3105 
3106 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3107 		if (flag <= 0)
3108 			continue;
3109 
3110 		// Do the flat lighting computation
3111 		LIGHTPOLYGON(n0, rgbIn, &rgb0);
3112 
3113 		// Draw untextured polygons
3114 		POLY_F3 *poly = (POLY_F3 *)drawpacket;
3115 		setPolyF3(poly);
3116 
3117 		// set XY's in the GPU packet 0-1-2
3118 		poly->x0 = sxy0.vx;
3119 		poly->y0 = sxy0.vy;
3120 		poly->x1 = sxy1.vx;
3121 		poly->y1 = sxy1.vy;
3122 		poly->x2 = sxy2.vx;
3123 		poly->y2 = sxy2.vy;
3124 
3125 		// Set the RGB colours
3126 		// Flat shaded so give each vertex the same colour
3127 		setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3128 
3129 		// Give the GTE some time to recover
3130 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3131 
3132 		// Put it into the global ot at the correct place
3133 		myAddPrimClip(z0, drawpacket);
3134 
3135 		// advance the global packet pointer by correct amount
3136 		myAddPacket(sizeof(POLY_F3));
3137 	}
3138 }
3139 
3140 // Fast: no options, Gouraud, Un-Textured, Lit, triangles
fastDrawGUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3141 void fastDrawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3142 	SVECTOR *n0;
3143 	SVECTOR *n1;
3144 	SVECTOR *n2;
3145 	SVECTORPC *v0;
3146 	SVECTORPC *v1;
3147 	SVECTORPC *v2;
3148 
3149 	uint32 tmp;
3150 	int32 flag;
3151 	uint32 i;
3152 	uint32 *pPoly;
3153 	int32 z0;
3154 	SVECTORPC sxy0, sxy1, sxy2;
3155 
3156 	// Base colour for gouraud shading computation
3157 	// Could easily be specified per polygon
3158 	CVECTOR rgbIn = {128, 128, 128, 0};
3159 	CVECTOR rgb0, rgb1, rgb2;
3160 
3161 	pPoly = polyStart;
3162 	// Loop over each polygon
3163 	for (i = 0; i < n; i++) {
3164 		// Structure is :
3165 		// 8-bits | 8-bits | 8-bits | 8-bits
3166 		// 0x20   | Blue   | Green  | Red
3167 		// 16-bits | 8-bits | 8-bits
3168 		// --------------------------
3169 		//  v0              | n0
3170 		//  v1              | n1
3171 		//  v2              | n2
3172 		tmp = *pPoly++;
3173 		// code0 = tmp >> 24;
3174 		rgbIn.r = (uint8)(tmp & 0xFF);
3175 		rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
3176 		rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
3177 
3178 		tmp = *pPoly++;
3179 		v0 = pVertex + (tmp >> 16);
3180 		n0 = pNormal + (tmp & 0xFFFF);
3181 
3182 		tmp = *pPoly++;
3183 		v1 = pVertex + (tmp >> 16);
3184 		n1 = pNormal + (tmp & 0xFFFF);
3185 
3186 		tmp = *pPoly++;
3187 		v2 = pVertex + (tmp >> 16);
3188 		n2 = pNormal + (tmp & 0xFFFF);
3189 
3190 		// Now do RotTransPers3 on the vectors
3191 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3192 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3193 
3194 		// test the return value of flag
3195 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
3196 		// The flag value is set to 0x8000 or 0 in the pad structure
3197 		if (v0->pad != 0)
3198 			continue;
3199 		if (v1->pad != 0)
3200 			continue;
3201 		if (v2->pad != 0)
3202 			continue;
3203 
3204 		// use winding order of the polygons
3205 		// e.g. NormalClip which is cross product of screen vectors
3206 		sxy0.vx = v0->vx;
3207 		sxy0.vy = v0->vy;
3208 		sxy1.vx = v1->vx;
3209 		sxy1.vy = v1->vy;
3210 		sxy2.vx = v2->vx;
3211 		sxy2.vy = v2->vy;
3212 
3213 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3214 		if (flag <= 0)
3215 			continue;
3216 
3217 		// Do the full gouraud computation
3218 		// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
3219 		LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
3220 
3221 		POLY_G3 *poly = (POLY_G3 *)drawpacket;
3222 		// Draw untextured polygons
3223 		setPolyG3(poly);
3224 		// set XY's in the GPU packet 0-1-2
3225 		poly->x0 = sxy0.vx;
3226 		poly->y0 = sxy0.vy;
3227 		poly->x1 = sxy1.vx;
3228 		poly->y1 = sxy1.vy;
3229 		poly->x2 = sxy2.vx;
3230 		poly->y2 = sxy2.vy;
3231 
3232 		setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3233 		setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
3234 		setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
3235 
3236 		// Give the GTE some time to recover
3237 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3238 
3239 		// Put it into the global ot at the correct place
3240 		myAddPrimClip(z0, drawpacket);
3241 		// advance the global packet pointer by correct amount
3242 		myAddPacket(sizeof(POLY_G3));
3243 	}
3244 }
3245 
3246 //------------------------------------------------------------------------
3247 
3248 // Fast: no options, Flat, Textured, Lit Triangles
fastDrawFTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3249 void fastDrawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3250 	SVECTOR *n0;
3251 	SVECTORPC *v0;
3252 	SVECTORPC *v1;
3253 	SVECTORPC *v2;
3254 
3255 	uint16 uu0, uu1, uu2;
3256 	uint16 vv0, vv1, vv2;
3257 	uint32 tmp;
3258 	int32 flag;
3259 	uint32 i;
3260 	uint32 *pPoly;
3261 	int32 z0;
3262 	SVECTORPC sxy0, sxy1, sxy2;
3263 	uint32 uv0, uv1, uv2;
3264 
3265 	// Base colour for shading computation
3266 	// Could easily be specified per polygon
3267 	CVECTOR rgbIn = {128, 128, 128, 0};
3268 	CVECTOR rgb0;
3269 
3270 	pPoly = polyStart;
3271 	// Loop over each polygon
3272 	for (i = 0; i < n; i++) {
3273 		// Structure is :
3274 		// Bit 31 ----> Bit 0
3275 		//
3276 		// 16-bits | 16-bits
3277 		// --------------------------
3278 		// v0      | u0
3279 		// v1      | u1
3280 		// v2      | u2
3281 		// --------------------------
3282 		//  v0     | n0
3283 		//  v2     | v1
3284 		uv0 = *pPoly++;
3285 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
3286 		uu0 = (uint16)(uv0 & 0xFFFF);
3287 
3288 		uv1 = *pPoly++;
3289 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
3290 		uu1 = (uint16)(uv1 & 0xFFFF);
3291 
3292 		uv2 = *pPoly++;
3293 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
3294 		uu2 = (uint16)(uv2 & 0xFFFF);
3295 
3296 		tmp = *pPoly++;
3297 		v0 = pVertex + (tmp >> 16);
3298 		n0 = pNormal + (tmp & 0xFFFF);
3299 
3300 		tmp = *pPoly++;
3301 		v1 = pVertex + (tmp & 0xFFFF);
3302 		v2 = pVertex + (tmp >> 16);
3303 
3304 		// Now do RotTransPers3 on the vectors
3305 		// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3306 		// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3307 
3308 		// test the return value of flag
3309 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
3310 		// The flag value is set to 0x8000 or 0 in the pad structure
3311 		if (v0->pad != 0)
3312 			continue;
3313 		if (v1->pad != 0)
3314 			continue;
3315 		if (v2->pad != 0)
3316 			continue;
3317 
3318 		// use winding order of the polygons
3319 		// e.g. NormalClip which is cross product of screen vectors
3320 		sxy0.vx = v0->vx;
3321 		sxy0.vy = v0->vy;
3322 		sxy1.vx = v1->vx;
3323 		sxy1.vy = v1->vy;
3324 		sxy2.vx = v2->vx;
3325 		sxy2.vy = v2->vy;
3326 
3327 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3328 		if (flag <= 0)
3329 			continue;
3330 
3331 		// Do the full gouraud computation
3332 		// NormalColorCol( n0, &rgbIn, &rgb0 );
3333 		LIGHTPOLYGON(n0, &rgbIn, &rgb0);
3334 
3335 		POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
3336 		setPolyFT3(poly);
3337 		// set XY's in the GPU packet 0-1-2
3338 		poly->x0 = sxy0.vx;
3339 		poly->y0 = sxy0.vy;
3340 		poly->x1 = sxy1.vx;
3341 		poly->y1 = sxy1.vy;
3342 		poly->x2 = sxy2.vx;
3343 		poly->y2 = sxy2.vy;
3344 
3345 		setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3346 		setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3347 
3348 		// Give the GTE some time to recover
3349 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3350 
3351 		// Put it into the global ot at the correct place
3352 		myAddPrimClip(z0, drawpacket);
3353 		// advance the global packet pointer by correct amount
3354 		myAddPacket(sizeof(POLY_FT3));
3355 	}
3356 }
3357 
3358 // Fast : no options : Gouraud, Textured, Lit Triangles
fastDrawGTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3359 void fastDrawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3360 	SVECTOR *n0;
3361 	SVECTOR *n1;
3362 	SVECTOR *n2;
3363 	SVECTORPC *v0;
3364 	SVECTORPC *v1;
3365 	SVECTORPC *v2;
3366 
3367 	uint16 uu0;
3368 	uint16 uu1;
3369 	uint16 uu2;
3370 	uint16 vv0;
3371 	uint16 vv1;
3372 	uint16 vv2;
3373 	int32 flag;
3374 	uint32 i;
3375 	int32 z0;
3376 	uint32 uv0;
3377 	uint32 uv1;
3378 	uint32 uv2;
3379 	uint32 vt0;
3380 	uint32 vt1;
3381 	uint32 vt2;
3382 	SVECTORPC sxy0;
3383 	SVECTORPC sxy1;
3384 	SVECTORPC sxy2;
3385 	int32 pad0;
3386 	int32 pad1;
3387 	int32 pad2;
3388 
3389 	// Base colour for gouraud shading computation
3390 	// Could easily be specified per polygon
3391 	CVECTOR rgbIn = {128, 128, 128, 0};
3392 	CVECTOR rgb0, rgb1, rgb2;
3393 
3394 	POLY_GT3 *poly;
3395 	uint32 *pPoly;
3396 
3397 	pPoly = polyStart;
3398 	// Loop over each polygon
3399 	for (i = 0; i < n; i++) {
3400 		// Structure is :
3401 		// v0, u0
3402 		// v1, u1
3403 		// v2, u2
3404 		// v0     | n0
3405 		// v1     | n1
3406 		// v2     | n2
3407 
3408 		uv0 = *(pPoly++);
3409 		vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
3410 		uu0 = (uint16)(uv0 & 0xFFFF);
3411 
3412 		uv1 = *(pPoly++);
3413 		vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
3414 		uu1 = (uint16)(uv1 & 0xFFFF);
3415 
3416 		uv2 = *(pPoly++);
3417 		vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
3418 		uu2 = (uint16)(uv2 & 0xFFFF);
3419 
3420 		vt0 = *(pPoly++);
3421 		v0 = (pVertex + (vt0 >> 16));
3422 		n0 = (pNormal + (vt0 & 0xFFFF));
3423 
3424 		vt1 = *(pPoly++);
3425 		v1 = (pVertex + (vt1 >> 16));
3426 		n1 = (pNormal + (vt1 & 0xFFFF));
3427 
3428 		vt2 = *(pPoly++);
3429 		v2 = (pVertex + (vt2 >> 16));
3430 		n2 = (pNormal + (vt2 & 0xFFFF));
3431 
3432 		// The vertices have been pre-transformed into screen space and stored in the vertex pool
3433 		// The flag value is set to 0x8000 or 0 in the pad structure
3434 		pad0 = v0->pad;
3435 		pad1 = v1->pad;
3436 		pad2 = v2->pad;
3437 		flag = pad0 | pad1 | pad2;
3438 
3439 		if (flag != 0)
3440 			continue;
3441 
3442 		// use winding order of the polygons
3443 		// e.g. NormalClip which is cross product of screen vectors
3444 		sxy0.vx = v0->vx;
3445 		sxy0.vy = v0->vy;
3446 		sxy1.vx = v1->vx;
3447 		sxy1.vy = v1->vy;
3448 		sxy2.vx = v2->vx;
3449 		sxy2.vy = v2->vy;
3450 
3451 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3452 
3453 		// Give the GTE some time to recover
3454 
3455 		// Ignore polygons which are too small
3456 		if (flag <= 0)
3457 			continue;
3458 
3459 		// Do the full gouraud computation
3460 		LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
3461 
3462 		// Try to overlap this with the LIGHTPOLYGON3 !
3463 		poly = (POLY_GT3 *)drawpacket;
3464 		setPolyGT3(poly);
3465 		// set XY's in the GPU packet 0-1-2
3466 		poly->x0 = sxy0.vx;
3467 		poly->y0 = sxy0.vy;
3468 		poly->x1 = sxy1.vx;
3469 		poly->y1 = sxy1.vy;
3470 		poly->x2 = sxy2.vx;
3471 		poly->y2 = sxy2.vy;
3472 
3473 		// Give the GTE some time to recover
3474 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3475 
3476 		setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3477 
3478 		setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3479 		setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
3480 		setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
3481 
3482 		// Put it into the global ot at the correct place
3483 		myAddPrimClip(z0, drawpacket);
3484 
3485 		// advance the global packet pointer by correct amount
3486 		myAddPacket(sizeof(POLY_GT3));
3487 	}
3488 }
3489 
3490 // For mucking about with lighting
3491 // Draw a solid bounding box around the actor (and so obscuring him)
3492 // but then have the box respond to the lights e.g. give it normals
3493 // and do flat & goraud shading
3494 // Assume the GTE lighting registers to be pre-prepared
3495 
3496 #if CD_MODE == 0
3497 
drawSolidBboxPC(SVECTOR * scrn,CVECTOR * rgbIn)3498 void drawSolidBboxPC(SVECTOR *scrn, CVECTOR *rgbIn) {
3499 	// 6 POLY_F4's i.e. 6 faces
3500 	// The 8 verticies are:
3501 	// 0 { xmin, ymin, zmin },
3502 	// 1 { xmin, ymin, zmax },
3503 	// 2 { xmax, ymin, zmin },
3504 	// 3 { xmax, ymin, zmax },
3505 	// 4 { xmax, ymax, zmin },
3506 	// 5 { xmax, ymax, zmax },
3507 	// 6 { xmin, ymax, zmin },
3508 	// 7 { xmin, ymax, zmax }
3509 
3510 	// The 6 faces are the following vertex links:
3511 	// ymin face : 0->1->3->2
3512 	// xmax face : 2->3->5->4
3513 	// zmin face : 0->2->4->6
3514 	// xmin face : 0->6->7->1
3515 	// zmax face : 1->7->5->3
3516 	// ymax face : 6->4->5->7
3517 
3518 	// The 6 face normals are (normal points into front side of face on PSX)
3519 	// ymin face : 0,+4096,0 +ve y
3520 	// xmax face : -4096,0,0 -ve x
3521 	// zmin face : 0,0,+4096 +ve z
3522 	// xmin face : +4096,0,0 +ve x
3523 	// zmax face : 0,0,-4096 -ve z
3524 	// ymax face : 0,-4096,0 -ve y
3525 
3526 	int32 z0, flag;
3527 	SVECTOR normal;
3528 	CVECTOR rgb;
3529 	POLY_F4 *face = NULL;
3530 
3531 	gte_NormalClip_pc(&(scrn[0]), &(scrn[1]), &(scrn[2]), &flag);
3532 	if (flag > 0) {
3533 		face = (POLY_F4 *)drawpacket;
3534 		setPolyF4(face);
3535 		// ymin face normal : 0,+4096,0 +ve y
3536 		normal.vx = 0;
3537 		normal.vy = 4096;
3538 		normal.vz = 0;
3539 		if (_drawLit) {
3540 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3541 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3542 		} else {
3543 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3544 		}
3545 		// ymin face : 0->1->3->2 : note PSX is 0-1-3-2 for a quad
3546 		setXY4(face, scrn[0].vx, scrn[0].vy, scrn[1].vx, scrn[1].vy, scrn[2].vx, scrn[2].vy, scrn[3].vx, scrn[3].vy);
3547 
3548 		z0 = (scrn[0].vz + scrn[1].vz + scrn[2].vz + scrn[3].vz) / 4;
3549 		z0 = myAddPrimClip(z0, drawpacket);
3550 		myAddPacket(sizeof(POLY_F4));
3551 	}
3552 
3553 	gte_NormalClip_pc(&(scrn[2]), &(scrn[3]), &(scrn[4]), &flag);
3554 	if (flag > 0) {
3555 		// xmax face : 2->3->5->4 : note PSX is 0-1-3-2 for a quad
3556 		face = (POLY_F4 *)drawpacket;
3557 		setPolyF4(face);
3558 		// xmax face : -4096,0,0 -ve x
3559 		normal.vx = -4096;
3560 		normal.vy = 0;
3561 		normal.vz = 0;
3562 		if (_drawLit) {
3563 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3564 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3565 		} else {
3566 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3567 		}
3568 		setXY4(face, scrn[2].vx, scrn[2].vy, scrn[3].vx, scrn[3].vy, scrn[4].vx, scrn[4].vy, scrn[5].vx, scrn[5].vy);
3569 		z0 = (scrn[2].vz + scrn[3].vz + scrn[4].vz + scrn[5].vz) / 4;
3570 		z0 = myAddPrimClip(z0, drawpacket);
3571 		myAddPacket(sizeof(POLY_F4));
3572 	}
3573 
3574 	gte_NormalClip_pc(&(scrn[0]), &(scrn[2]), &(scrn[4]), &flag);
3575 	if (flag > 0) {
3576 		// zmin face : 0->2->4->6 : note PSX is 0-1-3-2 for a quad
3577 		face = (POLY_F4 *)drawpacket;
3578 		setPolyF4(face);
3579 		// zmin face : 0,0,+4096 +ve z
3580 		normal.vx = 0;
3581 		normal.vy = 0;
3582 		normal.vz = 4096;
3583 		if (_drawLit) {
3584 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3585 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3586 		} else {
3587 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3588 		}
3589 		setXY4(face, scrn[0].vx, scrn[0].vy, scrn[2].vx, scrn[2].vy, scrn[6].vx, scrn[6].vy, scrn[4].vx, scrn[4].vy);
3590 		z0 = (scrn[0].vz + scrn[2].vz + scrn[4].vz + scrn[6].vz) / 4;
3591 		z0 = myAddPrimClip(z0, drawpacket);
3592 		myAddPacket(sizeof(POLY_F4));
3593 	}
3594 
3595 	gte_NormalClip_pc(&(scrn[0]), &(scrn[6]), &(scrn[7]), &flag);
3596 	if (flag > 0) {
3597 		// xmin face : 0->6->7->1 : note PSX is 0-1-3-2 for a quad
3598 		face = (POLY_F4 *)drawpacket;
3599 		setPolyF4(face);
3600 		// xmin face : +4096,0,0 +ve x
3601 		normal.vx = 0;
3602 		normal.vy = 0;
3603 		normal.vz = 4096;
3604 		if (_drawLit) {
3605 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3606 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3607 		} else {
3608 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3609 		}
3610 		setXY4(face, scrn[0].vx, scrn[0].vy, scrn[6].vx, scrn[6].vy, scrn[1].vx, scrn[1].vy, scrn[7].vx, scrn[7].vy);
3611 		z0 = myAddPrimClip(scrn[7].vz, drawpacket);
3612 		myAddPacket(sizeof(POLY_F4));
3613 	}
3614 
3615 	gte_NormalClip_pc(&(scrn[1]), &(scrn[7]), &(scrn[5]), &flag);
3616 	if (flag > 0) {
3617 		// zmax face : 1->7->5->3 : note PSX is 0-1-3-2 for a quad
3618 		face = (POLY_F4 *)drawpacket;
3619 		setPolyF4(face);
3620 		// zmax face : 0,0,-4096 -ve z
3621 		normal.vx = 0;
3622 		normal.vy = 0;
3623 		normal.vz = -4096;
3624 		if (_drawLit) {
3625 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3626 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3627 		} else {
3628 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3629 		}
3630 		setXY4(face, scrn[1].vx, scrn[1].vy, scrn[7].vx, scrn[7].vy, scrn[3].vx, scrn[3].vy, scrn[5].vx, scrn[5].vy);
3631 		z0 = (scrn[1].vz + scrn[3].vz + scrn[5].vz + scrn[7].vz) / 4;
3632 		z0 = myAddPrimClip(z0, drawpacket);
3633 		myAddPacket(sizeof(POLY_F4));
3634 	}
3635 
3636 	gte_NormalClip_pc(&(scrn[6]), &(scrn[4]), &(scrn[5]), &flag);
3637 	if (flag > 0) {
3638 		// ymax face : 6->4->5->7 : note PSX is 0-1-3-2 for a quad
3639 		face = (POLY_F4 *)drawpacket;
3640 		setPolyF4(face);
3641 		// ymax face : 0,-4096,0 -ve y
3642 		normal.vx = 0;
3643 		normal.vy = -4096;
3644 		normal.vz = 0;
3645 		if (_drawLit) {
3646 			LIGHTPOLYGON(&normal, rgbIn, &rgb);
3647 			setRGB0(face, rgb.r, rgb.g, rgb.b);
3648 		} else {
3649 			setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3650 		}
3651 		setXY4(face, scrn[6].vx, scrn[6].vy, scrn[4].vx, scrn[4].vy, scrn[7].vx, scrn[7].vy, scrn[5].vx, scrn[5].vy);
3652 		z0 = (scrn[4].vz + scrn[5].vz + scrn[6].vz + scrn[7].vz) / 4;
3653 		z0 = myAddPrimClip(z0, drawpacket);
3654 		myAddPacket(sizeof(POLY_F4));
3655 	}
3656 }
3657 
3658 #endif // #if CD_MODE == 0
3659 
3660 // Simple flat untextured triangles
3661 // draw backfacing triangles as well
3662 // the colour is set by a global variable
fastDrawTRI3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)3663 void fastDrawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
3664 	SVECTORPC *v0;
3665 	SVECTORPC *v1;
3666 	SVECTORPC *v2;
3667 
3668 	int32 flag;
3669 	uint32 i;
3670 	uint32 *pPoly;
3671 	int32 z0;
3672 	SVECTORPC sxy0, sxy1, sxy2, stemp;
3673 	uint32 tmp;
3674 
3675 	pPoly = polyStart;
3676 	// Loop over each polygon
3677 	for (i = 0; i < n; i++) {
3678 		// Each polygon is 2 32-bit WORDS
3679 		// Bit 31 ----> Bit 0
3680 		//
3681 		// 16-bits | 16-bits
3682 		// --------------------------
3683 		//  v1     | v0
3684 		//  pad    | v2
3685 
3686 		tmp = *pPoly++;
3687 		v0 = pVertex + (tmp & 0xFFFF);
3688 		v1 = pVertex + (tmp >> 16);
3689 
3690 		tmp = *pPoly++;
3691 		v2 = pVertex + (tmp & 0xFFFF);
3692 
3693 		flag = (v0->pad) | (v1->pad) | (v2->pad);
3694 		if (flag != 0)
3695 			continue;
3696 
3697 		// use winding order of the polygons
3698 		// e.g. NormalClip which is cross product of screen vectors
3699 		sxy0.vx = v0->vx;
3700 		sxy0.vy = v0->vy;
3701 		sxy1.vx = v1->vx;
3702 		sxy1.vy = v1->vy;
3703 		sxy2.vx = v2->vx;
3704 		sxy2.vy = v2->vy;
3705 
3706 		// See what winding order this polygon is ?
3707 		gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3708 
3709 		// Drawing back facing polys requires making them have
3710 		// clockwise winding order as by definition they have
3711 		// anti-clockwise winding order
3712 		if (flag < 0) {
3713 			stemp = sxy1;
3714 			sxy1 = sxy2;
3715 			sxy2 = stemp;
3716 		}
3717 
3718 		// Give the GTE some time to recover
3719 		gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3720 
3721 		// Draw untextured polygons
3722 		TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
3723 		setTPolyF3(poly);
3724 		setTABRMode(poly, 2);   // 2 = back - front
3725 		setTSemiTrans(poly, 1); // 1 = enable semi-transparency
3726 
3727 		// set XY's in the GPU packet 0-1-2
3728 		poly->x0 = sxy0.vx;
3729 		poly->y0 = sxy0.vy;
3730 		poly->x1 = sxy1.vx;
3731 		poly->y1 = sxy1.vy;
3732 		poly->x2 = sxy2.vx;
3733 		poly->y2 = sxy2.vy;
3734 
3735 		// Set the RGB colours
3736 		// No light source calculation
3737 		// So just set base colour
3738 		setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
3739 		poly->code = unlitPoly.cd;
3740 
3741 		myAddPrimClip(z0, drawpacket);
3742 
3743 		// advance the global packet pointer by correct amount
3744 		myAddPacket(sizeof(TPOLY_F3));
3745 	}
3746 }
3747 
3748 } // End of namespace ICB
3749