2 * $Logfile: /Freespace2/code/Graphics/TmapScanTiled64x64.cpp $
7 * Routines for drawing tiled 64x64 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 * 8 4/23/98 9:55a John
26 * Fixed some bugs in the tiled tmapper causing bright dots to appear all
29 * 7 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 * 6 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 * 5 12/04/97 10:38a John
44 * Fixed tiled texture mappers that were swapping uvs.
46 * 4 10/14/97 9:19a John
47 * removed fdiv warnings.
49 * 3 6/02/97 11:45a John
50 * fixed bugs with 64x64 and 128x128 tmappers.
52 * 2 5/12/97 12:27p John
53 * Restructured Graphics Library to add support for multiple renderers.
55 * 1 4/24/97 4:42p John
56 * Initial version of the tiled texture mappers for 64 & 128 wide
65 #include "grinternal.h"
67 #include "tmapscanline.h"
72 // Needed to keep warning 4725 to stay away. See PsTypes.h for details why.
73 void disable_warning_4725_stub_tst64()
77 void tmapscan_pln8_zbuffered_tiled_64x64()
79 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
80 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
81 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
83 if ( Tmap.fx_dl_dx < 0 ) {
84 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
85 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
86 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
87 // Assert( Tmap.fx_l > 31*F1_0 );
88 // Assert( Tmap.fx_l < 66*F1_0 );
89 // Assert( Tmap.fx_dl_dx >= 0 );
90 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
93 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
94 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
95 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
97 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
98 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
100 // Assert(Tmap.fx_w < 65536 );
101 // Assert(Tmap.fx_w >= 0 );
102 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
103 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
118 // Put the FPU in low precision mode
119 fstcw Tmap.OldFPUCW // store copy of CW
120 mov ax,Tmap.OldFPUCW // get it in ax
122 mov Tmap.FPUCW,ax // store it
123 fldcw Tmap.FPUCW // load the FPU
126 mov ecx, Tmap.loop_count // ecx = width
127 mov edi, Tmap.dest_row_data // edi = dest pointer
129 // edi = pointer to start pixel in dest dib
132 mov eax,ecx // eax and ecx = width
133 shr ecx,5 // ecx = width / subdivision length
134 and eax,31 // eax = width mod subdivision length
135 jnz some_left_over // any leftover?
136 dec ecx // no, so special case last span
137 mov eax,32 // it's 8 pixels long
139 mov Tmap.Subdivisions,ecx // store widths
140 mov Tmap.WidthModLength,eax
142 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
143 // st0 st1 st2 st3 st4 st5 st6 st7
145 fld Tmap.l.u // U/ZL V/ZL
146 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
147 fld1 // 1 1/ZL U/ZL V/ZL
148 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
149 fld st // ZL ZL 1/ZL U/ZL V/ZL
150 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
151 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
152 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
154 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
155 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
157 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
159 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
160 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
161 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
162 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
163 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
165 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
167 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
168 // @todo overlap this guy
169 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
170 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
171 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
172 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
173 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
175 cmp ecx,0 // check for any full spans
176 jle HandleLeftoverPixels
180 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
181 // UR VR V/ZR 1/ZR U/ZR UL VL
183 // convert left side coords
185 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
186 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
187 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
189 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
190 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
191 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
193 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
195 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
196 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
197 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
198 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
200 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
201 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
203 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
204 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
205 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
207 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
208 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
210 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
211 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
212 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
213 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
214 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
215 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
216 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
219 // setup delta values
221 mov eax,Tmap.DeltaV // get v 16.16 step
222 mov ebx,eax // copy it
223 sar eax,16 // get v int step
224 shl ebx,16 // get v frac step
225 mov Tmap.DeltaVFrac,ebx // store it
226 imul eax,Tmap.src_offset // calculate texture step for v int step
228 mov ebx,Tmap.DeltaU // get u 16.16 step
229 mov ecx,ebx // copy it
230 sar ebx,16 // get u int step
231 shl ecx,16 // get u frac step
232 mov Tmap.DeltaUFrac,ecx // store it
233 add eax,ebx // calculate uint + vint step
234 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
235 add eax,Tmap.src_offset // calculate whole step + v carry
236 mov Tmap.uv_delta[0],eax // save in v-carry slot
238 // setup initial coordinates
239 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
241 mov ebx,esi // copy it
242 sar esi,16 // get integer part
243 shl ebx,16 // get fractional part
245 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
247 mov edx,ecx // copy it
248 sar edx,16 // get integer part
249 shl ecx,16 // get fractional part
250 imul edx,Tmap.src_offset // calc texture scanline address
251 add esi,edx // calc texture offset
252 add esi,Tmap.pixptr // calc address
254 // set up affine registers
260 mov ebp, Tmap.fx_dl_dx
271 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
272 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
273 // This divide should happen while the pixel span is drawn.
274 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
278 // edi = dest dib bits at current pixel
279 // esi = texture pointer at current u,v
281 // ebx = u fraction 0.32
282 // ecx = v fraction 0.32
284 // ebp = v carry scratch
286 mov al,[edi] // preread the destination cache line
288 mov Tmap.InnerLooper, 32/4 // Set up loop counter
291 sub eax, Tmap.pScreenBits
296 // Make ESI = DU:DV in 6:10,6:10 format
302 mov Tmap.DeltaUFrac, esi
304 // Make ECX = U:V in 6:10,6:10 format
315 // ecx = V:U in 8.6:10.8
316 // edx = zbuffer pointer
325 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
326 jle Skip0 // If pixel is covered, skip drawing
328 mov [edx+0], esi // Write z
330 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
331 shr ax, 10 // EAX = V:U in 6.10:16.0
332 rol eax, 6 // EAX = V:U in 0.0:6:6
333 and eax, 0fffh // clear upper bits
334 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
338 and eax, 0ffffh // clear upper bits
339 mov al, gr_fade_table[eax]
342 add ecx, Tmap.DeltaUFrac
343 add esi, Tmap.fx_dwdx
347 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
348 jle Skip1 // If pixel is covered, skip drawing
350 mov [edx+4], esi // Write z
352 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
353 shr ax, 10 // EAX = V:U in 6.10:16.0
354 rol eax, 6 // EAX = V:U in 0.0:6:6
355 and eax, 0fffh // clear upper bits
356 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
360 and eax, 0ffffh // clear upper bits
361 mov al, gr_fade_table[eax]
364 add ecx, Tmap.DeltaUFrac
365 add esi, Tmap.fx_dwdx
369 cmp esi, [edx+8] // Compare the Z depth of this pixel with zbuffer
370 jle Skip2 // If pixel is covered, skip drawing
372 mov [edx+8], esi // Write z
374 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
375 shr ax, 10 // EAX = V:U in 6.10:16.0
376 rol eax, 6 // EAX = V:U in 0.0:6:6
377 and eax, 0fffh // clear upper bits
378 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
382 and eax, 0ffffh // clear upper bits
383 mov al, gr_fade_table[eax]
386 add ecx, Tmap.DeltaUFrac
387 add esi, Tmap.fx_dwdx
391 cmp esi, [edx+12] // Compare the Z depth of this pixel with zbuffer
392 jle Skip3 // If pixel is covered, skip drawing
394 mov [edx+12], esi // Write z
396 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
397 shr ax, 10 // EAX = V:U in 6.10:16.0
398 rol eax, 6 // EAX = V:U in 0.0:6:6
399 and eax, 0fffh // clear upper bits
400 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
404 and eax, 0ffffh // clear upper bits
405 mov al, gr_fade_table[eax]
408 add ecx, Tmap.DeltaUFrac
409 add esi, Tmap.fx_dwdx
420 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
421 // ZR V/ZR 1/ZR U/ZR UL VL
423 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
424 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
425 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
426 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
428 dec Tmap.Subdivisions // decrement span count
429 jnz SpanLoop // loop back
432 HandleLeftoverPixels:
434 mov esi,Tmap.pixptr // load texture pointer
436 // edi = dest dib bits
437 // esi = current texture dib bits
438 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
439 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
441 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
442 jz FPUReturn ; nope, pop the FPU and bail
444 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
446 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
447 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
448 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
450 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
451 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
452 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
454 dec Tmap.WidthModLength ; calc how many steps to take
455 jz OnePixelSpan ; just one, don't do deltas'
457 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
460 // @todo rearrange things so we don't need these two instructions
461 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
462 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
464 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
465 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
466 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
467 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
468 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
469 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
471 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
473 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
474 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
476 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
478 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
479 fxch st(1) ; VR UR inv. inv. inv. dU VL
480 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
481 fxch st(6) ; dV UR inv. inv. inv. dU VR
483 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
484 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
485 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
487 fxch st(4) ; dU inv. inv. inv. UR VR
488 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
489 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
490 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
492 // @todo gross! these are to line up with the other loop
493 fld st(1) ; inv. inv. inv. inv. UR VR
494 fld st(2) ; inv. inv. inv. inv. inv. UR VR
497 // setup delta values
498 mov eax, Tmap.DeltaV // get v 16.16 step
499 mov ebx, eax // copy it
500 sar eax, 16 // get v int step
501 shl ebx, 16 // get v frac step
502 mov Tmap.DeltaVFrac, ebx // store it
503 imul eax, Tmap.src_offset // calc texture step for v int step
505 mov ebx, Tmap.DeltaU // get u 16.16 step
506 mov ecx, ebx // copy it
507 sar ebx, 16 // get the u int step
508 shl ecx, 16 // get the u frac step
509 mov Tmap.DeltaUFrac, ecx // store it
510 add eax, ebx // calc uint + vint step
511 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
512 add eax, Tmap.src_offset // calc whole step + v carry
513 mov Tmap.uv_delta[0], eax // save in v-carry slot
518 ; setup initial coordinates
519 mov esi, Tmap.UFixed // get u 16.16
520 mov ebx, esi // copy it
521 sar esi, 16 // get integer part
522 shl ebx, 16 // get fractional part
524 mov ecx, Tmap.VFixed // get v 16.16
525 mov edx, ecx // copy it
526 sar edx, 16 // get integer part
527 shl ecx, 16 // get fractional part
528 imul edx, Tmap.src_offset // calc texture scanline address
529 add esi, edx // calc texture offset
530 add esi, Tmap.pixptr // calc address
537 // mov edx, Tmap.DeltaUFrac
541 mov ebx, Tmap.fx_l_right
547 mov eax, Tmap.fx_dl_dx
555 sub eax, Tmap.pScreenBits
560 inc Tmap.WidthModLength
561 mov eax,Tmap.WidthModLength
565 mov Tmap.WidthModLength, eax
569 mov al,[edi] // preread the destination cache line
571 // Make ESI = DV:DU in 6:10,6:10 format
577 mov Tmap.DeltaUFrac, esi
579 // Make ECX = V:U in 6:10,6:10 format
590 // ecx = V:U in 8.6:10.8
591 // edx = zbuffer pointer
600 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
601 jle Skip0a // If pixel is covered, skip drawing
603 mov [edx+0], esi // Write z
605 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
606 shr ax, 10 // EAX = V:U in 6.10:16.0
607 rol eax, 6 // EAX = V:U in 0.0:6:6
608 and eax, 0fffh // clear upper bits
609 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
613 and eax, 0ffffh // clear upper bits
614 mov al, gr_fade_table[eax]
617 add ecx, Tmap.DeltaUFrac
618 add esi, Tmap.fx_dwdx
622 cmp esi, [edx+4] // Compare the Z depth of this pixel with zbuffer
623 jle Skip1a // If pixel is covered, skip drawing
625 mov [edx+4], esi // Write z
627 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
628 shr ax, 10 // EAX = V:U in 6.10:16.0
629 rol eax, 6 // EAX = V:U in 0.0:6:6
630 and eax, 0fffh // clear upper bits
631 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
635 and eax, 0ffffh // clear upper bits
636 mov al, gr_fade_table[eax]
639 add ecx, Tmap.DeltaUFrac
640 add esi, Tmap.fx_dwdx
647 dec Tmap.WidthModLength
655 cmp esi, [edx+0] // Compare the Z depth of this pixel with zbuffer
656 jle Skip0b // If pixel is covered, skip drawing
658 mov [edx+0], esi // Write z
660 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
661 shr ax, 10 // EAX = V:U in 6.10:16.0
662 rol eax, 6 // EAX = V:U in 0.0:6:6
663 and eax, 0fffh // clear upper bits
664 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
668 and eax, 0ffffh // clear upper bits
669 mov al, gr_fade_table[eax]
672 add ecx, Tmap.DeltaUFrac
673 add esi, Tmap.fx_dwdx
679 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
680 // xxx xxx xxx xxx xxx xxx xxx
689 fldcw Tmap.OldFPUCW // restore the FPU
702 void tmapscan_pln8_tiled_64x64()
705 switch(gr_zbuffering_mode) {
708 case GR_ZBUFF_FULL: // both
709 tmapscan_pln8_zbuffered_tiled_64x64();
711 case GR_ZBUFF_WRITE: // write only
712 tmapscan_pln8_zbuffered_tiled_64x64();
714 case GR_ZBUFF_READ: // read only
715 tmapscan_pln8_zbuffered_tiled_64x64();
720 Tmap.fx_l = fl2f(Tmap.l.b*32.0);
721 Tmap.fx_l_right = fl2f(Tmap.r.b*32.0);
722 Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
724 if ( Tmap.fx_dl_dx < 0 ) {
725 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
726 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
727 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
728 // Assert( Tmap.fx_l > 31*F1_0 );
729 // Assert( Tmap.fx_l < 66*F1_0 );
730 // Assert( Tmap.fx_dl_dx >= 0 );
731 // Assert( Tmap.fx_dl_dx < 31*F1_0 );
734 Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
735 Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
736 Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
738 Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
739 Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
741 // Assert(Tmap.fx_w < 65536 );
742 // Assert(Tmap.fx_w >= 0 );
743 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
744 // Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
759 // Put the FPU in low precision mode
760 fstcw Tmap.OldFPUCW // store copy of CW
761 mov ax,Tmap.OldFPUCW // get it in ax
763 mov Tmap.FPUCW,ax // store it
764 fldcw Tmap.FPUCW // load the FPU
767 mov ecx, Tmap.loop_count // ecx = width
768 mov edi, Tmap.dest_row_data // edi = dest pointer
770 // edi = pointer to start pixel in dest dib
773 mov eax,ecx // eax and ecx = width
774 shr ecx,5 // ecx = width / subdivision length
775 and eax,31 // eax = width mod subdivision length
776 jnz some_left_over // any leftover?
777 dec ecx // no, so special case last span
778 mov eax,32 // it's 8 pixels long
780 mov Tmap.Subdivisions,ecx // store widths
781 mov Tmap.WidthModLength,eax
783 // calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
784 // st0 st1 st2 st3 st4 st5 st6 st7
786 fld Tmap.l.u // U/ZL V/ZL
787 fld Tmap.l.sw // 1/ZL U/ZL V/ZL
788 fld1 // 1 1/ZL U/ZL V/ZL
789 fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
790 fld st // ZL ZL 1/ZL U/ZL V/ZL
791 fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
792 fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
793 fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
795 fstp st(5) // VL 1/ZL U/ZL V/ZL UL
796 fstp st(5) // 1/ZL U/ZL V/ZL UL VL
798 // calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
800 fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
801 fxch st(1) // U/ZL 1/ZR V/ZL UL VL
802 fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
803 fxch st(2) // V/ZL 1/ZR U/ZR UL VL
804 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
806 // calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
808 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
809 // @todo overlap this guy
810 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
811 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
812 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
813 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
814 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
816 cmp ecx,0 // check for any full spans
817 jle HandleLeftoverPixels
821 // at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
822 // UR VR V/ZR 1/ZR U/ZR UL VL
824 // convert left side coords
826 fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
827 fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
828 fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
830 fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
831 fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
832 fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
834 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
836 fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
837 fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
838 fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
839 fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
841 fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
842 fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
844 fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
845 fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
846 fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
848 // increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
849 // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
851 fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
852 fxch st(1) // 1/ZL V/ZR U/ZL UL VL
853 fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
854 fxch st(2) // U/ZL V/ZR 1/ZR UL VL
855 fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
856 fxch st(2) // 1/ZR V/ZR U/ZR UL VL
857 fxch st(1) // V/ZR 1/ZR U/ZR UL VL
860 // setup delta values
862 mov eax,Tmap.DeltaV // get v 16.16 step
863 mov ebx,eax // copy it
864 sar eax,16 // get v int step
865 shl ebx,16 // get v frac step
866 mov Tmap.DeltaVFrac,ebx // store it
867 imul eax,Tmap.src_offset // calculate texture step for v int step
869 mov ebx,Tmap.DeltaU // get u 16.16 step
870 mov ecx,ebx // copy it
871 sar ebx,16 // get u int step
872 shl ecx,16 // get u frac step
873 mov Tmap.DeltaUFrac,ecx // store it
874 add eax,ebx // calculate uint + vint step
875 mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
876 add eax,Tmap.src_offset // calculate whole step + v carry
877 mov Tmap.uv_delta[0],eax // save in v-carry slot
879 // setup initial coordinates
880 mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
882 mov ebx,esi // copy it
883 sar esi,16 // get integer part
884 shl ebx,16 // get fractional part
886 mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
888 mov edx,ecx // copy it
889 sar edx,16 // get integer part
890 shl ecx,16 // get fractional part
891 imul edx,Tmap.src_offset // calc texture scanline address
892 add esi,edx // calc texture offset
893 add esi,Tmap.pixptr // calc address
895 // set up affine registers
901 mov ebp, Tmap.fx_dl_dx
912 // calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
913 fld1 // 1 V/ZR 1/ZR U/ZR UL VL
914 // This divide should happen while the pixel span is drawn.
915 fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
919 // edi = dest dib bits at current pixel
920 // esi = texture pointer at current u,v
922 // ebx = u fraction 0.32
923 // ecx = v fraction 0.32
925 // ebp = v carry scratch
927 mov al,[edi] // preread the destination cache line
929 mov Tmap.InnerLooper, 32/4 // Set up loop counter
932 sub eax, Tmap.pScreenBits
937 // Make ESI = DV:DU in 6:10,6:10 format
943 mov Tmap.DeltaUFrac, esi
945 // Make ECX = V:U in 6:10,6:10 format
955 // ecx = V:U in 8.6:10.8
956 // edx = zbuffer pointer
965 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
966 shr ax, 10 // EAX = V:U in 6.10:16.0
967 rol eax, 6 // EAX = V:U in 0.0:6:6
968 and eax, 0fffh // clear upper bits
969 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
973 and eax, 0ffffh // clear upper bits
974 mov al, gr_fade_table[eax]
976 add ecx, Tmap.DeltaUFrac
980 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
981 shr ax, 10 // EAX = V:U in 6.10:16.0
982 rol eax, 6 // EAX = V:U in 0.0:6:6
983 and eax, 0fffh // clear upper bits
984 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
988 and eax, 0ffffh // clear upper bits
989 mov al, gr_fade_table[eax]
991 add ecx, Tmap.DeltaUFrac
995 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
996 shr ax, 10 // EAX = V:U in 6.10:16.0
997 rol eax, 6 // EAX = V:U in 0.0:6:6
998 and eax, 0fffh // clear upper bits
999 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1003 and eax, 0ffffh // clear upper bits
1004 mov al, gr_fade_table[eax]
1006 add ecx, Tmap.DeltaUFrac
1010 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1011 shr ax, 10 // EAX = V:U in 6.10:16.0
1012 rol eax, 6 // EAX = V:U in 0.0:6:6
1013 and eax, 0fffh // clear upper bits
1014 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1018 and eax, 0ffffh // clear upper bits
1019 mov al, gr_fade_table[eax]
1021 add ecx, Tmap.DeltaUFrac
1026 dec Tmap.InnerLooper
1031 // the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
1032 // ZR V/ZR 1/ZR U/ZR UL VL
1034 fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
1035 fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
1036 fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
1037 fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
1039 dec Tmap.Subdivisions // decrement span count
1040 jnz SpanLoop // loop back
1043 HandleLeftoverPixels:
1045 mov esi,Tmap.pixptr // load texture pointer
1047 // edi = dest dib bits
1048 // esi = current texture dib bits
1049 // at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
1050 // inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
1052 cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
1053 jz FPUReturn ; nope, pop the FPU and bail
1055 // convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
1057 fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
1058 fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
1059 fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
1061 fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
1062 fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
1063 fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
1065 dec Tmap.WidthModLength ; calc how many steps to take
1066 jz OnePixelSpan ; just one, don't do deltas'
1068 // calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
1071 // @todo rearrange things so we don't need these two instructions
1072 fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
1073 fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
1075 fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
1076 fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
1077 fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
1078 fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
1079 fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
1080 fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
1082 fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
1084 fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
1085 fmulp st(2),st ; UR VR inv. inv. inv. UL VL
1087 // calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
1089 fsubr st(5),st ; UR VR inv. inv. inv. dU VL
1090 fxch st(1) ; VR UR inv. inv. inv. dU VL
1091 fsubr st(6),st ; VR UR inv. inv. inv. dU dV
1092 fxch st(6) ; dV UR inv. inv. inv. dU VR
1094 fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
1095 fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
1096 fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
1098 fxch st(4) ; dU inv. inv. inv. UR VR
1099 fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
1100 fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
1101 fistp Tmap.DeltaU ; inv. inv. inv. UR VR
1103 // @todo gross! these are to line up with the other loop
1104 fld st(1) ; inv. inv. inv. inv. UR VR
1105 fld st(2) ; inv. inv. inv. inv. inv. UR VR
1108 // setup delta values
1109 mov eax, Tmap.DeltaV // get v 16.16 step
1110 mov ebx, eax // copy it
1111 sar eax, 16 // get v int step
1112 shl ebx, 16 // get v frac step
1113 mov Tmap.DeltaVFrac, ebx // store it
1114 imul eax, Tmap.src_offset // calc texture step for v int step
1116 mov ebx, Tmap.DeltaU // get u 16.16 step
1117 mov ecx, ebx // copy it
1118 sar ebx, 16 // get the u int step
1119 shl ecx, 16 // get the u frac step
1120 mov Tmap.DeltaUFrac, ecx // store it
1121 add eax, ebx // calc uint + vint step
1122 mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
1123 add eax, Tmap.src_offset // calc whole step + v carry
1124 mov Tmap.uv_delta[0], eax // save in v-carry slot
1129 ; setup initial coordinates
1130 mov esi, Tmap.UFixed // get u 16.16
1131 mov ebx, esi // copy it
1132 sar esi, 16 // get integer part
1133 shl ebx, 16 // get fractional part
1135 mov ecx, Tmap.VFixed // get v 16.16
1136 mov edx, ecx // copy it
1137 sar edx, 16 // get integer part
1138 shl ecx, 16 // get fractional part
1139 imul edx, Tmap.src_offset // calc texture scanline address
1140 add esi, edx // calc texture offset
1141 add esi, Tmap.pixptr // calc address
1148 // mov edx, Tmap.DeltaUFrac
1152 mov ebx, Tmap.fx_l_right
1158 mov eax, Tmap.fx_dl_dx
1167 sub eax, Tmap.pScreenBits
1172 inc Tmap.WidthModLength
1173 mov eax,Tmap.WidthModLength
1177 mov Tmap.WidthModLength, eax
1181 mov al,[edi] // preread the destination cache line
1183 // Make ESI = DV:DU in 6:10,6:10 format
1184 mov eax, Tmap.DeltaU
1186 mov esi, Tmap.DeltaV
1189 mov Tmap.DeltaUFrac, esi
1191 // Make ECX = V:U in 6:10,6:10 format
1192 mov eax, Tmap.UFixed
1194 mov ecx, Tmap.VFixed
1202 // ecx = V:U in 8.6:10.8
1203 // edx = zbuffer pointer
1205 // edi = screen data
1212 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1213 shr ax, 10 // EAX = V:U in 6.10:16.0
1214 rol eax, 6 // EAX = V:U in 0.0:6:6
1215 and eax, 0fffh // clear upper bits
1216 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1220 and eax, 0ffffh // clear upper bits
1221 mov al, gr_fade_table[eax]
1223 add ecx, Tmap.DeltaUFrac
1227 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1228 shr ax, 10 // EAX = V:U in 6.10:16.0
1229 rol eax, 6 // EAX = V:U in 0.0:6:6
1230 and eax, 0fffh // clear upper bits
1231 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1235 and eax, 0ffffh // clear upper bits
1236 mov al, gr_fade_table[eax]
1238 add ecx, Tmap.DeltaUFrac
1245 dec Tmap.WidthModLength
1253 mov eax, ecx // EAX = V.VF:U.UF in 6.10:6.10
1254 shr ax, 10 // EAX = V:U in 6.10:16.0
1255 rol eax, 6 // EAX = V:U in 0.0:6:6
1256 and eax, 0fffh // clear upper bits
1257 add eax, Tmap.pixptr // EAX = (V*64)+U + Pixptr
1261 and eax, 0ffffh // clear upper bits
1262 mov al, gr_fade_table[eax]
1264 add ecx, Tmap.DeltaUFrac
1270 // busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
1271 // xxx xxx xxx xxx xxx xxx xxx
1280 fldcw Tmap.OldFPUCW // restore the FPU