2 * $Logfile: /Freespace2/code/Graphics/TmapScanTiled16x16.cpp $
7 * Routines for drawing tiled 16x16 textues
10 * Revision 1.2 2002/05/07 03:16:45 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:09 root
17 * 4 11/30/98 5:31p Dave
18 * Fixed up Fred support for software mode.
20 * 3 11/30/98 1:07p Dave
21 * 16 bit conversion, first run.
23 * 2 10/07/98 10:53a Dave
26 * 1 10/07/98 10:49a Dave
28 * 6 4/23/98 9:55a John
29 * Fixed some bugs in the tiled tmapper causing bright dots to appear all
32 * 5 3/10/98 4:19p John
33 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
34 * & Glide have popups and print screen. Took out all >8bpp software
35 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
36 * support Fred. Made zbuffering key off of functions rather than one
39 * 4 1/23/98 5:08p John
40 * Took L out of vertex structure used B (blue) instead. Took all small
41 * fireballs out of fireball types and used particles instead. Fixed some
42 * debris explosion things. Restructured fireball code. Restructured
43 * some lighting code. Made dynamic lighting on by default. Made groups
44 * of lasers only cast one light. Made fireballs not cast light.
46 * 3 12/04/97 10:38a John
47 * Fixed tiled texture mappers that were swapping uvs.
49 * 2 10/14/97 9:19a John
50 * removed fdiv warnings.
52 * 1 6/18/97 4:02p John
53 * added new code for 16x16 and 32x32 tiled tmaps.
61 #include "grinternal.h"
63 #include "tmapscanline.h"
68 // Needed to keep warning 4725 to stay away. See PsTypes.h for details why.
69 void disable_warning_4725_stub_tst16()
73 void tmapscan_pln8_zbuffered_tiled_16x16()
75 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
76 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
77 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
79 if ( Tmap.fx_dl_dx < 0 ) {
80 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
81 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
82 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
83 // Assert( Tmap.fx_l > 31*F1_0 );
84 // Assert( Tmap.fx_l < 66*F1_0 );
85 // Assert( Tmap.fx_dl_dx >= 0 );
86 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
89 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
90 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
91 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
93 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
94 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
96 // Assert(Tmap.fx_w < 65536 );
97 // Assert(Tmap.fx_w >= 0 );
98 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
99 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
114 // Put the FPU in low precision mode
115 fstcw Tmap.OldFPUCW // store copy of CW
116 mov ax,Tmap.OldFPUCW // get it in ax
118 mov Tmap.FPUCW,ax // store it
119 fldcw Tmap.FPUCW // load the FPU
122 mov ecx, Tmap.loop_count // ecx = width
123 mov edi, Tmap.dest_row_data // edi = dest pointer
125 // edi = pointer to start pixel in dest dib
128 mov eax,ecx // eax and ecx = width
129 shr ecx,5 // ecx = width / subdivision length
130 and eax,31 // eax = width mod subdivision length
131 jnz some_left_over // any leftover?
132 dec ecx // no, so special case last span
133 mov eax,32 // it's 8 pixels long
135 mov Tmap.Subdivisions,ecx // store widths
136 mov Tmap.WidthModLength,eax
138 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
139 // st0 st1 st2 st3 st4 st5 st6 st7
141 fld Tmap.l.u // U/ZL V/ZL
142 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
143 fld1 // 1 1/ZL U/ZL V/ZL
144 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
145 fld st // ZL ZL 1/ZL U/ZL V/ZL
146 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
147 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
148 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
150 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
151 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
153 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
155 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
156 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
157 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
158 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
159 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
161 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
163 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
164 // @todo overlap this guy
165 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
166 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
167 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
168 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
169 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
171 cmp ecx,0 // check for any full spans
172 jle HandleLeftoverPixels
176 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
177 // UR VR V/ZR 1/ZR U/ZR UL VL
179 // convert left side coords
181 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
182 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
183 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
185 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
186 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
187 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
189 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
191 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
192 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
193 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
194 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
196 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
197 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
199 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
200 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
201 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
203 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
204 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
206 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
207 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
208 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
209 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
210 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
211 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
212 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
215 // setup delta values
217 mov eax,Tmap.DeltaV // get v 16.16 step
218 mov ebx,eax // copy it
219 sar eax,16 // get v int step
220 shl ebx,16 // get v frac step
221 mov Tmap.DeltaVFrac,ebx // store it
222 imul eax,Tmap.src_offset // calculate texture step for v int step
224 mov ebx,Tmap.DeltaU // get u 16.16 step
225 mov ecx,ebx // copy it
226 sar ebx,16 // get u int step
227 shl ecx,16 // get u frac step
228 mov Tmap.DeltaUFrac,ecx // store it
229 add eax,ebx // calculate uint + vint step
230 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
231 add eax,Tmap.src_offset // calculate whole step + v carry
232 mov Tmap.uv_delta[0],eax // save in v-carry slot
234 // setup initial coordinates
235 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
237 mov ebx,esi // copy it
238 sar esi,16 // get integer part
239 shl ebx,16 // get fractional part
241 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
243 mov edx,ecx // copy it
244 sar edx,16 // get integer part
245 shl ecx,16 // get fractional part
246 imul edx,Tmap.src_offset // calc texture scanline address
247 add esi,edx // calc texture offset
248 add esi,Tmap.pixptr // calc address
250 // set up affine registers
256 mov ebp, Tmap.fx_dl_dx
267 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
268 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
269 // This divide should happen while the pixel span is drawn.
270 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
274 // edi = dest dib bits at current pixel
275 // esi = texture pointer at current u,v
277 // ebx = u fraction 0.32
278 // ecx = v fraction 0.32
280 // ebp = v carry scratch
282 mov al,[edi] // preread the destination cache line
284 mov Tmap.InnerLooper, 32/4 // Set up loop counter
289 sub eax, Tmap.pScreenBits
293 // Make ESI = DV:DU in 5:11,5:11 format
299 mov Tmap.DeltaUFrac, esi
301 // Make ECX = V:U in 5:11,5:11 format
312 // ecx = V:U in 8.6:10.8
313 // edx = zbuffer pointer
322 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
323 jle Skip0 // If pixel is covered, skip drawing
325 mov [edx+0], esi // Write z
327 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
328 shr ax, 12 // EAX = V:U in 6.10:16.0
329 rol eax, 4 // EAX = V:U in 0.0:6:6
330 and eax, 0ffh // clear upper bits
331 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
335 and eax, 0ffffh // clear upper bits
336 mov al, gr_fade_table[eax]
339 add ecx, Tmap.DeltaUFrac
340 add esi, Tmap.fx_dwdx
344 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
345 jle Skip1 // If pixel is covered, skip drawing
347 mov [edx+4], esi // Write z
349 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
350 shr ax, 12 // EAX = V:U in 6.10:16.0
351 rol eax, 4 // EAX = V:U in 0.0:6:6
352 and eax, 0ffh // clear upper bits
353 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
357 and eax, 0ffffh // clear upper bits
358 mov al, gr_fade_table[eax]
361 add ecx, Tmap.DeltaUFrac
362 add esi, Tmap.fx_dwdx
366 cmp esi, [edx+8] // Compare the Z depth of this pixel with zbuffer
367 jle Skip2 // If pixel is covered, skip drawing
369 mov [edx+8], esi // Write z
371 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
372 shr ax, 12 // EAX = V:U in 6.10:16.0
373 rol eax, 4 // EAX = V:U in 0.0:6:6
374 and eax, 0ffh // clear upper bits
375 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
379 and eax, 0ffffh // clear upper bits
380 mov al, gr_fade_table[eax]
383 add ecx, Tmap.DeltaUFrac
384 add esi, Tmap.fx_dwdx
388 cmp esi, [edx+12] // Compare the Z depth of this pixel with zbuffer
389 jle Skip3 // If pixel is covered, skip drawing
391 mov [edx+12], esi // Write z
393 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
394 shr ax, 12 // EAX = V:U in 6.10:16.0
395 rol eax, 4 // EAX = V:U in 0.0:6:6
396 and eax, 0ffh // clear upper bits
397 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
401 and eax, 0ffffh // clear upper bits
402 mov al, gr_fade_table[eax]
405 add ecx, Tmap.DeltaUFrac
406 add esi, Tmap.fx_dwdx
417 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
418 // ZR V/ZR 1/ZR U/ZR UL VL
420 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
421 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
422 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
423 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
425 dec Tmap.Subdivisions // decrement span count
426 jnz SpanLoop // loop back
429 HandleLeftoverPixels:
431 mov esi,Tmap.pixptr // load texture pointer
433 // edi = dest dib bits
434 // esi = current texture dib bits
435 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
436 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
438 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
439 jz FPUReturn ; nope, pop the FPU and bail
441 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
443 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
444 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
445 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
447 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
448 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
449 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
451 dec Tmap.WidthModLength ; calc how many steps to take
452 jz OnePixelSpan ; just one, don't do deltas'
454 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
457 // @todo rearrange things so we don't need these two instructions
458 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
459 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
461 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
462 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
463 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
464 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
465 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
466 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
468 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
470 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
471 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
473 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
475 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
476 fxch st(1) ; VR UR inv. inv. inv. dU VL
477 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
478 fxch st(6) ; dV UR inv. inv. inv. dU VR
480 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
481 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
482 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
484 fxch st(4) ; dU inv. inv. inv. UR VR
485 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
486 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
487 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
489 // @todo gross! these are to line up with the other loop
490 fld st(1) ; inv. inv. inv. inv. UR VR
491 fld st(2) ; inv. inv. inv. inv. inv. UR VR
494 // setup delta values
495 mov eax, Tmap.DeltaV // get v 16.16 step
496 mov ebx, eax // copy it
497 sar eax, 16 // get v int step
498 shl ebx, 16 // get v frac step
499 mov Tmap.DeltaVFrac, ebx // store it
500 imul eax, Tmap.src_offset // calc texture step for v int step
502 mov ebx, Tmap.DeltaU // get u 16.16 step
503 mov ecx, ebx // copy it
504 sar ebx, 16 // get the u int step
505 shl ecx, 16 // get the u frac step
506 mov Tmap.DeltaUFrac, ecx // store it
507 add eax, ebx // calc uint + vint step
508 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
509 add eax, Tmap.src_offset // calc whole step + v carry
510 mov Tmap.uv_delta[0], eax // save in v-carry slot
515 ; setup initial coordinates
516 mov esi, Tmap.UFixed // get u 16.16
517 mov ebx, esi // copy it
518 sar esi, 16 // get integer part
519 shl ebx, 16 // get fractional part
521 mov ecx, Tmap.VFixed // get v 16.16
522 mov edx, ecx // copy it
523 sar edx, 16 // get integer part
524 shl ecx, 16 // get fractional part
525 imul edx, Tmap.src_offset // calc texture scanline address
526 add esi, edx // calc texture offset
527 add esi, Tmap.pixptr // calc address
534 // mov edx, Tmap.DeltaUFrac
538 mov ebx, Tmap.fx_l_right
544 mov eax, Tmap.fx_dl_dx
553 sub eax, Tmap.pScreenBits
558 inc Tmap.WidthModLength
559 mov eax,Tmap.WidthModLength
563 mov Tmap.WidthModLength, eax
567 mov al,[edi] // preread the destination cache line
569 // Make ESI = DV:DU in 6:10,6:10 format
575 mov Tmap.DeltaUFrac, esi
577 // Make ECX = V:U in 6:10,6:10 format
588 // ecx = V:U in 8.6:10.8
589 // edx = zbuffer pointer
598 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
599 jle Skip0a // If pixel is covered, skip drawing
601 mov [edx+0], esi // Write z
603 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
604 shr ax, 12 // EAX = V:U in 6.10:16.0
605 rol eax, 4 // EAX = V:U in 0.0:6:6
606 and eax, 0ffh // clear upper bits
607 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
611 and eax, 0ffffh // clear upper bits
612 mov al, gr_fade_table[eax]
615 add ecx, Tmap.DeltaUFrac
616 add esi, Tmap.fx_dwdx
620 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
621 jle Skip1a // If pixel is covered, skip drawing
623 mov [edx+4], esi // Write z
625 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
626 shr ax, 12 // EAX = V:U in 6.10:16.0
627 rol eax, 4 // EAX = V:U in 0.0:6:6
628 and eax, 0ffh // clear upper bits
629 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
633 and eax, 0ffffh // clear upper bits
634 mov al, gr_fade_table[eax]
637 add ecx, Tmap.DeltaUFrac
638 add esi, Tmap.fx_dwdx
645 dec Tmap.WidthModLength
653 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
654 jle Skip0b // If pixel is covered, skip drawing
656 mov [edx+0], esi // Write z
658 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
659 shr ax, 12 // EAX = V:U in 6.10:16.0
660 rol eax, 4 // EAX = V:U in 0.0:6:6
661 and eax, 0ffh // clear upper bits
662 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
666 and eax, 0ffffh // clear upper bits
667 mov al, gr_fade_table[eax]
670 add ecx, Tmap.DeltaUFrac
671 add esi, Tmap.fx_dwdx
677 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
678 // xxx xxx xxx xxx xxx xxx xxx
687 fldcw Tmap.OldFPUCW // restore the FPU
700 void tmapscan_pln8_tiled_16x16()
703 switch(gr_zbuffering_mode) {
706 case GR_ZBUFF_FULL: // both
707 tmapscan_pln8_zbuffered_tiled_16x16();
709 case GR_ZBUFF_WRITE: // write only
710 tmapscan_pln8_zbuffered_tiled_16x16();
712 case GR_ZBUFF_READ: // read only
713 tmapscan_pln8_zbuffered_tiled_16x16();
718 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
719 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
720 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
722 if ( Tmap.fx_dl_dx < 0 ) {
723 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
724 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
725 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
726 // Assert( Tmap.fx_l > 31*F1_0 );
727 // Assert( Tmap.fx_l < 66*F1_0 );
728 // Assert( Tmap.fx_dl_dx >= 0 );
729 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
732 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
733 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
734 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
736 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
737 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
739 // Assert(Tmap.fx_w < 65536 );
740 // Assert(Tmap.fx_w >= 0 );
741 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
742 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
757 // Put the FPU in low precision mode
758 fstcw Tmap.OldFPUCW // store copy of CW
759 mov ax,Tmap.OldFPUCW // get it in ax
761 mov Tmap.FPUCW,ax // store it
762 fldcw Tmap.FPUCW // load the FPU
765 mov ecx, Tmap.loop_count // ecx = width
766 mov edi, Tmap.dest_row_data // edi = dest pointer
768 // edi = pointer to start pixel in dest dib
771 mov eax,ecx // eax and ecx = width
772 shr ecx,5 // ecx = width / subdivision length
773 and eax,31 // eax = width mod subdivision length
774 jnz some_left_over // any leftover?
775 dec ecx // no, so special case last span
776 mov eax,32 // it's 8 pixels long
778 mov Tmap.Subdivisions,ecx // store widths
779 mov Tmap.WidthModLength,eax
781 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
782 // st0 st1 st2 st3 st4 st5 st6 st7
784 fld Tmap.l.u // U/ZL V/ZL
785 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
786 fld1 // 1 1/ZL U/ZL V/ZL
787 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
788 fld st // ZL ZL 1/ZL U/ZL V/ZL
789 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
790 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
791 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
793 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
794 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
796 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
798 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
799 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
800 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
801 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
802 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
804 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
806 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
807 // @todo overlap this guy
808 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
809 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
810 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
811 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
812 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
814 cmp ecx,0 // check for any full spans
815 jle HandleLeftoverPixels
819 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
820 // UR VR V/ZR 1/ZR U/ZR UL VL
822 // convert left side coords
824 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
825 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
826 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
828 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
829 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
830 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
832 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
834 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
835 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
836 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
837 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
839 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
840 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
842 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
843 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
844 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
846 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
847 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
849 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
850 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
851 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
852 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
853 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
854 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
855 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
858 // setup delta values
860 mov eax,Tmap.DeltaV // get v 16.16 step
861 mov ebx,eax // copy it
862 sar eax,16 // get v int step
863 shl ebx,16 // get v frac step
864 mov Tmap.DeltaVFrac,ebx // store it
865 imul eax,Tmap.src_offset // calculate texture step for v int step
867 mov ebx,Tmap.DeltaU // get u 16.16 step
868 mov ecx,ebx // copy it
869 sar ebx,16 // get u int step
870 shl ecx,16 // get u frac step
871 mov Tmap.DeltaUFrac,ecx // store it
872 add eax,ebx // calculate uint + vint step
873 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
874 add eax,Tmap.src_offset // calculate whole step + v carry
875 mov Tmap.uv_delta[0],eax // save in v-carry slot
877 // setup initial coordinates
878 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
880 mov ebx,esi // copy it
881 sar esi,16 // get integer part
882 shl ebx,16 // get fractional part
884 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
886 mov edx,ecx // copy it
887 sar edx,16 // get integer part
888 shl ecx,16 // get fractional part
889 imul edx,Tmap.src_offset // calc texture scanline address
890 add esi,edx // calc texture offset
891 add esi,Tmap.pixptr // calc address
893 // set up affine registers
899 mov ebp, Tmap.fx_dl_dx
910 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
911 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
912 // This divide should happen while the pixel span is drawn.
913 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
917 // edi = dest dib bits at current pixel
918 // esi = texture pointer at current u,v
920 // ebx = u fraction 0.32
921 // ecx = v fraction 0.32
923 // ebp = v carry scratch
925 mov al,[edi] // preread the destination cache line
927 mov Tmap.InnerLooper, 32/4 // Set up loop counter
932 sub eax, Tmap.pScreenBits
936 // Make ESI = DV:DU in 6:10,6:10 format
942 mov Tmap.DeltaUFrac, esi
944 // Make ECX = V:U in 6:10,6:10 format
954 // ecx = V:U in 8.6:10.8
955 // edx = zbuffer pointer
964 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
965 shr ax, 12 // EAX = V:U in 6.10:16.0
966 rol eax, 4 // EAX = V:U in 0.0:6:6
967 and eax, 0ffh // clear upper bits
968 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
972 and eax, 0ffffh // clear upper bits
973 mov al, gr_fade_table[eax]
975 add ecx, Tmap.DeltaUFrac
979 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
980 shr ax, 12 // EAX = V:U in 6.10:16.0
981 rol eax, 4 // EAX = V:U in 0.0:6:6
982 and eax, 0ffh // clear upper bits
983 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
987 and eax, 0ffffh // clear upper bits
988 mov al, gr_fade_table[eax]
990 add ecx, Tmap.DeltaUFrac
994 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
995 shr ax, 12 // EAX = V:U in 6.10:16.0
996 rol eax, 4 // EAX = V:U in 0.0:6:6
997 and eax, 0ffh // clear upper bits
998 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1002 and eax, 0ffffh // clear upper bits
1003 mov al, gr_fade_table[eax]
1005 add ecx, Tmap.DeltaUFrac
1009 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1010 shr ax, 12 // EAX = V:U in 6.10:16.0
1011 rol eax, 4 // EAX = V:U in 0.0:6:6
1012 and eax, 0ffh // clear upper bits
1013 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1017 and eax, 0ffffh // clear upper bits
1018 mov al, gr_fade_table[eax]
1020 add ecx, Tmap.DeltaUFrac
1025 dec Tmap.InnerLooper
1030 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
1031 // ZR V/ZR 1/ZR U/ZR UL VL
1033 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
1034 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
1035 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
1036 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
1038 dec Tmap.Subdivisions // decrement span count
1039 jnz SpanLoop // loop back
1042 HandleLeftoverPixels:
1044 mov esi,Tmap.pixptr // load texture pointer
1046 // edi = dest dib bits
1047 // esi = current texture dib bits
1048 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
1049 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
1051 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
1052 jz FPUReturn ; nope, pop the FPU and bail
1054 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
1056 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
1057 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
1058 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
1060 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
1061 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
1062 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
1064 dec Tmap.WidthModLength ; calc how many steps to take
1065 jz OnePixelSpan ; just one, don't do deltas'
1067 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
1070 // @todo rearrange things so we don't need these two instructions
1071 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
1072 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
1074 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
1075 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
1076 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
1077 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
1078 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
1079 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
1081 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
1083 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
1084 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
1086 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
1088 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
1089 fxch st(1) ; VR UR inv. inv. inv. dU VL
1090 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
1091 fxch st(6) ; dV UR inv. inv. inv. dU VR
1093 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
1094 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
1095 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
1097 fxch st(4) ; dU inv. inv. inv. UR VR
1098 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
1099 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
1100 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
1102 // @todo gross! these are to line up with the other loop
1103 fld st(1) ; inv. inv. inv. inv. UR VR
1104 fld st(2) ; inv. inv. inv. inv. inv. UR VR
1107 // setup delta values
1108 mov eax, Tmap.DeltaV // get v 16.16 step
1109 mov ebx, eax // copy it
1110 sar eax, 16 // get v int step
1111 shl ebx, 16 // get v frac step
1112 mov Tmap.DeltaVFrac, ebx // store it
1113 imul eax, Tmap.src_offset // calc texture step for v int step
1115 mov ebx, Tmap.DeltaU // get u 16.16 step
1116 mov ecx, ebx // copy it
1117 sar ebx, 16 // get the u int step
1118 shl ecx, 16 // get the u frac step
1119 mov Tmap.DeltaUFrac, ecx // store it
1120 add eax, ebx // calc uint + vint step
1121 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
1122 add eax, Tmap.src_offset // calc whole step + v carry
1123 mov Tmap.uv_delta[0], eax // save in v-carry slot
1128 ; setup initial coordinates
1129 mov esi, Tmap.UFixed // get u 16.16
1130 mov ebx, esi // copy it
1131 sar esi, 16 // get integer part
1132 shl ebx, 16 // get fractional part
1134 mov ecx, Tmap.VFixed // get v 16.16
1135 mov edx, ecx // copy it
1136 sar edx, 16 // get integer part
1137 shl ecx, 16 // get fractional part
1138 imul edx, Tmap.src_offset // calc texture scanline address
1139 add esi, edx // calc texture offset
1140 add esi, Tmap.pixptr // calc address
1147 // mov edx, Tmap.DeltaUFrac
1151 mov ebx, Tmap.fx_l_right
1157 mov eax, Tmap.fx_dl_dx
1166 sub eax, Tmap.pScreenBits
1171 inc Tmap.WidthModLength
1172 mov eax,Tmap.WidthModLength
1176 mov Tmap.WidthModLength, eax
1180 mov al,[edi] // preread the destination cache line
1182 // Make ESI = DV:DU in 6:10,6:10 format
1183 mov eax, Tmap.DeltaV
1185 mov esi, Tmap.DeltaU
1188 mov Tmap.DeltaUFrac, esi
1190 // Make ECX = V:U in 6:10,6:10 format
1191 mov eax, Tmap.VFixed
1193 mov ecx, Tmap.UFixed
1201 // ecx = V:U in 8.6:10.8
1202 // edx = zbuffer pointer
1204 // edi = screen data
1211 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1212 shr ax, 12 // EAX = V:U in 6.10:16.0
1213 rol eax, 4 // EAX = V:U in 0.0:6:6
1214 and eax, 0ffh // clear upper bits
1215 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1219 and eax, 0ffffh // clear upper bits
1220 mov al, gr_fade_table[eax]
1222 add ecx, Tmap.DeltaUFrac
1226 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1227 shr ax, 12 // EAX = V:U in 6.10:16.0
1228 rol eax, 4 // EAX = V:U in 0.0:6:6
1229 and eax, 0ffh // clear upper bits
1230 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1234 and eax, 0ffffh // clear upper bits
1235 mov al, gr_fade_table[eax]
1237 add ecx, Tmap.DeltaUFrac
1244 dec Tmap.WidthModLength
1252 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1253 shr ax, 12 // EAX = V:U in 6.10:16.0
1254 rol eax, 4 // EAX = V:U in 0.0:6:6
1255 and eax, 0ffh // clear upper bits
1256 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1260 and eax, 0ffffh // clear upper bits
1261 mov al, gr_fade_table[eax]
1263 add ecx, Tmap.DeltaUFrac
1269 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
1270 // xxx xxx xxx xxx xxx xxx xxx
1279 fldcw Tmap.OldFPUCW // restore the FPU