Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_polyse.c (39385B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // d_polyset.c: routines for drawing sets of polygons sharing the same
     21 // texture (used for Alias models)
     22 
     23 #include "r_local.h"
     24 
     25 int	rand1k[] = {
     26 #include "rand1k.h"
     27 };
     28 
     29 #define MASK_1K	0x3FF
     30 
     31 int		rand1k_index = 0;
     32 
     33 // TODO: put in span spilling to shrink list size
     34 // !!! if this is changed, it must be changed in d_polysa.s too !!!
     35 #define DPS_MAXSPANS			MAXHEIGHT+1	
     36 									// 1 extra for spanpackage that marks end
     37 
     38 // !!! if this is changed, it must be changed in asm_draw.h too !!!
     39 typedef struct {
     40 	void			*pdest;
     41 	short			*pz;
     42 	int				count;
     43 	byte			*ptex;
     44 	int				sfrac, tfrac, light, zi;
     45 } spanpackage_t;
     46 
     47 typedef struct {
     48 	int		isflattop;
     49 	int		numleftedges;
     50 	int		*pleftedgevert0;
     51 	int		*pleftedgevert1;
     52 	int		*pleftedgevert2;
     53 	int		numrightedges;
     54 	int		*prightedgevert0;
     55 	int		*prightedgevert1;
     56 	int		*prightedgevert2;
     57 } edgetable;
     58 
     59 aliastriangleparms_t aliastriangleparms;
     60 
     61 int	r_p0[6], r_p1[6], r_p2[6];
     62 
     63 byte		*d_pcolormap;
     64 
     65 int			d_aflatcolor;
     66 int			d_xdenom;
     67 
     68 edgetable	*pedgetable;
     69 
     70 edgetable	edgetables[12] = {
     71 	{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
     72 	{0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, NULL},
     73 	{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
     74 	{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
     75 	{0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, NULL},
     76 	{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
     77 	{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
     78 	{0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, NULL},
     79 	{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
     80 	{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
     81 	{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
     82 	{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
     83 };
     84 
     85 // FIXME: some of these can become statics
     86 int				a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
     87 int				r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
     88 int				r_zistepx, r_zistepy;
     89 int				d_aspancount, d_countextrastep;
     90 
     91 spanpackage_t			*a_spans;
     92 spanpackage_t			*d_pedgespanpackage;
     93 static int				ystart;
     94 byte					*d_pdest, *d_ptex;
     95 short					*d_pz;
     96 int						d_sfrac, d_tfrac, d_light, d_zi;
     97 int						d_ptexextrastep, d_sfracextrastep;
     98 int						d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
     99 int						d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
    100 int						d_sfracbasestep, d_tfracbasestep;
    101 int						d_ziextrastep, d_zibasestep;
    102 int						d_pzextrastep, d_pzbasestep;
    103 
    104 typedef struct {
    105 	int		quotient;
    106 	int		remainder;
    107 } adivtab_t;
    108 
    109 static adivtab_t	adivtab[32*32] = {
    110 #include "adivtab.h"
    111 };
    112 
    113 byte	*skintable[MAX_LBM_HEIGHT];
    114 int		skinwidth;
    115 byte	*skinstart;
    116 
    117 void	(*d_pdrawspans)(spanpackage_t *pspanpackage);
    118 
    119 void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage);
    120 void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage);
    121 void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage);
    122 
    123 void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage);
    124 void R_PolysetCalcGradients (int skinwidth);
    125 void R_DrawNonSubdiv (void);
    126 void R_PolysetSetEdgeTable (void);
    127 void R_RasterizeAliasPolySmooth (void);
    128 void R_PolysetScanLeftEdge(int height);
    129 void R_PolysetScanLeftEdge_C(int height);
    130 
    131 // ======================
    132 // PGM
    133 // 64 65 66 67 68 69 70 71   72 73 74 75 76 77 78 79
    134 byte iractive = 0;
    135 byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72,		// black/white
    136 					  71, 70, 69, 68, 67, 66, 65, 64,
    137 					  64, 65, 66, 67, 68, 69, 70, 71,		// dark taupe
    138 					  72, 73, 74, 75, 76, 77, 78, 79,
    139 
    140 					  64, 65, 66, 67, 68, 69, 70, 71,		// slate grey
    141 					  72, 73, 74, 75, 76, 77, 78, 79,
    142 					  208, 208, 208, 208, 208, 208, 208, 208,	// unused?'
    143 					  64, 66, 68, 70, 72, 74, 76, 78,		// dark yellow
    144 					  
    145 					  64, 65, 66, 67, 68, 69, 70, 71,		// dark red
    146 					  72, 73, 74, 75, 76, 77, 78, 79,
    147 					  64, 65, 66, 67, 68, 69, 70, 71,		// grey/tan
    148 					  72, 73, 74, 75, 76, 77, 78, 79,
    149 
    150 					  64, 66, 68, 70, 72, 74, 76, 78,		// chocolate
    151 					  68, 67, 66, 65, 64, 65, 66, 67,		// mauve / teal
    152 					  68, 69, 70, 71, 72, 73, 74, 75,
    153 					  76, 76, 77, 77, 78, 78, 79, 79,		
    154 
    155 					  64, 65, 66, 67, 68, 69, 70, 71,		// more mauve
    156 					  72, 73, 74, 75, 76, 77, 78, 79,
    157 					  64, 65, 66, 67, 68, 69, 70, 71,		// olive
    158 					  72, 73, 74, 75, 76, 77, 78, 79,
    159 
    160 					  64, 65, 66, 67, 68, 69, 70, 71,		// maroon
    161 					  72, 73, 74, 75, 76, 77, 78, 79,
    162 					  64, 65, 66, 67, 68, 69, 70, 71,		// sky blue
    163 					  72, 73, 74, 75, 76, 77, 78, 79,
    164 					  
    165 					  64, 65, 66, 67, 68, 69, 70, 71,		// olive again
    166 					  72, 73, 74, 75, 76, 77, 78, 79,
    167 					  64, 65, 66, 67, 68, 69, 70, 71,		// nuclear green
    168 					  64, 65, 66, 67, 68, 69, 70, 71,		// bright yellow
    169 
    170 					  64, 65, 66, 67, 68, 69, 70, 71,		// fire colors
    171 					  72, 73, 74, 75, 76, 77, 78, 79,
    172 					  208, 208, 64, 64, 70, 71, 72, 64,		// mishmash1
    173 					  66, 68, 70, 64, 65, 66, 67, 68};		// mishmash2
    174 // PGM
    175 // ======================
    176 
    177 /*
    178 ================
    179 R_PolysetUpdateTables
    180 ================
    181 */
    182 void R_PolysetUpdateTables (void)
    183 {
    184 	int		i;
    185 	byte	*s;
    186 	
    187 	if (r_affinetridesc.skinwidth != skinwidth ||
    188 		r_affinetridesc.pskin != skinstart)
    189 	{
    190 		skinwidth = r_affinetridesc.skinwidth;
    191 		skinstart = r_affinetridesc.pskin;
    192 		s = skinstart;
    193 		for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
    194 			skintable[i] = s;
    195 	}
    196 }
    197 
    198 
    199 /*
    200 ================
    201 R_DrawTriangle
    202 ================
    203 */
    204 void R_DrawTriangle( void )
    205 {
    206 	spanpackage_t spans[DPS_MAXSPANS];
    207 
    208 	int dv1_ab, dv0_ac;
    209 	int dv0_ab, dv1_ac;
    210 
    211 	/*
    212 	d_xdenom = ( aliastriangleparms.a->v[1] - aliastriangleparms.b->v[1] ) * ( aliastriangleparms.a->v[0] - aliastriangleparms.c->v[0] ) -
    213 			   ( aliastriangleparms.a->v[0] - aliastriangleparms.b->v[0] ) * ( aliastriangleparms.a->v[1] - aliastriangleparms.c->v[1] );
    214 	*/
    215 
    216 	dv0_ab = aliastriangleparms.a->u - aliastriangleparms.b->u;
    217 	dv1_ab = aliastriangleparms.a->v - aliastriangleparms.b->v;
    218 
    219 	if ( !( dv0_ab | dv1_ab ) )
    220 		return;
    221 
    222 	dv0_ac = aliastriangleparms.a->u - aliastriangleparms.c->u;
    223 	dv1_ac = aliastriangleparms.a->v - aliastriangleparms.c->v;
    224 
    225 	if ( !( dv0_ac | dv1_ac ) )
    226 		return;
    227 
    228 	d_xdenom = ( dv0_ac * dv1_ab ) - ( dv0_ab * dv1_ac );
    229 
    230 	if ( d_xdenom < 0 )
    231 	{
    232 		a_spans = spans;
    233 
    234 		r_p0[0] = aliastriangleparms.a->u;		// u
    235 		r_p0[1] = aliastriangleparms.a->v;		// v
    236 		r_p0[2] = aliastriangleparms.a->s;		// s
    237 		r_p0[3] = aliastriangleparms.a->t;		// t
    238 		r_p0[4] = aliastriangleparms.a->l;		// light
    239 		r_p0[5] = aliastriangleparms.a->zi;		// iz
    240 
    241 		r_p1[0] = aliastriangleparms.b->u;
    242 		r_p1[1] = aliastriangleparms.b->v;
    243 		r_p1[2] = aliastriangleparms.b->s;
    244 		r_p1[3] = aliastriangleparms.b->t;
    245 		r_p1[4] = aliastriangleparms.b->l;
    246 		r_p1[5] = aliastriangleparms.b->zi;
    247 
    248 		r_p2[0] = aliastriangleparms.c->u;
    249 		r_p2[1] = aliastriangleparms.c->v;
    250 		r_p2[2] = aliastriangleparms.c->s;
    251 		r_p2[3] = aliastriangleparms.c->t;
    252 		r_p2[4] = aliastriangleparms.c->l;
    253 		r_p2[5] = aliastriangleparms.c->zi;
    254 
    255 		R_PolysetSetEdgeTable ();
    256 		R_RasterizeAliasPolySmooth ();
    257 	}
    258 }
    259 
    260 
    261 /*
    262 ===================
    263 R_PolysetScanLeftEdge_C
    264 ====================
    265 */
    266 void R_PolysetScanLeftEdge_C(int height)
    267 {
    268 	do
    269 	{
    270 		d_pedgespanpackage->pdest = d_pdest;
    271 		d_pedgespanpackage->pz = d_pz;
    272 		d_pedgespanpackage->count = d_aspancount;
    273 		d_pedgespanpackage->ptex = d_ptex;
    274 
    275 		d_pedgespanpackage->sfrac = d_sfrac;
    276 		d_pedgespanpackage->tfrac = d_tfrac;
    277 
    278 	// FIXME: need to clamp l, s, t, at both ends?
    279 		d_pedgespanpackage->light = d_light;
    280 		d_pedgespanpackage->zi = d_zi;
    281 
    282 		d_pedgespanpackage++;
    283 
    284 		errorterm += erroradjustup;
    285 		if (errorterm >= 0)
    286 		{
    287 			d_pdest += d_pdestextrastep;
    288 			d_pz += d_pzextrastep;
    289 			d_aspancount += d_countextrastep;
    290 			d_ptex += d_ptexextrastep;
    291 			d_sfrac += d_sfracextrastep;
    292 			d_ptex += d_sfrac >> 16;
    293 
    294 			d_sfrac &= 0xFFFF;
    295 			d_tfrac += d_tfracextrastep;
    296 			if (d_tfrac & 0x10000)
    297 			{
    298 				d_ptex += r_affinetridesc.skinwidth;
    299 				d_tfrac &= 0xFFFF;
    300 			}
    301 			d_light += d_lightextrastep;
    302 			d_zi += d_ziextrastep;
    303 			errorterm -= erroradjustdown;
    304 		}
    305 		else
    306 		{
    307 			d_pdest += d_pdestbasestep;
    308 			d_pz += d_pzbasestep;
    309 			d_aspancount += ubasestep;
    310 			d_ptex += d_ptexbasestep;
    311 			d_sfrac += d_sfracbasestep;
    312 			d_ptex += d_sfrac >> 16;
    313 			d_sfrac &= 0xFFFF;
    314 			d_tfrac += d_tfracbasestep;
    315 			if (d_tfrac & 0x10000)
    316 			{
    317 				d_ptex += r_affinetridesc.skinwidth;
    318 				d_tfrac &= 0xFFFF;
    319 			}
    320 			d_light += d_lightbasestep;
    321 			d_zi += d_zibasestep;
    322 		}
    323 	} while (--height);
    324 }
    325 
    326 /*
    327 ===================
    328 FloorDivMod
    329 
    330 Returns mathematically correct (floor-based) quotient and remainder for
    331 numer and denom, both of which should contain no fractional part. The
    332 quotient must fit in 32 bits.
    333 FIXME: GET RID OF THIS! (FloorDivMod)
    334 ====================
    335 */
    336 void FloorDivMod (float numer, float denom, int *quotient,
    337 		int *rem)
    338 {
    339 	int		q, r;
    340 	float	x;
    341 
    342 	if (numer >= 0.0)
    343 	{
    344 
    345 		x = floor(numer / denom);
    346 		q = (int)x;
    347 		r = (int)floor(numer - (x * denom));
    348 	}
    349 	else
    350 	{
    351 	//
    352 	// perform operations with positive values, and fix mod to make floor-based
    353 	//
    354 		x = floor(-numer / denom);
    355 		q = -(int)x;
    356 		r = (int)floor(-numer - (x * denom));
    357 		if (r != 0)
    358 		{
    359 			q--;
    360 			r = (int)denom - r;
    361 		}
    362 	}
    363 
    364 	*quotient = q;
    365 	*rem = r;
    366 }
    367 
    368 
    369 /*
    370 ===================
    371 R_PolysetSetUpForLineScan
    372 ====================
    373 */
    374 void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
    375 		fixed8_t endvertu, fixed8_t endvertv)
    376 {
    377 	float		dm, dn;
    378 	int			tm, tn;
    379 	adivtab_t	*ptemp;
    380 
    381 // TODO: implement x86 version
    382 
    383 	errorterm = -1;
    384 
    385 	tm = endvertu - startvertu;
    386 	tn = endvertv - startvertv;
    387 
    388 	if (((tm <= 16) && (tm >= -15)) &&
    389 		((tn <= 16) && (tn >= -15)))
    390 	{
    391 		ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
    392 		ubasestep = ptemp->quotient;
    393 		erroradjustup = ptemp->remainder;
    394 		erroradjustdown = tn;
    395 	}
    396 	else
    397 	{
    398 		dm = tm;
    399 		dn = tn;
    400 
    401 		FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
    402 
    403 		erroradjustdown = dn;
    404 	}
    405 }
    406 
    407 
    408 
    409 /*
    410 ================
    411 R_PolysetCalcGradients
    412 ================
    413 */
    414 #if id386 && !defined __linux__
    415 void R_PolysetCalcGradients( int skinwidth )
    416 {
    417 	static float xstepdenominv, ystepdenominv, t0, t1;
    418 	static float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
    419 	static float one = 1.0F, negative_one = -1.0F;
    420 	static unsigned long t0_int, t1_int;
    421 
    422 	extern unsigned long fpu_sp24_ceil_cw, fpu_ceil_cw, fpu_chop_cw;
    423 
    424 	/*
    425 	p00_minus_p20 = r_p0[0] - r_p2[0];
    426 	p01_minus_p21 = r_p0[1] - r_p2[1];
    427 	p10_minus_p20 = r_p1[0] - r_p2[0];
    428 	p11_minus_p21 = r_p1[1] - r_p2[1];
    429 	*/
    430 
    431 	__asm mov eax, dword ptr [r_p0+0]
    432 	__asm mov ebx, dword ptr [r_p0+4]
    433 	__asm sub eax, dword ptr [r_p2+0]
    434 	__asm sub ebx, dword ptr [r_p2+4]
    435 	__asm mov p00_minus_p20, eax
    436 	__asm mov p01_minus_p21, ebx
    437 	__asm fild dword ptr p00_minus_p20
    438 	__asm fild dword ptr p01_minus_p21
    439 	__asm mov eax, dword ptr [r_p1+0]
    440 	__asm mov ebx, dword ptr [r_p1+4]
    441 	__asm sub eax, dword ptr [r_p2+0]
    442 	__asm sub ebx, dword ptr [r_p2+4]
    443 	__asm fstp p01_minus_p21
    444 	__asm fstp p00_minus_p20
    445 	__asm mov p10_minus_p20, eax
    446 	__asm mov p11_minus_p21, ebx
    447 	__asm fild dword ptr p10_minus_p20
    448 	__asm fild dword ptr p11_minus_p21
    449 	__asm fstp p11_minus_p21
    450 	__asm fstp p10_minus_p20
    451 
    452 	/*
    453 	xstepdenominv = 1.0 / (float)d_xdenom;
    454 
    455 	ystepdenominv = -xstepdenominv;
    456 	*/
    457 
    458 	/*
    459 	** put FPU in single precision ceil mode
    460 	*/
    461 	__asm fldcw word ptr [fpu_sp24_ceil_cw]
    462 //	__asm fldcw word ptr [fpu_ceil_cw]
    463 
    464 	__asm fild  dword ptr d_xdenom    ; d_xdenom
    465 	__asm fdivr one                   ; 1 / d_xdenom
    466 	__asm fst   xstepdenominv         ; 
    467 	__asm fmul  negative_one          ; -( 1 / d_xdenom )
    468 
    469 // ceil () for light so positive steps are exaggerated, negative steps
    470 // diminished,  pushing us away from underflow toward overflow. Underflow is
    471 // very visible, overflow is very unlikely, because of ambient lighting
    472 	/*
    473 	t0 = r_p0[4] - r_p2[4];
    474 	t1 = r_p1[4] - r_p2[4];
    475 	r_lstepx = (int)
    476 			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
    477 	r_lstepy = (int)
    478 			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
    479 	*/
    480 	__asm mov   eax, dword ptr [r_p0+16]
    481 	__asm mov   ebx, dword ptr [r_p1+16]
    482 	__asm sub   eax, dword ptr [r_p2+16]
    483 	__asm sub   ebx, dword ptr [r_p2+16]
    484 
    485 	__asm fstp  ystepdenominv       ; (empty)
    486 
    487 	__asm mov   t0_int, eax
    488 	__asm mov   t1_int, ebx
    489 	__asm fild  t0_int              ; t0
    490 	__asm fild  t1_int              ; t1 | t0
    491 	__asm fxch  st(1)               ; t0 | t1
    492 	__asm fstp  t0                  ; t1
    493 	__asm fst   t1                  ; t1
    494 	__asm fmul  p01_minus_p21       ; t1 * p01_minus_p21
    495 	__asm fld   t0                  ; t0 | t1 * p01_minus_p21
    496 	__asm fmul  p11_minus_p21       ; t0 * p11_minus_p21 | t1 * p01_minus_p21
    497 	__asm fld   t1                  ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    498 	__asm fmul  p00_minus_p20       ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    499 	__asm fld   t0                  ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    500 	__asm fmul  p10_minus_p20       ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    501 	__asm fxch  st(2)               ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
    502 	__asm fsubp st(3), st           ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    503 	__asm fsubrp st(1), st          ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    504 	__asm fxch  st(1)               ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
    505 	__asm fmul  xstepdenominv       ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
    506 	__asm fxch  st(1)
    507 	__asm fmul  ystepdenominv       ; r_lstepy | r_lstepx
    508 	__asm fxch  st(1)               ; r_lstepx | r_lstepy
    509 	__asm fistp dword ptr [r_lstepx]
    510 	__asm fistp dword ptr [r_lstepy]
    511 
    512 	/*
    513 	** put FPU back into extended precision chop mode
    514 	*/
    515 	__asm fldcw word ptr [fpu_chop_cw]
    516 
    517 	/*
    518 	t0 = r_p0[2] - r_p2[2];
    519 	t1 = r_p1[2] - r_p2[2];
    520 	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    521 			xstepdenominv);
    522 	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
    523 			ystepdenominv);
    524 	*/
    525 	__asm mov eax, dword ptr [r_p0+8]
    526 	__asm mov ebx, dword ptr [r_p1+8]
    527 	__asm sub eax, dword ptr [r_p2+8]
    528 	__asm sub ebx, dword ptr [r_p2+8]
    529 	__asm mov   t0_int, eax
    530 	__asm mov   t1_int, ebx
    531 	__asm fild  t0_int              ; t0
    532 	__asm fild  t1_int              ; t1 | t0
    533 	__asm fxch  st(1)               ; t0 | t1
    534 	__asm fstp  t0                  ; t1
    535 	__asm fst   t1                  ; (empty)
    536 
    537 	__asm fmul  p01_minus_p21       ; t1 * p01_minus_p21
    538 	__asm fld   t0                  ; t0 | t1 * p01_minus_p21
    539 	__asm fmul  p11_minus_p21       ; t0 * p11_minus_p21 | t1 * p01_minus_p21
    540 	__asm fld   t1                  ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    541 	__asm fmul  p00_minus_p20       ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    542 	__asm fld   t0                  ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    543 	__asm fmul  p10_minus_p20       ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    544 	__asm fxch  st(2)               ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
    545 	__asm fsubp st(3), st           ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    546 	__asm fsubrp st(1), st           ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    547 	__asm fxch  st(1)               ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
    548 	__asm fmul  xstepdenominv       ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
    549 	__asm fxch  st(1)
    550 	__asm fmul  ystepdenominv       ; r_lstepy | r_lstepx
    551 	__asm fxch  st(1)               ; r_lstepx | r_lstepy
    552 	__asm fistp dword ptr [r_sstepx]
    553 	__asm fistp dword ptr [r_sstepy]
    554 
    555 	/*
    556 	t0 = r_p0[3] - r_p2[3];
    557 	t1 = r_p1[3] - r_p2[3];
    558 	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    559 			xstepdenominv);
    560 	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
    561 			ystepdenominv);
    562 	*/
    563 	__asm mov eax, dword ptr [r_p0+12]
    564 	__asm mov ebx, dword ptr [r_p1+12]
    565 	__asm sub eax, dword ptr [r_p2+12]
    566 	__asm sub ebx, dword ptr [r_p2+12]
    567 
    568 	__asm mov   t0_int, eax
    569 	__asm mov   t1_int, ebx
    570 	__asm fild  t0_int              ; t0
    571 	__asm fild  t1_int              ; t1 | t0
    572 	__asm fxch  st(1)               ; t0 | t1
    573 	__asm fstp  t0                  ; t1
    574 	__asm fst   t1                  ; (empty)
    575 
    576 	__asm fmul  p01_minus_p21       ; t1 * p01_minus_p21
    577 	__asm fld   t0                  ; t0 | t1 * p01_minus_p21
    578 	__asm fmul  p11_minus_p21       ; t0 * p11_minus_p21 | t1 * p01_minus_p21
    579 	__asm fld   t1                  ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    580 	__asm fmul  p00_minus_p20       ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    581 	__asm fld   t0                  ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    582 	__asm fmul  p10_minus_p20       ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    583 	__asm fxch  st(2)               ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
    584 	__asm fsubp st(3), st           ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    585 	__asm fsubrp st(1), st           ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    586 	__asm fxch  st(1)               ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
    587 	__asm fmul  xstepdenominv       ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
    588 	__asm fxch  st(1)
    589 	__asm fmul  ystepdenominv       ; r_lstepy | r_lstepx
    590 	__asm fxch  st(1)               ; r_lstepx | r_lstepy
    591 	__asm fistp dword ptr [r_tstepx]
    592 	__asm fistp dword ptr [r_tstepy]
    593 
    594 	/*
    595 	t0 = r_p0[5] - r_p2[5];
    596 	t1 = r_p1[5] - r_p2[5];
    597 	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    598 			xstepdenominv);
    599 	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
    600 			ystepdenominv);
    601 	*/
    602 	__asm mov eax, dword ptr [r_p0+20]
    603 	__asm mov ebx, dword ptr [r_p1+20]
    604 	__asm sub eax, dword ptr [r_p2+20]
    605 	__asm sub ebx, dword ptr [r_p2+20]
    606 
    607 	__asm mov   t0_int, eax
    608 	__asm mov   t1_int, ebx
    609 	__asm fild  t0_int              ; t0
    610 	__asm fild  t1_int              ; t1 | t0
    611 	__asm fxch  st(1)               ; t0 | t1
    612 	__asm fstp  t0                  ; t1
    613 	__asm fst   t1                  ; (empty)
    614 
    615 	__asm fmul  p01_minus_p21       ; t1 * p01_minus_p21
    616 	__asm fld   t0                  ; t0 | t1 * p01_minus_p21
    617 	__asm fmul  p11_minus_p21       ; t0 * p11_minus_p21 | t1 * p01_minus_p21
    618 	__asm fld   t1                  ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    619 	__asm fmul  p00_minus_p20       ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    620 	__asm fld   t0                  ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    621 	__asm fmul  p10_minus_p20       ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21
    622 	__asm fxch  st(2)               ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21
    623 	__asm fsubp st(3), st           ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    624 	__asm fsubrp st(1), st           ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21
    625 	__asm fxch  st(1)               ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20
    626 	__asm fmul  xstepdenominv       ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20
    627 	__asm fxch  st(1)
    628 	__asm fmul  ystepdenominv       ; r_lstepy | r_lstepx
    629 	__asm fxch  st(1)               ; r_lstepx | r_lstepy
    630 	__asm fistp dword ptr [r_zistepx]
    631 	__asm fistp dword ptr [r_zistepy]
    632 
    633 	/*
    634 #if	id386ALIAS
    635 	a_sstepxfrac = r_sstepx << 16;
    636 	a_tstepxfrac = r_tstepx << 16;
    637 #else
    638 	a_sstepxfrac = r_sstepx & 0xFFFF;
    639 	a_tstepxfrac = r_tstepx & 0xFFFF;
    640 #endif
    641 	*/
    642 	__asm mov eax, d_pdrawspans
    643 	__asm cmp eax, offset R_PolysetDrawSpans8_Opaque
    644 	__asm mov eax, r_sstepx
    645 	__asm mov ebx, r_tstepx
    646 	__asm jne translucent
    647 //#if id386ALIAS
    648 	__asm shl eax, 16
    649 	__asm shl ebx, 16
    650 	__asm jmp done_with_steps
    651 //#else
    652 translucent:
    653 	__asm and eax, 0ffffh
    654 	__asm and ebx, 0ffffh
    655 //#endif
    656 done_with_steps:
    657 	__asm mov a_sstepxfrac, eax
    658 	__asm mov a_tstepxfrac, ebx
    659 
    660 	/*
    661 	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
    662 	*/
    663 	__asm mov ebx, r_tstepx
    664 	__asm mov ecx, r_sstepx
    665 	__asm sar ebx, 16
    666 	__asm mov eax, skinwidth
    667 	__asm mul ebx
    668 	__asm sar ecx, 16
    669 	__asm add eax, ecx
    670 	__asm mov a_ststepxwhole, eax
    671 }
    672 #else
    673 void R_PolysetCalcGradients (int skinwidth)
    674 {
    675 	float	xstepdenominv, ystepdenominv, t0, t1;
    676 	float	p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
    677 
    678 	p00_minus_p20 = r_p0[0] - r_p2[0];
    679 	p01_minus_p21 = r_p0[1] - r_p2[1];
    680 	p10_minus_p20 = r_p1[0] - r_p2[0];
    681 	p11_minus_p21 = r_p1[1] - r_p2[1];
    682 
    683 	xstepdenominv = 1.0 / (float)d_xdenom;
    684 
    685 	ystepdenominv = -xstepdenominv;
    686 
    687 // ceil () for light so positive steps are exaggerated, negative steps
    688 // diminished,  pushing us away from underflow toward overflow. Underflow is
    689 // very visible, overflow is very unlikely, because of ambient lighting
    690 	t0 = r_p0[4] - r_p2[4];
    691 	t1 = r_p1[4] - r_p2[4];
    692 	r_lstepx = (int)
    693 			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
    694 	r_lstepy = (int)
    695 			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
    696 
    697 	t0 = r_p0[2] - r_p2[2];
    698 	t1 = r_p1[2] - r_p2[2];
    699 	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    700 			xstepdenominv);
    701 	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
    702 			ystepdenominv);
    703 
    704 	t0 = r_p0[3] - r_p2[3];
    705 	t1 = r_p1[3] - r_p2[3];
    706 	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    707 			xstepdenominv);
    708 	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
    709 			ystepdenominv);
    710 
    711 	t0 = r_p0[5] - r_p2[5];
    712 	t1 = r_p1[5] - r_p2[5];
    713 	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
    714 			xstepdenominv);
    715 	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
    716 			ystepdenominv);
    717 
    718 //#if	id386ALIAS
    719 #if id386
    720 	if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
    721 	{
    722 		a_sstepxfrac = r_sstepx << 16;
    723 		a_tstepxfrac = r_tstepx << 16;
    724 	}
    725 	else
    726 #endif
    727 	{
    728 //#else
    729 		a_sstepxfrac = r_sstepx & 0xFFFF;
    730 		a_tstepxfrac = r_tstepx & 0xFFFF;
    731 	}
    732 //#endif
    733 
    734 	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
    735 }
    736 #endif
    737 
    738 /*
    739 ================
    740 R_PolysetDrawThreshSpans8
    741 
    742 Random fizzle fade rasterizer
    743 ================
    744 */
    745 void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage)
    746 {
    747 	int		lcount;
    748 	byte	*lpdest;
    749 	byte	*lptex;
    750 	int		lsfrac, ltfrac;
    751 	int		llight;
    752 	int		lzi;
    753 	short	*lpz;
    754 
    755 	do
    756 	{
    757 		lcount = d_aspancount - pspanpackage->count;
    758 
    759 		errorterm += erroradjustup;
    760 		if (errorterm >= 0)
    761 		{
    762 			d_aspancount += d_countextrastep;
    763 			errorterm -= erroradjustdown;
    764 		}
    765 		else
    766 		{
    767 			d_aspancount += ubasestep;
    768 		}
    769 
    770 		if (lcount)
    771 		{
    772 			lpdest = pspanpackage->pdest;
    773 			lptex = pspanpackage->ptex;
    774 			lpz = pspanpackage->pz;
    775 			lsfrac = pspanpackage->sfrac;
    776 			ltfrac = pspanpackage->tfrac;
    777 			llight = pspanpackage->light;
    778 			lzi = pspanpackage->zi;
    779 
    780 			do
    781 			{
    782 				if ((lzi >> 16) >= *lpz)
    783 				{
    784 					rand1k_index = (rand1k_index + 1) & MASK_1K;
    785 
    786 					if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh)
    787 					{
    788 						*lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
    789 						*lpz = lzi >> 16;
    790 					}
    791 				}
    792 
    793 				lpdest++;
    794 				lzi += r_zistepx;
    795 				lpz++;
    796 				llight += r_lstepx;
    797 				lptex += a_ststepxwhole;
    798 				lsfrac += a_sstepxfrac;
    799 				lptex += lsfrac >> 16;
    800 				lsfrac &= 0xFFFF;
    801 				ltfrac += a_tstepxfrac;
    802 				if (ltfrac & 0x10000)
    803 				{
    804 					lptex += r_affinetridesc.skinwidth;
    805 					ltfrac &= 0xFFFF;
    806 				}
    807 			} while (--lcount);
    808 		}
    809 
    810 		pspanpackage++;
    811 	} while (pspanpackage->count != -999999);
    812 }
    813 
    814 
    815 /*
    816 ================
    817 R_PolysetDrawSpans8
    818 ================
    819 */
    820 void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage)
    821 {
    822 	int		lcount;
    823 	byte	*lpdest;
    824 	byte	*lptex;
    825 	int		lsfrac, ltfrac;
    826 	int		llight;
    827 	int		lzi;
    828 	short	*lpz;
    829 
    830 	do
    831 	{
    832 		lcount = d_aspancount - pspanpackage->count;
    833 
    834 		errorterm += erroradjustup;
    835 		if (errorterm >= 0)
    836 		{
    837 			d_aspancount += d_countextrastep;
    838 			errorterm -= erroradjustdown;
    839 		}
    840 		else
    841 		{
    842 			d_aspancount += ubasestep;
    843 		}
    844 
    845 		if (lcount)
    846 		{
    847 			lpdest = pspanpackage->pdest;
    848 			lptex = pspanpackage->ptex;
    849 			lpz = pspanpackage->pz;
    850 			lsfrac = pspanpackage->sfrac;
    851 			ltfrac = pspanpackage->tfrac;
    852 			llight = pspanpackage->light;
    853 			lzi = pspanpackage->zi;
    854 
    855 			do
    856 			{
    857 				if ((lzi >> 16) >= *lpz)
    858 				{
    859 					int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
    860 
    861 					*lpdest = vid.alphamap[temp+ *lpdest*256];
    862 				}
    863 				lpdest++;
    864 				lzi += r_zistepx;
    865 				lpz++;
    866 				llight += r_lstepx;
    867 				lptex += a_ststepxwhole;
    868 				lsfrac += a_sstepxfrac;
    869 				lptex += lsfrac >> 16;
    870 				lsfrac &= 0xFFFF;
    871 				ltfrac += a_tstepxfrac;
    872 				if (ltfrac & 0x10000)
    873 				{
    874 					lptex += r_affinetridesc.skinwidth;
    875 					ltfrac &= 0xFFFF;
    876 				}
    877 			} while (--lcount);
    878 		}
    879 
    880 		pspanpackage++;
    881 	} while (pspanpackage->count != -999999);
    882 }
    883 
    884 void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage)
    885 {
    886 	int		lcount;
    887 	byte	*lpdest;
    888 	int		lzi;
    889 	short	*lpz;
    890 
    891 	do
    892 	{
    893 		lcount = d_aspancount - pspanpackage->count;
    894 
    895 		errorterm += erroradjustup;
    896 		if (errorterm >= 0)
    897 		{
    898 			d_aspancount += d_countextrastep;
    899 			errorterm -= erroradjustdown;
    900 		}
    901 		else
    902 		{
    903 			d_aspancount += ubasestep;
    904 		}
    905 
    906 		if (lcount)
    907 		{
    908 			lpdest = pspanpackage->pdest;
    909 			lpz = pspanpackage->pz;
    910 			lzi = pspanpackage->zi;
    911 
    912 			do
    913 			{
    914 				if ((lzi >> 16) >= *lpz)
    915 				{
    916 					*lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256];
    917 				}
    918 				lpdest++;
    919 				lzi += r_zistepx;
    920 				lpz++;
    921 			} while (--lcount);
    922 		}
    923 
    924 		pspanpackage++;
    925 	} while (pspanpackage->count != -999999);
    926 }
    927 
    928 void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage)
    929 {
    930 	int		lcount;
    931 	byte	*lpdest;
    932 	byte	*lptex;
    933 	int		lsfrac, ltfrac;
    934 	int		llight;
    935 	int		lzi;
    936 	short	*lpz;
    937 
    938 	do
    939 	{
    940 		lcount = d_aspancount - pspanpackage->count;
    941 
    942 		errorterm += erroradjustup;
    943 		if (errorterm >= 0)
    944 		{
    945 			d_aspancount += d_countextrastep;
    946 			errorterm -= erroradjustdown;
    947 		}
    948 		else
    949 		{
    950 			d_aspancount += ubasestep;
    951 		}
    952 
    953 		if (lcount)
    954 		{
    955 			lpdest = pspanpackage->pdest;
    956 			lptex = pspanpackage->ptex;
    957 			lpz = pspanpackage->pz;
    958 			lsfrac = pspanpackage->sfrac;
    959 			ltfrac = pspanpackage->tfrac;
    960 			llight = pspanpackage->light;
    961 			lzi = pspanpackage->zi;
    962 
    963 			do
    964 			{
    965 				if ((lzi >> 16) >= *lpz)
    966 				{
    967 					int temp = vid.colormap[*lptex + ( llight & 0xFF00 )];
    968 
    969 					*lpdest = vid.alphamap[temp*256 + *lpdest];
    970 					*lpz = lzi >> 16;
    971 				}
    972 				lpdest++;
    973 				lzi += r_zistepx;
    974 				lpz++;
    975 				llight += r_lstepx;
    976 				lptex += a_ststepxwhole;
    977 				lsfrac += a_sstepxfrac;
    978 				lptex += lsfrac >> 16;
    979 				lsfrac &= 0xFFFF;
    980 				ltfrac += a_tstepxfrac;
    981 				if (ltfrac & 0x10000)
    982 				{
    983 					lptex += r_affinetridesc.skinwidth;
    984 					ltfrac &= 0xFFFF;
    985 				}
    986 			} while (--lcount);
    987 		}
    988 
    989 		pspanpackage++;
    990 	} while (pspanpackage->count != -999999);
    991 }
    992 
    993 void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage)
    994 {
    995 	int		lcount;
    996 	byte	*lpdest;
    997 	int		lzi;
    998 	short	*lpz;
    999 
   1000 	do
   1001 	{
   1002 		lcount = d_aspancount - pspanpackage->count;
   1003 
   1004 		errorterm += erroradjustup;
   1005 		if (errorterm >= 0)
   1006 		{
   1007 			d_aspancount += d_countextrastep;
   1008 			errorterm -= erroradjustdown;
   1009 		}
   1010 		else
   1011 		{
   1012 			d_aspancount += ubasestep;
   1013 		}
   1014 
   1015 		if (lcount)
   1016 		{
   1017 			lpdest = pspanpackage->pdest;
   1018 			lpz = pspanpackage->pz;
   1019 			lzi = pspanpackage->zi;
   1020 
   1021 			do
   1022 			{
   1023 				if ((lzi >> 16) >= *lpz)
   1024 				{
   1025 					*lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest];
   1026 				}
   1027 				lpdest++;
   1028 				lzi += r_zistepx;
   1029 				lpz++;
   1030 			} while (--lcount);
   1031 		}
   1032 
   1033 		pspanpackage++;
   1034 	} while (pspanpackage->count != -999999);
   1035 }
   1036 
   1037 #if !id386
   1038 void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage)
   1039 {
   1040 	int		lcount;
   1041 
   1042 	do
   1043 	{
   1044 		lcount = d_aspancount - pspanpackage->count;
   1045 
   1046 		errorterm += erroradjustup;
   1047 		if (errorterm >= 0)
   1048 		{
   1049 			d_aspancount += d_countextrastep;
   1050 			errorterm -= erroradjustdown;
   1051 		}
   1052 		else
   1053 		{
   1054 			d_aspancount += ubasestep;
   1055 		}
   1056 
   1057 		if (lcount)
   1058 		{
   1059 			int		lsfrac, ltfrac;
   1060 			byte	*lpdest;
   1061 			byte	*lptex;
   1062 			int		llight;
   1063 			int		lzi;
   1064 			short	*lpz;
   1065 
   1066 			lpdest = pspanpackage->pdest;
   1067 			lptex = pspanpackage->ptex;
   1068 			lpz = pspanpackage->pz;
   1069 			lsfrac = pspanpackage->sfrac;
   1070 			ltfrac = pspanpackage->tfrac;
   1071 			llight = pspanpackage->light;
   1072 			lzi = pspanpackage->zi;
   1073 
   1074 			do
   1075 			{
   1076 				if ((lzi >> 16) >= *lpz)
   1077 				{
   1078 //PGM
   1079 					if(r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
   1080 						*lpdest = ((byte *)vid.colormap)[irtable[*lptex]];
   1081 					else
   1082 					*lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)];
   1083 //PGM
   1084 					*lpz = lzi >> 16;
   1085 				}
   1086 				lpdest++;
   1087 				lzi += r_zistepx;
   1088 				lpz++;
   1089 				llight += r_lstepx;
   1090 				lptex += a_ststepxwhole;
   1091 				lsfrac += a_sstepxfrac;
   1092 				lptex += lsfrac >> 16;
   1093 				lsfrac &= 0xFFFF;
   1094 				ltfrac += a_tstepxfrac;
   1095 				if (ltfrac & 0x10000)
   1096 				{
   1097 					lptex += r_affinetridesc.skinwidth;
   1098 					ltfrac &= 0xFFFF;
   1099 				}
   1100 			} while (--lcount);
   1101 		}
   1102 
   1103 		pspanpackage++;
   1104 	} while (pspanpackage->count != -999999);
   1105 }
   1106 #endif
   1107 
   1108 
   1109 /*
   1110 ================
   1111 R_PolysetFillSpans8
   1112 ================
   1113 */
   1114 void R_PolysetFillSpans8 (spanpackage_t *pspanpackage)
   1115 {
   1116 	int				color;
   1117 
   1118 // FIXME: do z buffering
   1119 
   1120 	color = d_aflatcolor++;
   1121 
   1122 	while (1)
   1123 	{
   1124 		int		lcount;
   1125 		byte	*lpdest;
   1126 
   1127 		lcount = pspanpackage->count;
   1128 
   1129 		if (lcount == -1)
   1130 			return;
   1131 
   1132 		if (lcount)
   1133 		{
   1134 			lpdest = pspanpackage->pdest;
   1135 
   1136 			do
   1137 			{
   1138 				*lpdest++ = color;
   1139 			} while (--lcount);
   1140 		}
   1141 
   1142 		pspanpackage++;
   1143 	}
   1144 }
   1145 
   1146 /*
   1147 ================
   1148 R_RasterizeAliasPolySmooth
   1149 ================
   1150 */
   1151 void R_RasterizeAliasPolySmooth (void)
   1152 {
   1153 	int				initialleftheight, initialrightheight;
   1154 	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
   1155 	int				working_lstepx, originalcount;
   1156 
   1157 	plefttop = pedgetable->pleftedgevert0;
   1158 	prighttop = pedgetable->prightedgevert0;
   1159 
   1160 	pleftbottom = pedgetable->pleftedgevert1;
   1161 	prightbottom = pedgetable->prightedgevert1;
   1162 
   1163 	initialleftheight = pleftbottom[1] - plefttop[1];
   1164 	initialrightheight = prightbottom[1] - prighttop[1];
   1165 
   1166 //
   1167 // set the s, t, and light gradients, which are consistent across the triangle
   1168 // because being a triangle, things are affine
   1169 //
   1170 	R_PolysetCalcGradients (r_affinetridesc.skinwidth);
   1171 //
   1172 // rasterize the polygon
   1173 //
   1174 
   1175 //
   1176 // scan out the top (and possibly only) part of the left edge
   1177 //
   1178 	d_pedgespanpackage = a_spans;
   1179 
   1180 	ystart = plefttop[1];
   1181 	d_aspancount = plefttop[0] - prighttop[0];
   1182 
   1183 	d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
   1184 			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
   1185 //#if	id386ALIAS
   1186 #if id386
   1187 	if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1188 	{
   1189 		d_sfrac = (plefttop[2] & 0xFFFF) << 16;
   1190 		d_tfrac = (plefttop[3] & 0xFFFF) << 16;
   1191 	}
   1192 //#else
   1193 	else
   1194 #endif
   1195 	{
   1196 		d_sfrac = plefttop[2] & 0xFFFF;
   1197 		d_tfrac = plefttop[3] & 0xFFFF;
   1198 	}
   1199 //#endif
   1200 	d_light = plefttop[4];
   1201 	d_zi = plefttop[5];
   1202 
   1203 	d_pdest = (byte *)d_viewbuffer +
   1204 			ystart * r_screenwidth + plefttop[0];
   1205 	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
   1206 
   1207 	if (initialleftheight == 1)
   1208 	{
   1209 		d_pedgespanpackage->pdest = d_pdest;
   1210 		d_pedgespanpackage->pz = d_pz;
   1211 		d_pedgespanpackage->count = d_aspancount;
   1212 		d_pedgespanpackage->ptex = d_ptex;
   1213 
   1214 		d_pedgespanpackage->sfrac = d_sfrac;
   1215 		d_pedgespanpackage->tfrac = d_tfrac;
   1216 
   1217 	// FIXME: need to clamp l, s, t, at both ends?
   1218 		d_pedgespanpackage->light = d_light;
   1219 		d_pedgespanpackage->zi = d_zi;
   1220 
   1221 		d_pedgespanpackage++;
   1222 	}
   1223 	else
   1224 	{
   1225 		R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
   1226 							  pleftbottom[0], pleftbottom[1]);
   1227 
   1228 //#if	id386ALIAS
   1229 #if id386
   1230 		if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1231 		{
   1232 			d_pzbasestep = (d_zwidth + ubasestep) << 1;
   1233 			d_pzextrastep = d_pzbasestep + 2;
   1234 		}
   1235 //#else
   1236 		else
   1237 #endif
   1238 		{
   1239 			d_pzbasestep = d_zwidth + ubasestep;
   1240 			d_pzextrastep = d_pzbasestep + 1;
   1241 		}
   1242 //#endif
   1243 
   1244 		d_pdestbasestep = r_screenwidth + ubasestep;
   1245 		d_pdestextrastep = d_pdestbasestep + 1;
   1246 
   1247 	// TODO: can reuse partial expressions here
   1248 
   1249 	// for negative steps in x along left edge, bias toward overflow rather than
   1250 	// underflow (sort of turning the floor () we did in the gradient calcs into
   1251 	// ceil (), but plus a little bit)
   1252 		if (ubasestep < 0)
   1253 			working_lstepx = r_lstepx - 1;
   1254 		else
   1255 			working_lstepx = r_lstepx;
   1256 
   1257 		d_countextrastep = ubasestep + 1;
   1258 		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
   1259 				((r_tstepy + r_tstepx * ubasestep) >> 16) *
   1260 				r_affinetridesc.skinwidth;
   1261 //#if	id386ALIAS
   1262 #if id386
   1263 		if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1264 		{
   1265 			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
   1266 			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
   1267 		}
   1268 		else
   1269 #endif
   1270 		{
   1271 //#else
   1272 			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
   1273 			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
   1274 		}
   1275 //#endif
   1276 		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
   1277 		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
   1278 
   1279 		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
   1280 				((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
   1281 				r_affinetridesc.skinwidth;
   1282 //#if	id386ALIAS
   1283 #if id386
   1284 		if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1285 		{
   1286 			d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
   1287 			d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
   1288 		}
   1289 		else
   1290 #endif
   1291 		{
   1292 //#else
   1293 			d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
   1294 			d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
   1295 		}
   1296 //#endif
   1297 		d_lightextrastep = d_lightbasestep + working_lstepx;
   1298 		d_ziextrastep = d_zibasestep + r_zistepx;
   1299 
   1300 #if id386
   1301 		if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1302 		{
   1303 			R_PolysetScanLeftEdge (initialleftheight);
   1304 		}
   1305 		else
   1306 #endif
   1307 		{
   1308 			R_PolysetScanLeftEdge_C(initialleftheight);
   1309 		}
   1310 	}
   1311 
   1312 //
   1313 // scan out the bottom part of the left edge, if it exists
   1314 //
   1315 	if (pedgetable->numleftedges == 2)
   1316 	{
   1317 		int		height;
   1318 
   1319 		plefttop = pleftbottom;
   1320 		pleftbottom = pedgetable->pleftedgevert2;
   1321 
   1322 		height = pleftbottom[1] - plefttop[1];
   1323 
   1324 // TODO: make this a function; modularize this function in general
   1325 
   1326 		ystart = plefttop[1];
   1327 		d_aspancount = plefttop[0] - prighttop[0];
   1328 		d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
   1329 				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
   1330 		d_sfrac = 0;
   1331 		d_tfrac = 0;
   1332 		d_light = plefttop[4];
   1333 		d_zi = plefttop[5];
   1334 
   1335 		d_pdest = (byte *)d_viewbuffer + ystart * r_screenwidth + plefttop[0];
   1336 		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
   1337 
   1338 		if (height == 1)
   1339 		{
   1340 			d_pedgespanpackage->pdest = d_pdest;
   1341 			d_pedgespanpackage->pz = d_pz;
   1342 			d_pedgespanpackage->count = d_aspancount;
   1343 			d_pedgespanpackage->ptex = d_ptex;
   1344 
   1345 			d_pedgespanpackage->sfrac = d_sfrac;
   1346 			d_pedgespanpackage->tfrac = d_tfrac;
   1347 
   1348 		// FIXME: need to clamp l, s, t, at both ends?
   1349 			d_pedgespanpackage->light = d_light;
   1350 			d_pedgespanpackage->zi = d_zi;
   1351 
   1352 			d_pedgespanpackage++;
   1353 		}
   1354 		else
   1355 		{
   1356 			R_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
   1357 								  pleftbottom[0], pleftbottom[1]);
   1358 
   1359 			d_pdestbasestep = r_screenwidth + ubasestep;
   1360 			d_pdestextrastep = d_pdestbasestep + 1;
   1361 
   1362 //#if	id386ALIAS
   1363 #if id386
   1364 			if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1365 			{
   1366 				d_pzbasestep = (d_zwidth + ubasestep) << 1;
   1367 				d_pzextrastep = d_pzbasestep + 2;
   1368 			}
   1369 //#else
   1370 			else
   1371 #endif
   1372 			{
   1373 				d_pzbasestep = d_zwidth + ubasestep;
   1374 				d_pzextrastep = d_pzbasestep + 1;
   1375 			}
   1376 //#endif
   1377 
   1378 			if (ubasestep < 0)
   1379 				working_lstepx = r_lstepx - 1;
   1380 			else
   1381 				working_lstepx = r_lstepx;
   1382 
   1383 			d_countextrastep = ubasestep + 1;
   1384 			d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
   1385 					((r_tstepy + r_tstepx * ubasestep) >> 16) *
   1386 					r_affinetridesc.skinwidth;
   1387 //#if	id386ALIAS
   1388 #if id386
   1389 			if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1390 			{
   1391 				d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
   1392 				d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
   1393 			}
   1394 //#else
   1395 			else
   1396 #endif
   1397 			{
   1398 				d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
   1399 				d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
   1400 			}
   1401 //#endif
   1402 			d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
   1403 			d_zibasestep = r_zistepy + r_zistepx * ubasestep;
   1404 
   1405 			d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
   1406 					((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
   1407 					r_affinetridesc.skinwidth;
   1408 //#if	id386ALIAS
   1409 #if id386
   1410 			if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1411 			{
   1412 				d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
   1413 				d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
   1414 			}
   1415 			else
   1416 #endif
   1417 //#endif
   1418 			{
   1419 				d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
   1420 				d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
   1421 			}
   1422 //#endif
   1423 			d_lightextrastep = d_lightbasestep + working_lstepx;
   1424 			d_ziextrastep = d_zibasestep + r_zistepx;
   1425 
   1426 #if id386
   1427 			if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque )
   1428 			{
   1429 				R_PolysetScanLeftEdge (height);
   1430 			}
   1431 			else
   1432 #endif
   1433 			{
   1434 				R_PolysetScanLeftEdge_C(height);
   1435 			}
   1436 		}
   1437 	}
   1438 
   1439 // scan out the top (and possibly only) part of the right edge, updating the
   1440 // count field
   1441 	d_pedgespanpackage = a_spans;
   1442 
   1443 	R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
   1444 						  prightbottom[0], prightbottom[1]);
   1445 	d_aspancount = 0;
   1446 	d_countextrastep = ubasestep + 1;
   1447 	originalcount = a_spans[initialrightheight].count;
   1448 	a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
   1449 	(*d_pdrawspans) (a_spans);
   1450 
   1451 // scan out the bottom part of the right edge, if it exists
   1452 	if (pedgetable->numrightedges == 2)
   1453 	{
   1454 		int				height;
   1455 		spanpackage_t	*pstart;
   1456 
   1457 		pstart = a_spans + initialrightheight;
   1458 		pstart->count = originalcount;
   1459 
   1460 		d_aspancount = prightbottom[0] - prighttop[0];
   1461 
   1462 		prighttop = prightbottom;
   1463 		prightbottom = pedgetable->prightedgevert2;
   1464 
   1465 		height = prightbottom[1] - prighttop[1];
   1466 
   1467 		R_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
   1468 							  prightbottom[0], prightbottom[1]);
   1469 
   1470 		d_countextrastep = ubasestep + 1;
   1471 		a_spans[initialrightheight + height].count = -999999;
   1472 											// mark end of the spanpackages
   1473 		(*d_pdrawspans) (pstart);
   1474 	}
   1475 }
   1476 
   1477 
   1478 /*
   1479 ================
   1480 R_PolysetSetEdgeTable
   1481 ================
   1482 */
   1483 void R_PolysetSetEdgeTable (void)
   1484 {
   1485 	int			edgetableindex;
   1486 
   1487 	edgetableindex = 0;	// assume the vertices are already in
   1488 						//  top to bottom order
   1489 
   1490 //
   1491 // determine which edges are right & left, and the order in which
   1492 // to rasterize them
   1493 //
   1494 	if (r_p0[1] >= r_p1[1])
   1495 	{
   1496 		if (r_p0[1] == r_p1[1])
   1497 		{
   1498 			if (r_p0[1] < r_p2[1])
   1499 				pedgetable = &edgetables[2];
   1500 			else
   1501 				pedgetable = &edgetables[5];
   1502 
   1503 			return;
   1504 		}
   1505 		else
   1506 		{
   1507 			edgetableindex = 1;
   1508 		}
   1509 	}
   1510 
   1511 	if (r_p0[1] == r_p2[1])
   1512 	{
   1513 		if (edgetableindex)
   1514 			pedgetable = &edgetables[8];
   1515 		else
   1516 			pedgetable = &edgetables[9];
   1517 
   1518 		return;
   1519 	}
   1520 	else if (r_p1[1] == r_p2[1])
   1521 	{
   1522 		if (edgetableindex)
   1523 			pedgetable = &edgetables[10];
   1524 		else
   1525 			pedgetable = &edgetables[11];
   1526 
   1527 		return;
   1528 	}
   1529 
   1530 	if (r_p0[1] > r_p2[1])
   1531 		edgetableindex += 2;
   1532 
   1533 	if (r_p1[1] > r_p2[1])
   1534 		edgetableindex += 4;
   1535 
   1536 	pedgetable = &edgetables[edgetableindex];
   1537 }
   1538 
   1539