2 * $Logfile: /Freespace2/code/Graphics/TmapScanTiled32x32.cpp $
7 * Routines for drawing tiled 32x32 textues
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 4 11/30/98 5:31p Dave
15 * Fixed up Fred support for software mode.
17 * 3 11/30/98 1:07p Dave
18 * 16 bit conversion, first run.
20 * 2 10/07/98 10:53a Dave
23 * 1 10/07/98 10:49a Dave
25 * 6 4/23/98 9:55a John
26 * Fixed some bugs in the tiled tmapper causing bright dots to appear all
29 * 5 3/10/98 4:19p John
30 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
31 * & Glide have popups and print screen. Took out all >8bpp software
32 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
33 * support Fred. Made zbuffering key off of functions rather than one
36 * 4 1/23/98 5:08p John
37 * Took L out of vertex structure used B (blue) instead. Took all small
38 * fireballs out of fireball types and used particles instead. Fixed some
39 * debris explosion things. Restructured fireball code. Restructured
40 * some lighting code. Made dynamic lighting on by default. Made groups
41 * of lasers only cast one light. Made fireballs not cast light.
43 * 3 12/04/97 10:38a John
44 * Fixed tiled texture mappers that were swapping uvs.
46 * 2 10/14/97 9:19a John
47 * removed fdiv warnings.
49 * 1 6/18/97 4:02p John
50 * added new code for 16x16 and 32x32 tiled tmaps.
58 #include "grinternal.h"
60 #include "tmapscanline.h"
65 // Needed to keep warning 4725 to stay away. See PsTypes.h for details why.
66 void disable_warning_4725_stub_tst32()
70 void tmapscan_pln8_zbuffered_tiled_32x32()
72 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
73 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
74 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
76 if ( Tmap.fx_dl_dx < 0 ) {
77 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
78 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
79 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
80 // Assert( Tmap.fx_l > 31*F1_0 );
81 // Assert( Tmap.fx_l < 66*F1_0 );
82 // Assert( Tmap.fx_dl_dx >= 0 );
83 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
86 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
87 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
88 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
90 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
91 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
93 // Assert(Tmap.fx_w < 65536 );
94 // Assert(Tmap.fx_w >= 0 );
95 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
96 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
111 // Put the FPU in low precision mode
112 fstcw Tmap.OldFPUCW // store copy of CW
113 mov ax,Tmap.OldFPUCW // get it in ax
115 mov Tmap.FPUCW,ax // store it
116 fldcw Tmap.FPUCW // load the FPU
119 mov ecx, Tmap.loop_count // ecx = width
120 mov edi, Tmap.dest_row_data // edi = dest pointer
122 // edi = pointer to start pixel in dest dib
125 mov eax,ecx // eax and ecx = width
126 shr ecx,5 // ecx = width / subdivision length
127 and eax,31 // eax = width mod subdivision length
128 jnz some_left_over // any leftover?
129 dec ecx // no, so special case last span
130 mov eax,32 // it's 8 pixels long
132 mov Tmap.Subdivisions,ecx // store widths
133 mov Tmap.WidthModLength,eax
135 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
136 // st0 st1 st2 st3 st4 st5 st6 st7
138 fld Tmap.l.u // U/ZL V/ZL
139 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
140 fld1 // 1 1/ZL U/ZL V/ZL
141 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
142 fld st // ZL ZL 1/ZL U/ZL V/ZL
143 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
144 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
145 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
147 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
148 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
150 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
152 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
153 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
154 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
155 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
156 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
158 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
160 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
161 // @todo overlap this guy
162 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
163 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
164 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
165 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
166 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
168 cmp ecx,0 // check for any full spans
169 jle HandleLeftoverPixels
173 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
174 // UR VR V/ZR 1/ZR U/ZR UL VL
176 // convert left side coords
178 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
179 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
180 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
182 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
183 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
184 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
186 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
188 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
189 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
190 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
191 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
193 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
194 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
196 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
197 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
198 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
200 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
201 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
203 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
204 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
205 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
206 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
207 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
208 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
209 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
212 // setup delta values
214 mov eax,Tmap.DeltaV // get v 16.16 step
215 mov ebx,eax // copy it
216 sar eax,16 // get v int step
217 shl ebx,16 // get v frac step
218 mov Tmap.DeltaVFrac,ebx // store it
219 imul eax,Tmap.src_offset // calculate texture step for v int step
221 mov ebx,Tmap.DeltaU // get u 16.16 step
222 mov ecx,ebx // copy it
223 sar ebx,16 // get u int step
224 shl ecx,16 // get u frac step
225 mov Tmap.DeltaUFrac,ecx // store it
226 add eax,ebx // calculate uint + vint step
227 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
228 add eax,Tmap.src_offset // calculate whole step + v carry
229 mov Tmap.uv_delta[0],eax // save in v-carry slot
231 // setup initial coordinates
232 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
234 mov ebx,esi // copy it
235 sar esi,16 // get integer part
236 shl ebx,16 // get fractional part
238 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
240 mov edx,ecx // copy it
241 sar edx,16 // get integer part
242 shl ecx,16 // get fractional part
243 imul edx,Tmap.src_offset // calc texture scanline address
244 add esi,edx // calc texture offset
245 add esi,Tmap.pixptr // calc address
247 // set up affine registers
253 mov ebp, Tmap.fx_dl_dx
264 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
265 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
266 // This divide should happen while the pixel span is drawn.
267 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
271 // edi = dest dib bits at current pixel
272 // esi = texture pointer at current u,v
274 // ebx = u fraction 0.32
275 // ecx = v fraction 0.32
277 // ebp = v carry scratch
279 mov al,[edi] // preread the destination cache line
281 mov Tmap.InnerLooper, 32/4 // Set up loop counter
284 sub eax, Tmap.pScreenBits
289 // Make ESI = DV:DU in 5:11,5:11 format
295 mov Tmap.DeltaUFrac, esi
297 // Make ECX = V:U in 5:11,5:11 format
308 // ecx = V:U in 8.6:10.8
309 // edx = zbuffer pointer
318 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
319 jle Skip0 // If pixel is covered, skip drawing
321 mov [edx+0], esi // Write z
323 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
324 shr ax, 11 // EAX = V:U in 6.10:16.0
325 rol eax, 5 // EAX = V:U in 0.0:6:6
326 and eax, 03ffh // clear upper bits
327 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
331 and eax, 0ffffh // clear upper bits
332 mov al, gr_fade_table[eax]
335 add ecx, Tmap.DeltaUFrac
336 add esi, Tmap.fx_dwdx
340 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
341 jle Skip1 // If pixel is covered, skip drawing
343 mov [edx+4], esi // Write z
345 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
346 shr ax, 11 // EAX = V:U in 6.10:16.0
347 rol eax, 5 // EAX = V:U in 0.0:6:6
348 and eax, 03ffh // clear upper bits
349 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
353 and eax, 0ffffh // clear upper bits
354 mov al, gr_fade_table[eax]
357 add ecx, Tmap.DeltaUFrac
358 add esi, Tmap.fx_dwdx
362 cmp esi, [edx+8] // Compare the Z depth of this pixel with zbuffer
363 jle Skip2 // If pixel is covered, skip drawing
365 mov [edx+8], esi // Write z
367 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
368 shr ax, 11 // EAX = V:U in 6.10:16.0
369 rol eax, 5 // EAX = V:U in 0.0:6:6
370 and eax, 03ffh // clear upper bits
371 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
375 and eax, 0ffffh // clear upper bits
376 mov al, gr_fade_table[eax]
379 add ecx, Tmap.DeltaUFrac
380 add esi, Tmap.fx_dwdx
384 cmp esi, [edx+12] // Compare the Z depth of this pixel with zbuffer
385 jle Skip3 // If pixel is covered, skip drawing
387 mov [edx+12], esi // Write z
389 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
390 shr ax, 11 // EAX = V:U in 6.10:16.0
391 rol eax, 5 // EAX = V:U in 0.0:6:6
392 and eax, 03ffh // clear upper bits
393 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
397 and eax, 0ffffh // clear upper bits
398 mov al, gr_fade_table[eax]
401 add ecx, Tmap.DeltaUFrac
402 add esi, Tmap.fx_dwdx
413 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
414 // ZR V/ZR 1/ZR U/ZR UL VL
416 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
417 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
418 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
419 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
421 dec Tmap.Subdivisions // decrement span count
422 jnz SpanLoop // loop back
425 HandleLeftoverPixels:
427 mov esi,Tmap.pixptr // load texture pointer
429 // edi = dest dib bits
430 // esi = current texture dib bits
431 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
432 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
434 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
435 jz FPUReturn ; nope, pop the FPU and bail
437 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
439 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
440 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
441 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
443 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
444 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
445 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
447 dec Tmap.WidthModLength ; calc how many steps to take
448 jz OnePixelSpan ; just one, don't do deltas'
450 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
453 // @todo rearrange things so we don't need these two instructions
454 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
455 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
457 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
458 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
459 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
460 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
461 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
462 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
464 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
466 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
467 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
469 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
471 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
472 fxch st(1) ; VR UR inv. inv. inv. dU VL
473 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
474 fxch st(6) ; dV UR inv. inv. inv. dU VR
476 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
477 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
478 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
480 fxch st(4) ; dU inv. inv. inv. UR VR
481 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
482 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
483 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
485 // @todo gross! these are to line up with the other loop
486 fld st(1) ; inv. inv. inv. inv. UR VR
487 fld st(2) ; inv. inv. inv. inv. inv. UR VR
490 // setup delta values
491 mov eax, Tmap.DeltaV // get v 16.16 step
492 mov ebx, eax // copy it
493 sar eax, 16 // get v int step
494 shl ebx, 16 // get v frac step
495 mov Tmap.DeltaVFrac, ebx // store it
496 imul eax, Tmap.src_offset // calc texture step for v int step
498 mov ebx, Tmap.DeltaU // get u 16.16 step
499 mov ecx, ebx // copy it
500 sar ebx, 16 // get the u int step
501 shl ecx, 16 // get the u frac step
502 mov Tmap.DeltaUFrac, ecx // store it
503 add eax, ebx // calc uint + vint step
504 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
505 add eax, Tmap.src_offset // calc whole step + v carry
506 mov Tmap.uv_delta[0], eax // save in v-carry slot
511 ; setup initial coordinates
512 mov esi, Tmap.UFixed // get u 16.16
513 mov ebx, esi // copy it
514 sar esi, 16 // get integer part
515 shl ebx, 16 // get fractional part
517 mov ecx, Tmap.VFixed // get v 16.16
518 mov edx, ecx // copy it
519 sar edx, 16 // get integer part
520 shl ecx, 16 // get fractional part
521 imul edx, Tmap.src_offset // calc texture scanline address
522 add esi, edx // calc texture offset
523 add esi, Tmap.pixptr // calc address
530 // mov edx, Tmap.DeltaUFrac
535 mov ebx, Tmap.fx_l_right
541 mov eax, Tmap.fx_dl_dx
550 sub eax, Tmap.pScreenBits
555 inc Tmap.WidthModLength
556 mov eax,Tmap.WidthModLength
560 mov Tmap.WidthModLength, eax
564 mov al,[edi] // preread the destination cache line
566 // Make ESI = DV:DU in 6:10,6:10 format
572 mov Tmap.DeltaUFrac, esi
574 // Make ECX = V:U in 6:10,6:10 format
585 // ecx = V:U in 8.6:10.8
586 // edx = zbuffer pointer
595 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
596 jle Skip0a // If pixel is covered, skip drawing
598 mov [edx+0], esi // Write z
600 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
601 shr ax, 11 // EAX = V:U in 6.10:16.0
602 rol eax, 5 // EAX = V:U in 0.0:6:6
603 and eax, 03ffh // clear upper bits
604 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
608 and eax, 0ffffh // clear upper bits
609 mov al, gr_fade_table[eax]
612 add ecx, Tmap.DeltaUFrac
613 add esi, Tmap.fx_dwdx
617 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
618 jle Skip1a // If pixel is covered, skip drawing
620 mov [edx+4], esi // Write z
622 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
623 shr ax, 11 // EAX = V:U in 6.10:16.0
624 rol eax, 5 // EAX = V:U in 0.0:6:6
625 and eax, 03ffh // clear upper bits
626 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
630 and eax, 0ffffh // clear upper bits
631 mov al, gr_fade_table[eax]
634 add ecx, Tmap.DeltaUFrac
635 add esi, Tmap.fx_dwdx
642 dec Tmap.WidthModLength
650 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
651 jle Skip0b // If pixel is covered, skip drawing
653 mov [edx+0], esi // Write z
655 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
656 shr ax, 11 // EAX = V:U in 6.10:16.0
657 rol eax, 5 // EAX = V:U in 0.0:6:6
658 and eax, 03ffh // clear upper bits
659 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
663 and eax, 0ffffh // clear upper bits
664 mov al, gr_fade_table[eax]
667 add ecx, Tmap.DeltaUFrac
668 add esi, Tmap.fx_dwdx
674 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
675 // xxx xxx xxx xxx xxx xxx xxx
684 fldcw Tmap.OldFPUCW // restore the FPU
697 void tmapscan_pln8_tiled_32x32()
700 switch(gr_zbuffering_mode) {
703 case GR_ZBUFF_FULL: // both
704 tmapscan_pln8_zbuffered_tiled_32x32();
706 case GR_ZBUFF_WRITE: // write only
707 tmapscan_pln8_zbuffered_tiled_32x32();
709 case GR_ZBUFF_READ: // read only
710 tmapscan_pln8_zbuffered_tiled_32x32();
715 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
716 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
717 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
719 if ( Tmap.fx_dl_dx < 0 ) {
720 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
721 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
722 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
723 // Assert( Tmap.fx_l > 31*F1_0 );
724 // Assert( Tmap.fx_l < 66*F1_0 );
725 // Assert( Tmap.fx_dl_dx >= 0 );
726 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
729 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
730 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
731 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
733 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
734 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
736 // Assert(Tmap.fx_w < 65536 );
737 // Assert(Tmap.fx_w >= 0 );
738 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
739 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
754 // Put the FPU in low precision mode
755 fstcw Tmap.OldFPUCW // store copy of CW
756 mov ax,Tmap.OldFPUCW // get it in ax
758 mov Tmap.FPUCW,ax // store it
759 fldcw Tmap.FPUCW // load the FPU
762 mov ecx, Tmap.loop_count // ecx = width
763 mov edi, Tmap.dest_row_data // edi = dest pointer
765 // edi = pointer to start pixel in dest dib
768 mov eax,ecx // eax and ecx = width
769 shr ecx,5 // ecx = width / subdivision length
770 and eax,31 // eax = width mod subdivision length
771 jnz some_left_over // any leftover?
772 dec ecx // no, so special case last span
773 mov eax,32 // it's 8 pixels long
775 mov Tmap.Subdivisions,ecx // store widths
776 mov Tmap.WidthModLength,eax
778 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
779 // st0 st1 st2 st3 st4 st5 st6 st7
781 fld Tmap.l.u // U/ZL V/ZL
782 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
783 fld1 // 1 1/ZL U/ZL V/ZL
784 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
785 fld st // ZL ZL 1/ZL U/ZL V/ZL
786 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
787 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
788 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
790 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
791 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
793 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
795 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
796 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
797 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
798 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
799 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
801 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
803 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
804 // @todo overlap this guy
805 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
806 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
807 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
808 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
809 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
811 cmp ecx,0 // check for any full spans
812 jle HandleLeftoverPixels
816 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
817 // UR VR V/ZR 1/ZR U/ZR UL VL
819 // convert left side coords
821 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
822 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
823 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
825 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
826 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
827 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
829 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
831 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
832 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
833 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
834 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
836 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
837 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
839 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
840 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
841 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
843 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
844 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
846 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
847 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
848 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
849 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
850 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
851 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
852 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
855 // setup delta values
857 mov eax,Tmap.DeltaV // get v 16.16 step
858 mov ebx,eax // copy it
859 sar eax,16 // get v int step
860 shl ebx,16 // get v frac step
861 mov Tmap.DeltaVFrac,ebx // store it
862 imul eax,Tmap.src_offset // calculate texture step for v int step
864 mov ebx,Tmap.DeltaU // get u 16.16 step
865 mov ecx,ebx // copy it
866 sar ebx,16 // get u int step
867 shl ecx,16 // get u frac step
868 mov Tmap.DeltaUFrac,ecx // store it
869 add eax,ebx // calculate uint + vint step
870 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
871 add eax,Tmap.src_offset // calculate whole step + v carry
872 mov Tmap.uv_delta[0],eax // save in v-carry slot
874 // setup initial coordinates
875 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
877 mov ebx,esi // copy it
878 sar esi,16 // get integer part
879 shl ebx,16 // get fractional part
881 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
883 mov edx,ecx // copy it
884 sar edx,16 // get integer part
885 shl ecx,16 // get fractional part
886 imul edx,Tmap.src_offset // calc texture scanline address
887 add esi,edx // calc texture offset
888 add esi,Tmap.pixptr // calc address
890 // set up affine registers
896 mov ebp, Tmap.fx_dl_dx
907 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
908 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
909 // This divide should happen while the pixel span is drawn.
910 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
914 // edi = dest dib bits at current pixel
915 // esi = texture pointer at current u,v
917 // ebx = u fraction 0.32
918 // ecx = v fraction 0.32
920 // ebp = v carry scratch
922 mov al,[edi] // preread the destination cache line
924 mov Tmap.InnerLooper, 32/4 // Set up loop counter
927 sub eax, Tmap.pScreenBits
932 // Make ESI = DV:DU in 6:10,6:10 format
938 mov Tmap.DeltaUFrac, esi
940 // Make ECX = V:U in 6:10,6:10 format
950 // ecx = V:U in 8.6:10.8
951 // edx = zbuffer pointer
960 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
961 shr ax, 11 // EAX = V:U in 6.10:16.0
962 rol eax, 5 // EAX = V:U in 0.0:6:6
963 and eax, 03ffh // clear upper bits
964 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
968 and eax, 0ffffh // clear upper bits
969 mov al, gr_fade_table[eax]
971 add ecx, Tmap.DeltaUFrac
975 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
976 shr ax, 11 // EAX = V:U in 6.10:16.0
977 rol eax, 5 // EAX = V:U in 0.0:6:6
978 and eax, 03ffh // clear upper bits
979 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
983 and eax, 0ffffh // clear upper bits
984 mov al, gr_fade_table[eax]
986 add ecx, Tmap.DeltaUFrac
990 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
991 shr ax, 11 // EAX = V:U in 6.10:16.0
992 rol eax, 5 // EAX = V:U in 0.0:6:6
993 and eax, 03ffh // clear upper bits
994 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
998 and eax, 0ffffh // clear upper bits
999 mov al, gr_fade_table[eax]
1001 add ecx, Tmap.DeltaUFrac
1005 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1006 shr ax, 11 // EAX = V:U in 6.10:16.0
1007 rol eax, 5 // EAX = V:U in 0.0:6:6
1008 and eax, 03ffh // clear upper bits
1009 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1013 and eax, 0ffffh // clear upper bits
1014 mov al, gr_fade_table[eax]
1016 add ecx, Tmap.DeltaUFrac
1021 dec Tmap.InnerLooper
1026 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
1027 // ZR V/ZR 1/ZR U/ZR UL VL
1029 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
1030 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
1031 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
1032 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
1034 dec Tmap.Subdivisions // decrement span count
1035 jnz SpanLoop // loop back
1038 HandleLeftoverPixels:
1040 mov esi,Tmap.pixptr // load texture pointer
1042 // edi = dest dib bits
1043 // esi = current texture dib bits
1044 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
1045 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
1047 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
1048 jz FPUReturn ; nope, pop the FPU and bail
1050 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
1052 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
1053 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
1054 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
1056 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
1057 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
1058 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
1060 dec Tmap.WidthModLength ; calc how many steps to take
1061 jz OnePixelSpan ; just one, don't do deltas'
1063 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
1066 // @todo rearrange things so we don't need these two instructions
1067 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
1068 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
1070 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
1071 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
1072 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
1073 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
1074 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
1075 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
1077 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
1079 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
1080 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
1082 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
1084 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
1085 fxch st(1) ; VR UR inv. inv. inv. dU VL
1086 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
1087 fxch st(6) ; dV UR inv. inv. inv. dU VR
1089 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
1090 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
1091 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
1093 fxch st(4) ; dU inv. inv. inv. UR VR
1094 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
1095 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
1096 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
1098 // @todo gross! these are to line up with the other loop
1099 fld st(1) ; inv. inv. inv. inv. UR VR
1100 fld st(2) ; inv. inv. inv. inv. inv. UR VR
1103 // setup delta values
1104 mov eax, Tmap.DeltaV // get v 16.16 step
1105 mov ebx, eax // copy it
1106 sar eax, 16 // get v int step
1107 shl ebx, 16 // get v frac step
1108 mov Tmap.DeltaVFrac, ebx // store it
1109 imul eax, Tmap.src_offset // calc texture step for v int step
1111 mov ebx, Tmap.DeltaU // get u 16.16 step
1112 mov ecx, ebx // copy it
1113 sar ebx, 16 // get the u int step
1114 shl ecx, 16 // get the u frac step
1115 mov Tmap.DeltaUFrac, ecx // store it
1116 add eax, ebx // calc uint + vint step
1117 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
1118 add eax, Tmap.src_offset // calc whole step + v carry
1119 mov Tmap.uv_delta[0], eax // save in v-carry slot
1124 ; setup initial coordinates
1125 mov esi, Tmap.UFixed // get u 16.16
1126 mov ebx, esi // copy it
1127 sar esi, 16 // get integer part
1128 shl ebx, 16 // get fractional part
1130 mov ecx, Tmap.VFixed // get v 16.16
1131 mov edx, ecx // copy it
1132 sar edx, 16 // get integer part
1133 shl ecx, 16 // get fractional part
1134 imul edx, Tmap.src_offset // calc texture scanline address
1135 add esi, edx // calc texture offset
1136 add esi, Tmap.pixptr // calc address
1143 // mov edx, Tmap.DeltaUFrac
1147 mov ebx, Tmap.fx_l_right
1153 mov eax, Tmap.fx_dl_dx
1162 sub eax, Tmap.pScreenBits
1167 inc Tmap.WidthModLength
1168 mov eax,Tmap.WidthModLength
1172 mov Tmap.WidthModLength, eax
1176 mov al,[edi] // preread the destination cache line
1178 // Make ESI = DV:DU in 6:10,6:10 format
1179 mov eax, Tmap.DeltaU
1181 mov esi, Tmap.DeltaV
1184 mov Tmap.DeltaUFrac, esi
1186 // Make ECX = V:U in 6:10,6:10 format
1187 mov eax, Tmap.UFixed
1189 mov ecx, Tmap.VFixed
1197 // ecx = V:U in 8.6:10.8
1198 // edx = zbuffer pointer
1200 // edi = screen data
1207 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1208 shr ax, 11 // EAX = V:U in 6.10:16.0
1209 rol eax, 5 // EAX = V:U in 0.0:6:6
1210 and eax, 03ffh // clear upper bits
1211 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1215 and eax, 0ffffh // clear upper bits
1216 mov al, gr_fade_table[eax]
1218 add ecx, Tmap.DeltaUFrac
1222 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1223 shr ax, 11 // EAX = V:U in 6.10:16.0
1224 rol eax, 5 // EAX = V:U in 0.0:6:6
1225 and eax, 03ffh // clear upper bits
1226 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1230 and eax, 0ffffh // clear upper bits
1231 mov al, gr_fade_table[eax]
1233 add ecx, Tmap.DeltaUFrac
1240 dec Tmap.WidthModLength
1248 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1249 shr ax, 11 // EAX = V:U in 6.10:16.0
1250 rol eax, 5 // EAX = V:U in 0.0:6:6
1251 and eax, 03ffh // clear upper bits
1252 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1256 and eax, 0ffffh // clear upper bits
1257 mov al, gr_fade_table[eax]
1259 add ecx, Tmap.DeltaUFrac
1265 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
1266 // xxx xxx xxx xxx xxx xxx xxx
1275 fldcw Tmap.OldFPUCW // restore the FPU