2 * $Logfile: /Freespace2/code/Graphics/TmapScanTiled32x32.cpp $
7 * Routines for drawing tiled 32x32 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_tst32()
73 void tmapscan_pln8_zbuffered_tiled_32x32()
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
287 sub eax, Tmap.pScreenBits
292 // Make ESI = DV:DU in 5:11,5:11 format
298 mov Tmap.DeltaUFrac, esi
300 // Make ECX = V:U in 5:11,5:11 format
311 // ecx = V:U in 8.6:10.8
312 // edx = zbuffer pointer
321 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
322 jle Skip0 // If pixel is covered, skip drawing
324 mov [edx+0], esi // Write z
326 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
327 shr ax, 11 // EAX = V:U in 6.10:16.0
328 rol eax, 5 // EAX = V:U in 0.0:6:6
329 and eax, 03ffh // clear upper bits
330 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
334 and eax, 0ffffh // clear upper bits
335 mov al, gr_fade_table[eax]
338 add ecx, Tmap.DeltaUFrac
339 add esi, Tmap.fx_dwdx
343 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
344 jle Skip1 // If pixel is covered, skip drawing
346 mov [edx+4], esi // Write z
348 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
349 shr ax, 11 // EAX = V:U in 6.10:16.0
350 rol eax, 5 // EAX = V:U in 0.0:6:6
351 and eax, 03ffh // clear upper bits
352 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
356 and eax, 0ffffh // clear upper bits
357 mov al, gr_fade_table[eax]
360 add ecx, Tmap.DeltaUFrac
361 add esi, Tmap.fx_dwdx
365 cmp esi, [edx+8] // Compare the Z depth of this pixel with zbuffer
366 jle Skip2 // If pixel is covered, skip drawing
368 mov [edx+8], esi // Write z
370 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
371 shr ax, 11 // EAX = V:U in 6.10:16.0
372 rol eax, 5 // EAX = V:U in 0.0:6:6
373 and eax, 03ffh // clear upper bits
374 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
378 and eax, 0ffffh // clear upper bits
379 mov al, gr_fade_table[eax]
382 add ecx, Tmap.DeltaUFrac
383 add esi, Tmap.fx_dwdx
387 cmp esi, [edx+12] // Compare the Z depth of this pixel with zbuffer
388 jle Skip3 // If pixel is covered, skip drawing
390 mov [edx+12], esi // Write z
392 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
393 shr ax, 11 // EAX = V:U in 6.10:16.0
394 rol eax, 5 // EAX = V:U in 0.0:6:6
395 and eax, 03ffh // clear upper bits
396 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
400 and eax, 0ffffh // clear upper bits
401 mov al, gr_fade_table[eax]
404 add ecx, Tmap.DeltaUFrac
405 add esi, Tmap.fx_dwdx
416 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
417 // ZR V/ZR 1/ZR U/ZR UL VL
419 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
420 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
421 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
422 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
424 dec Tmap.Subdivisions // decrement span count
425 jnz SpanLoop // loop back
428 HandleLeftoverPixels:
430 mov esi,Tmap.pixptr // load texture pointer
432 // edi = dest dib bits
433 // esi = current texture dib bits
434 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
435 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
437 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
438 jz FPUReturn ; nope, pop the FPU and bail
440 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
442 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
443 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
444 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
446 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
447 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
448 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
450 dec Tmap.WidthModLength ; calc how many steps to take
451 jz OnePixelSpan ; just one, don't do deltas'
453 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
456 // @todo rearrange things so we don't need these two instructions
457 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
458 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
460 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
461 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
462 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
463 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
464 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
465 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
467 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
469 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
470 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
472 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
474 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
475 fxch st(1) ; VR UR inv. inv. inv. dU VL
476 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
477 fxch st(6) ; dV UR inv. inv. inv. dU VR
479 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
480 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
481 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
483 fxch st(4) ; dU inv. inv. inv. UR VR
484 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
485 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
486 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
488 // @todo gross! these are to line up with the other loop
489 fld st(1) ; inv. inv. inv. inv. UR VR
490 fld st(2) ; inv. inv. inv. inv. inv. UR VR
493 // setup delta values
494 mov eax, Tmap.DeltaV // get v 16.16 step
495 mov ebx, eax // copy it
496 sar eax, 16 // get v int step
497 shl ebx, 16 // get v frac step
498 mov Tmap.DeltaVFrac, ebx // store it
499 imul eax, Tmap.src_offset // calc texture step for v int step
501 mov ebx, Tmap.DeltaU // get u 16.16 step
502 mov ecx, ebx // copy it
503 sar ebx, 16 // get the u int step
504 shl ecx, 16 // get the u frac step
505 mov Tmap.DeltaUFrac, ecx // store it
506 add eax, ebx // calc uint + vint step
507 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
508 add eax, Tmap.src_offset // calc whole step + v carry
509 mov Tmap.uv_delta[0], eax // save in v-carry slot
514 ; setup initial coordinates
515 mov esi, Tmap.UFixed // get u 16.16
516 mov ebx, esi // copy it
517 sar esi, 16 // get integer part
518 shl ebx, 16 // get fractional part
520 mov ecx, Tmap.VFixed // get v 16.16
521 mov edx, ecx // copy it
522 sar edx, 16 // get integer part
523 shl ecx, 16 // get fractional part
524 imul edx, Tmap.src_offset // calc texture scanline address
525 add esi, edx // calc texture offset
526 add esi, Tmap.pixptr // calc address
533 // 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, 11 // EAX = V:U in 6.10:16.0
605 rol eax, 5 // EAX = V:U in 0.0:6:6
606 and eax, 03ffh // 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, 11 // EAX = V:U in 6.10:16.0
627 rol eax, 5 // EAX = V:U in 0.0:6:6
628 and eax, 03ffh // 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, 11 // EAX = V:U in 6.10:16.0
660 rol eax, 5 // EAX = V:U in 0.0:6:6
661 and eax, 03ffh // 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_32x32()
703 switch(gr_zbuffering_mode) {
706 case GR_ZBUFF_FULL: // both
707 tmapscan_pln8_zbuffered_tiled_32x32();
709 case GR_ZBUFF_WRITE: // write only
710 tmapscan_pln8_zbuffered_tiled_32x32();
712 case GR_ZBUFF_READ: // read only
713 tmapscan_pln8_zbuffered_tiled_32x32();
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
930 sub eax, Tmap.pScreenBits
935 // Make ESI = DV:DU in 6:10,6:10 format
941 mov Tmap.DeltaUFrac, esi
943 // Make ECX = V:U in 6:10,6:10 format
953 // ecx = V:U in 8.6:10.8
954 // edx = zbuffer pointer
963 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
964 shr ax, 11 // EAX = V:U in 6.10:16.0
965 rol eax, 5 // EAX = V:U in 0.0:6:6
966 and eax, 03ffh // clear upper bits
967 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
971 and eax, 0ffffh // clear upper bits
972 mov al, gr_fade_table[eax]
974 add ecx, Tmap.DeltaUFrac
978 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
979 shr ax, 11 // EAX = V:U in 6.10:16.0
980 rol eax, 5 // EAX = V:U in 0.0:6:6
981 and eax, 03ffh // clear upper bits
982 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
986 and eax, 0ffffh // clear upper bits
987 mov al, gr_fade_table[eax]
989 add ecx, Tmap.DeltaUFrac
993 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
994 shr ax, 11 // EAX = V:U in 6.10:16.0
995 rol eax, 5 // EAX = V:U in 0.0:6:6
996 and eax, 03ffh // clear upper bits
997 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1001 and eax, 0ffffh // clear upper bits
1002 mov al, gr_fade_table[eax]
1004 add ecx, Tmap.DeltaUFrac
1008 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1009 shr ax, 11 // EAX = V:U in 6.10:16.0
1010 rol eax, 5 // EAX = V:U in 0.0:6:6
1011 and eax, 03ffh // clear upper bits
1012 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1016 and eax, 0ffffh // clear upper bits
1017 mov al, gr_fade_table[eax]
1019 add ecx, Tmap.DeltaUFrac
1024 dec Tmap.InnerLooper
1029 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
1030 // ZR V/ZR 1/ZR U/ZR UL VL
1032 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
1033 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
1034 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
1035 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
1037 dec Tmap.Subdivisions // decrement span count
1038 jnz SpanLoop // loop back
1041 HandleLeftoverPixels:
1043 mov esi,Tmap.pixptr // load texture pointer
1045 // edi = dest dib bits
1046 // esi = current texture dib bits
1047 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
1048 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
1050 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
1051 jz FPUReturn ; nope, pop the FPU and bail
1053 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
1055 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
1056 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
1057 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
1059 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
1060 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
1061 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
1063 dec Tmap.WidthModLength ; calc how many steps to take
1064 jz OnePixelSpan ; just one, don't do deltas'
1066 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
1069 // @todo rearrange things so we don't need these two instructions
1070 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
1071 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
1073 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
1074 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
1075 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
1076 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
1077 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
1078 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
1080 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
1082 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
1083 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
1085 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
1087 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
1088 fxch st(1) ; VR UR inv. inv. inv. dU VL
1089 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
1090 fxch st(6) ; dV UR inv. inv. inv. dU VR
1092 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
1093 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
1094 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
1096 fxch st(4) ; dU inv. inv. inv. UR VR
1097 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
1098 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
1099 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
1101 // @todo gross! these are to line up with the other loop
1102 fld st(1) ; inv. inv. inv. inv. UR VR
1103 fld st(2) ; inv. inv. inv. inv. inv. UR VR
1106 // setup delta values
1107 mov eax, Tmap.DeltaV // get v 16.16 step
1108 mov ebx, eax // copy it
1109 sar eax, 16 // get v int step
1110 shl ebx, 16 // get v frac step
1111 mov Tmap.DeltaVFrac, ebx // store it
1112 imul eax, Tmap.src_offset // calc texture step for v int step
1114 mov ebx, Tmap.DeltaU // get u 16.16 step
1115 mov ecx, ebx // copy it
1116 sar ebx, 16 // get the u int step
1117 shl ecx, 16 // get the u frac step
1118 mov Tmap.DeltaUFrac, ecx // store it
1119 add eax, ebx // calc uint + vint step
1120 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
1121 add eax, Tmap.src_offset // calc whole step + v carry
1122 mov Tmap.uv_delta[0], eax // save in v-carry slot
1127 ; setup initial coordinates
1128 mov esi, Tmap.UFixed // get u 16.16
1129 mov ebx, esi // copy it
1130 sar esi, 16 // get integer part
1131 shl ebx, 16 // get fractional part
1133 mov ecx, Tmap.VFixed // get v 16.16
1134 mov edx, ecx // copy it
1135 sar edx, 16 // get integer part
1136 shl ecx, 16 // get fractional part
1137 imul edx, Tmap.src_offset // calc texture scanline address
1138 add esi, edx // calc texture offset
1139 add esi, Tmap.pixptr // calc address
1146 // mov edx, Tmap.DeltaUFrac
1150 mov ebx, Tmap.fx_l_right
1156 mov eax, Tmap.fx_dl_dx
1165 sub eax, Tmap.pScreenBits
1170 inc Tmap.WidthModLength
1171 mov eax,Tmap.WidthModLength
1175 mov Tmap.WidthModLength, eax
1179 mov al,[edi] // preread the destination cache line
1181 // Make ESI = DV:DU in 6:10,6:10 format
1182 mov eax, Tmap.DeltaU
1184 mov esi, Tmap.DeltaV
1187 mov Tmap.DeltaUFrac, esi
1189 // Make ECX = V:U in 6:10,6:10 format
1190 mov eax, Tmap.UFixed
1192 mov ecx, Tmap.VFixed
1200 // ecx = V:U in 8.6:10.8
1201 // edx = zbuffer pointer
1203 // edi = screen data
1210 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1211 shr ax, 11 // EAX = V:U in 6.10:16.0
1212 rol eax, 5 // EAX = V:U in 0.0:6:6
1213 and eax, 03ffh // clear upper bits
1214 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1218 and eax, 0ffffh // clear upper bits
1219 mov al, gr_fade_table[eax]
1221 add ecx, Tmap.DeltaUFrac
1225 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1226 shr ax, 11 // EAX = V:U in 6.10:16.0
1227 rol eax, 5 // EAX = V:U in 0.0:6:6
1228 and eax, 03ffh // clear upper bits
1229 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1233 and eax, 0ffffh // clear upper bits
1234 mov al, gr_fade_table[eax]
1236 add ecx, Tmap.DeltaUFrac
1243 dec Tmap.WidthModLength
1251 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1252 shr ax, 11 // EAX = V:U in 6.10:16.0
1253 rol eax, 5 // EAX = V:U in 0.0:6:6
1254 and eax, 03ffh // clear upper bits
1255 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1259 and eax, 0ffffh // clear upper bits
1260 mov al, gr_fade_table[eax]
1262 add ecx, Tmap.DeltaUFrac
1268 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
1269 // xxx xxx xxx xxx xxx xxx xxx
1278 fldcw Tmap.OldFPUCW // restore the FPU