1 /*
2  * d_scan.c - Portable C scan-level rasterization code, all pixel depths.
3  * $Id: d_scan.c 5976 2017-09-16 20:03:22Z sezero $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  * C versions of several asm functions:  Juraj Styk <jurajstyk@host.sk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or (at
12  * your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * See the GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  */
24 
25 #include "quakedef.h"
26 #include "r_local.h"
27 #include "d_local.h"
28 
29 ASM_LINKAGE_BEGIN
30 unsigned char	*r_turb_pbase, *r_turb_pdest;
31 fixed16_t		r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
32 int				*r_turb_turb;
33 int				r_turb_spancount;
34 byte			scanList[SCAN_SIZE];
35 int				ZScanCount;
36 ASM_LINKAGE_END
37 
38 
39 /*
40 =============
41 D_WarpScreen
42 
43 // this performs a slight compression of the screen at the same time as
44 // the sine warp, to keep the edges from wrapping
45 =============
46 */
D_WarpScreen(void)47 void D_WarpScreen (void)
48 {
49 	int		w, h;
50 	int		u, v;
51 	byte	*dest;
52 	int		*turb;
53 	int		*col;
54 	byte	**row;
55 	byte	*rowptr[MAXHEIGHT+(AMP2*2)];
56 	int		column[MAXWIDTH+(AMP2*2)];
57 	float	wratio, hratio;
58 
59 	w = r_refdef.vrect.width;
60 	h = r_refdef.vrect.height;
61 
62 	wratio = w / (float)scr_vrect.width;
63 	hratio = h / (float)scr_vrect.height;
64 
65 	for (v = 0; v < scr_vrect.height + AMP2*2; v++)
66 	{
67 		rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) +
68 				 (screenwidth * (int)((float)v * hratio * h / (h + AMP2 * 2)));
69 	}
70 
71 	for (u = 0; u < scr_vrect.width + AMP2*2; u++)
72 	{
73 		column[u] = r_refdef.vrect.x +
74 				(int)((float)u * wratio * w / (w + AMP2 * 2));
75 	}
76 
77 	turb = intsintable + ((int)(cl.time*SPEED) & (CYCLE-1));
78 	dest = vid.buffer + scr_vrect.y * vid.rowbytes + scr_vrect.x;
79 
80 	for (v = 0; v < scr_vrect.height; v++, dest += vid.rowbytes)
81 	{
82 		col = &column[turb[v]];
83 		row = &rowptr[v];
84 
85 		for (u = 0; u < scr_vrect.width; u += 4)
86 		{
87 			dest[u+0] = row[turb[u+0]][col[u+0]];
88 			dest[u+1] = row[turb[u+1]][col[u+1]];
89 			dest[u+2] = row[turb[u+2]][col[u+2]];
90 			dest[u+3] = row[turb[u+3]][col[u+3]];
91 		}
92 	}
93 }
94 
95 
96 #if	!id386
97 /*
98 =============
99 D_DrawTurbulent8Span
100 =============
101 */
102 #if !id68k
D_DrawTurbulent8Span(void)103 static void D_DrawTurbulent8Span (void)
104 {
105 	int		sturb, tturb;
106 
107 	do
108 	{
109 		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
110 		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
111 		*r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
112 		r_turb_s += r_turb_sstep;
113 		r_turb_t += r_turb_tstep;
114 	} while (--r_turb_spancount > 0);
115 }
116 #endif
117 
D_DrawTurbulent8TSpan(void)118 static void D_DrawTurbulent8TSpan (void)
119 {
120 	int		sturb, tturb;
121 	unsigned char	temp;
122 
123 	do
124 	{
125 		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
126 		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
127 
128 		if (scanList[r_turb_spancount-1] == 1)
129 		{
130 			temp = *(r_turb_pbase + (tturb<<6) + sturb);
131 			*r_turb_pdest = mainTransTable[(temp<<8) + (*r_turb_pdest)];
132 			r_turb_pdest++;
133 		}
134 		else
135 			r_turb_pdest++;
136 
137 		r_turb_s += r_turb_sstep;
138 		r_turb_t += r_turb_tstep;
139 	} while (--r_turb_spancount > 0);
140 }
141 
D_DrawTurbulent8TQuickSpan(void)142 static void D_DrawTurbulent8TQuickSpan (void)
143 {
144 	int		sturb, tturb;
145 	unsigned char	temp;
146 
147 	do
148 	{
149 		sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
150 		tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
151 		temp = *(r_turb_pbase + (tturb<<6) + sturb);
152 		*r_turb_pdest = mainTransTable[(temp<<8) + (*r_turb_pdest)];
153 		r_turb_pdest++;
154 		r_turb_s += r_turb_sstep;
155 		r_turb_t += r_turb_tstep;
156 	} while (--r_turb_spancount > 0);
157 }
158 
159 #endif	/* !id386 */
160 
161 
162 /*
163 =============
164 Turbulent8
165 =============
166 */
Turbulent8(surf_t * s)167 void Turbulent8 (surf_t *s)
168 {
169 	int				count;
170 	fixed16_t		snext, tnext;
171 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
172 	float			sdivz16stepu, tdivz16stepu, zi16stepu;
173 	byte			origscanList[SCAN_SIZE];
174 	espan_t			*pspan;
175 
176 	pspan = s->spans;
177 
178 	r_turb_turb = sintable + ((int)(cl.time*SPEED)&(CYCLE-1));
179 
180 	r_turb_sstep = 0;	// keep compiler happy
181 	r_turb_tstep = 0;	// ditto
182 
183 	r_turb_pbase = (unsigned char *)cacheblock;
184 
185 	sdivz16stepu = d_sdivzstepu * 16;
186 	tdivz16stepu = d_tdivzstepu * 16;
187 	zi16stepu = d_zistepu * 16;
188 
189 	do
190 	{
191 		r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u);
192 		count = pspan->count;
193 
194 		if (r_transwater.integer && s->flags & SURF_TRANSLUCENT)
195 		{
196 			D_DrawSingleZSpans(pspan);
197 			if (ZScanCount == count)  // fully blocked
198 				continue;
199 
200 			if (ZScanCount)
201 				memcpy(origscanList,scanList,count);
202 		}
203 
204 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
205 		du = (float)pspan->u;
206 		dv = (float)pspan->v;
207 
208 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
209 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
210 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
211 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
212 
213 		r_turb_s = (int)(sdivz * z) + sadjust;
214 		if (r_turb_s > bbextents)
215 			r_turb_s = bbextents;
216 		else if (r_turb_s < 0)
217 			r_turb_s = 0;
218 
219 		r_turb_t = (int)(tdivz * z) + tadjust;
220 		if (r_turb_t > bbextentt)
221 			r_turb_t = bbextentt;
222 		else if (r_turb_t < 0)
223 			r_turb_t = 0;
224 
225 		do
226 		{
227 		// calculate s and t at the far end of the span
228 			if (count >= 16)
229 			{
230 				r_turb_spancount = 16;
231 			}
232 			else
233 				r_turb_spancount = count;
234 
235 			count -= r_turb_spancount;
236 
237 			if (count)
238 			{
239 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
240 			// calculate s and t steps across span by shifting
241 				sdivz += sdivz16stepu;
242 				tdivz += tdivz16stepu;
243 				zi += zi16stepu;
244 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
245 
246 				snext = (int)(sdivz * z) + sadjust;
247 				if (snext > bbextents)
248 					snext = bbextents;
249 				else if (snext < 16)
250 					snext = 16;	// prevent round-off error on <0 steps from
251 								//  from causing overstepping & running off the
252 								//  edge of the texture
253 
254 				tnext = (int)(tdivz * z) + tadjust;
255 				if (tnext > bbextentt)
256 					tnext = bbextentt;
257 				else if (tnext < 16)
258 					tnext = 16;	// guard against round-off error on <0 steps
259 
260 				r_turb_sstep = (snext - r_turb_s) >> 4;
261 				r_turb_tstep = (tnext - r_turb_t) >> 4;
262 			}
263 			else
264 			{
265 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
266 			// can't step off polygon), clamp, calculate s and t steps across
267 			// span by division, biasing steps low so we don't run off the
268 			// texture
269 				spancountminus1 = (float)(r_turb_spancount - 1);
270 				sdivz += d_sdivzstepu * spancountminus1;
271 				tdivz += d_tdivzstepu * spancountminus1;
272 				zi += d_zistepu * spancountminus1;
273 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
274 				snext = (int)(sdivz * z) + sadjust;
275 				if (snext > bbextents)
276 					snext = bbextents;
277 				else if (snext < 16)
278 					snext = 16;	// prevent round-off error on <0 steps from
279 								//  from causing overstepping & running off the
280 								//  edge of the texture
281 
282 				tnext = (int)(tdivz * z) + tadjust;
283 				if (tnext > bbextentt)
284 					tnext = bbextentt;
285 				else if (tnext < 16)
286 					tnext = 16;	// guard against round-off error on <0 steps
287 
288 				if (r_turb_spancount > 1)
289 				{
290 					r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
291 					r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
292 				}
293 			}
294 
295 			r_turb_s = r_turb_s & ((CYCLE<<16)-1);
296 			r_turb_t = r_turb_t & ((CYCLE<<16)-1);
297 
298 			if (r_transwater.integer && s->flags & SURF_TRANSLUCENT)
299 			{
300 				if (ZScanCount)
301 				{
302 					memcpy(scanList,&origscanList[count],r_turb_spancount);
303 					D_DrawTurbulent8TSpan ();
304 				}
305 				else
306 					D_DrawTurbulent8TQuickSpan ();
307 			}
308 			else
309 				D_DrawTurbulent8Span ();
310 
311 			r_turb_s = snext;
312 			r_turb_t = tnext;
313 
314 		} while (count > 0);
315 
316 	} while ((pspan = pspan->pnext) != NULL);
317 }
318 
319 
320 #if	!id386
321 
322 /*
323 =============
324 D_DrawSpans8
325 =============
326 */
327 #if !id68k
D_DrawSpans8(espan_t * pspan)328 void D_DrawSpans8 (espan_t *pspan)
329 {
330 	int				count, spancount;
331 	unsigned char	*pbase, *pdest;
332 	fixed16_t		s, t, snext, tnext, sstep, tstep;
333 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
334 	float			sdivz8stepu, tdivz8stepu, zi8stepu;
335 
336 	sstep = 0;	// keep compiler happy
337 	tstep = 0;	// ditto
338 
339 	pbase = (unsigned char *)cacheblock;
340 
341 	sdivz8stepu = d_sdivzstepu * 8;
342 	tdivz8stepu = d_tdivzstepu * 8;
343 	zi8stepu = d_zistepu * 8;
344 
345 	do
346 	{
347 		pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u);
348 		count = pspan->count;
349 
350 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
351 		du = (float)pspan->u;
352 		dv = (float)pspan->v;
353 
354 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
355 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
356 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
357 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
358 
359 		s = (int)(sdivz * z) + sadjust;
360 		if (s > bbextents)
361 			s = bbextents;
362 		else if (s < 0)
363 			s = 0;
364 
365 		t = (int)(tdivz * z) + tadjust;
366 		if (t > bbextentt)
367 			t = bbextentt;
368 		else if (t < 0)
369 			t = 0;
370 
371 		do
372 		{
373 		// calculate s and t at the far end of the span
374 			if (count >= 8)
375 				spancount = 8;
376 			else
377 				spancount = count;
378 
379 			count -= spancount;
380 
381 			if (count)
382 			{
383 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
384 			// calculate s and t steps across span by shifting
385 				sdivz += sdivz8stepu;
386 				tdivz += tdivz8stepu;
387 				zi += zi8stepu;
388 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
389 
390 				snext = (int)(sdivz * z) + sadjust;
391 				if (snext > bbextents)
392 					snext = bbextents;
393 				else if (snext < 8)
394 					snext = 8;	// prevent round-off error on <0 steps from
395 								//  from causing overstepping & running off the
396 								//  edge of the texture
397 
398 				tnext = (int)(tdivz * z) + tadjust;
399 				if (tnext > bbextentt)
400 					tnext = bbextentt;
401 				else if (tnext < 8)
402 					tnext = 8;	// guard against round-off error on <0 steps
403 
404 				sstep = (snext - s) >> 3;
405 				tstep = (tnext - t) >> 3;
406 			}
407 			else
408 			{
409 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
410 			// can't step off polygon), clamp, calculate s and t steps across
411 			// span by division, biasing steps low so we don't run off the
412 			// texture
413 				spancountminus1 = (float)(spancount - 1);
414 				sdivz += d_sdivzstepu * spancountminus1;
415 				tdivz += d_tdivzstepu * spancountminus1;
416 				zi += d_zistepu * spancountminus1;
417 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
418 				snext = (int)(sdivz * z) + sadjust;
419 				if (snext > bbextents)
420 					snext = bbextents;
421 				else if (snext < 8)
422 					snext = 8;	// prevent round-off error on <0 steps from
423 								//  from causing overstepping & running off the
424 								//  edge of the texture
425 
426 				tnext = (int)(tdivz * z) + tadjust;
427 				if (tnext > bbextentt)
428 					tnext = bbextentt;
429 				else if (tnext < 8)
430 					tnext = 8;	// guard against round-off error on <0 steps
431 
432 				if (spancount > 1)
433 				{
434 					sstep = (snext - s) / (spancount - 1);
435 					tstep = (tnext - t) / (spancount - 1);
436 				}
437 			}
438 
439 			do
440 			{
441 				*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
442 				s += sstep;
443 				t += tstep;
444 			} while (--spancount > 0);
445 
446 			s = snext;
447 			t = tnext;
448 
449 		} while (count > 0);
450 
451 	} while ((pspan = pspan->pnext) != NULL);
452 }
453 #endif /* !id68k */
454 
D_DrawSpans8T(espan_t * pspan)455 void D_DrawSpans8T (espan_t *pspan)
456 {
457 	int				count, spancount;
458 	unsigned char	*pbase, *pdest;
459 	fixed16_t		s, t, snext, tnext, sstep, tstep;
460 	float			sdivz, tdivz, zi, z, du, dv, spancountminus1;
461 	float			sdivz8stepu, tdivz8stepu, zi8stepu;
462 	short		*pz;
463 	byte		btemp;
464 	int			izi, izistep;
465 
466 	sstep = 0;	// keep compiler happy
467 	tstep = 0;	// ditto
468 
469 	pbase = (unsigned char *)cacheblock;
470 
471 	sdivz8stepu = d_sdivzstepu * 8;
472 	tdivz8stepu = d_tdivzstepu * 8;
473 	zi8stepu = d_zistepu * 8;
474 
475 	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
476 
477 	do
478 	{
479 		pdest = (unsigned char *)((byte *)d_viewbuffer + (screenwidth * pspan->v) + pspan->u);
480 		pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
481 		count = pspan->count;
482 
483 	// calculate the initial s/z, t/z, 1/z, s, and t and clamp
484 		du = (float)pspan->u;
485 		dv = (float)pspan->v;
486 
487 		sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
488 		tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
489 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
490 		z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
491 		izi = (int)(zi * 0x8000 * 0x10000);
492 
493 		s = (int)(sdivz * z) + sadjust;
494 		if (s > bbextents)
495 			s = bbextents;
496 		else if (s < 0)
497 			s = 0;
498 
499 		t = (int)(tdivz * z) + tadjust;
500 		if (t > bbextentt)
501 			t = bbextentt;
502 		else if (t < 0)
503 			t = 0;
504 
505 		do
506 		{
507 		// calculate s and t at the far end of the span
508 			if (count >= 8)
509 				spancount = 8;
510 			else
511 				spancount = count;
512 
513 			count -= spancount;
514 
515 			if (count)
516 			{
517 			// calculate s/z, t/z, zi->fixed s and t at far end of span,
518 			// calculate s and t steps across span by shifting
519 				sdivz += sdivz8stepu;
520 				tdivz += tdivz8stepu;
521 				zi += zi8stepu;
522 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
523 
524 				snext = (int)(sdivz * z) + sadjust;
525 				if (snext > bbextents)
526 					snext = bbextents;
527 				else if (snext < 8)
528 					snext = 8;	// prevent round-off error on <0 steps from
529 								//  from causing overstepping & running off the
530 								//  edge of the texture
531 
532 				tnext = (int)(tdivz * z) + tadjust;
533 				if (tnext > bbextentt)
534 					tnext = bbextentt;
535 				else if (tnext < 8)
536 					tnext = 8;	// guard against round-off error on <0 steps
537 
538 				sstep = (snext - s) >> 3;
539 				tstep = (tnext - t) >> 3;
540 			}
541 			else
542 			{
543 			// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
544 			// can't step off polygon), clamp, calculate s and t steps across
545 			// span by division, biasing steps low so we don't run off the
546 			// texture
547 				spancountminus1 = (float)(spancount - 1);
548 				sdivz += d_sdivzstepu * spancountminus1;
549 				tdivz += d_tdivzstepu * spancountminus1;
550 				zi += d_zistepu * spancountminus1;
551 				z = (float)0x10000 / zi;	// prescale to 16.16 fixed-point
552 				snext = (int)(sdivz * z) + sadjust;
553 				if (snext > bbextents)
554 					snext = bbextents;
555 				else if (snext < 8)
556 					snext = 8;	// prevent round-off error on <0 steps from
557 								//  from causing overstepping & running off the
558 								//  edge of the texture
559 
560 				tnext = (int)(tdivz * z) + tadjust;
561 				if (tnext > bbextentt)
562 					tnext = bbextentt;
563 				else if (tnext < 8)
564 					tnext = 8;	// guard against round-off error on <0 steps
565 
566 				if (spancount > 1)
567 				{
568 					sstep = (snext - s) / (spancount - 1);
569 					tstep = (tnext - t) / (spancount - 1);
570 				}
571 			}
572 
573 			do
574 			{
575 				btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
576 				if (*pz <= (izi >> 16))
577 				{
578 					*pdest = mainTransTable[(btemp<<8) + (*pdest)];
579 				}
580 				izi += izistep;
581 				pdest++;
582 				pz++;
583 
584 			//	*pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
585 				s += sstep;
586 				t += tstep;
587 			} while (--spancount > 0);
588 
589 			s = snext;
590 			t = tnext;
591 
592 		} while (count > 0);
593 
594 	} while ((pspan = pspan->pnext) != NULL);
595 }
596 
597 /*
598 =============
599 D_DrawZSpans
600 =============
601 */
602 #if !id68k
D_DrawZSpans(espan_t * pspan)603 void D_DrawZSpans (espan_t *pspan)
604 {
605 	int			count, doublecount, izistep;
606 	int			izi;
607 	short			*pdest;
608 	unsigned int		ltemp;
609 	double			zi;
610 	float			du, dv;
611 
612 // FIXME: check for clamping/range problems
613 // we count on FP exceptions being turned off to avoid range problems
614 	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
615 
616 	do
617 	{
618 		pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
619 
620 		count = pspan->count;
621 
622 	// calculate the initial 1/z
623 		du = (float)pspan->u;
624 		dv = (float)pspan->v;
625 
626 		zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
627 	// we count on FP exceptions being turned off to avoid range problems
628 		izi = (int)(zi * 0x8000 * 0x10000);
629 
630 		if ((intptr_t)pdest & 0x02)
631 		{
632 			*pdest++ = (short)(izi >> 16);
633 			izi += izistep;
634 			count--;
635 		}
636 
637 		if ((doublecount = count >> 1) > 0)
638 		{
639 			do
640 			{
641 				ltemp = izi >> 16;
642 				izi += izistep;
643 				ltemp |= izi & 0xFFFF0000;
644 				izi += izistep;
645 				*(int *)pdest = ltemp;
646 				pdest += 2;
647 			} while (--doublecount > 0);
648 		}
649 
650 		if (count & 1)
651 			*pdest = (short)(izi >> 16);
652 
653 	} while ((pspan = pspan->pnext) != NULL);
654 }
655 #endif /* !id68k */
656 
657 /*
658 =============
659 D_DrawSingleZSpans
660 =============
661 */
D_DrawSingleZSpans(espan_t * pspan)662 void D_DrawSingleZSpans (espan_t *pspan)
663 {
664 	int			count, izistep;
665 	int			izi;
666 	short			*pdest;
667 	float			zi;
668 	float			du, dv;
669 
670 	ZScanCount = 0;
671 
672 // FIXME: check for clamping/range problems
673 // we count on FP exceptions being turned off to avoid range problems
674 	izistep = (int)(d_zistepu * 0x8000 * 0x10000);
675 
676 	pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
677 
678 	count = pspan->count;
679 
680 // calculate the initial 1/z
681 	du = (float)pspan->u;
682 	dv = (float)pspan->v;
683 
684 	zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
685 // we count on FP exceptions being turned off to avoid range problems
686 	izi = (int)(zi * 0x8000 * 0x10000);
687 
688 	if (count > 0)
689 	{
690 		do
691 		{
692 			if (*pdest > (short)(izi >> 16))
693 			{
694 				ZScanCount++;
695 				scanList[count-1] = 0;
696 			}
697 			else
698 			{
699 				scanList[count-1] = 1;
700 				*pdest = (short)(izi >> 16);
701 			}
702 			izi += izistep;
703 			pdest++;
704 			count--;
705 		} while (count > 0);
706 	}
707 }
708 
709 #endif	/* !id386 */
710 
711