]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/tmapscantiled32x32.cpp
line fixes
[taylor/freespace2.git] / src / graphics / tmapscantiled32x32.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/TmapScanTiled32x32.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Routines for drawing tiled 32x32 textues
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:45  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:09  root
14  * Initial import.
15  *
16  * 
17  * 4     11/30/98 5:31p Dave
18  * Fixed up Fred support for software mode.
19  * 
20  * 3     11/30/98 1:07p Dave
21  * 16 bit conversion, first run.
22  * 
23  * 2     10/07/98 10:53a Dave
24  * Initial checkin.
25  * 
26  * 1     10/07/98 10:49a Dave
27  * 
28  * 6     4/23/98 9:55a John
29  * Fixed some bugs in the tiled tmapper causing bright dots to appear all
30  * over models.
31  * 
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
37  * global variable.
38  * 
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.
45  * 
46  * 3     12/04/97 10:38a John
47  * Fixed tiled texture mappers that were swapping uvs.
48  * 
49  * 2     10/14/97 9:19a John
50  * removed fdiv warnings.
51  * 
52  * 1     6/18/97 4:02p John
53  * added new code for 16x16 and 32x32 tiled tmaps.
54  *
55  * $NoKeywords: $
56  */
57
58
59 #include "3d.h"
60 #include "2d.h"
61 #include "grinternal.h"
62 #include "tmapper.h"
63 #include "tmapscanline.h"
64 #include "floating.h"
65 #include "palman.h"
66 #include "fix.h"
67
68 // Needed to keep warning 4725 to stay away.  See PsTypes.h for details why.
69 void disable_warning_4725_stub_tst32()
70 {
71 }
72
73 void tmapscan_pln8_zbuffered_tiled_32x32()
74 {
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);
78
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 );
87         }
88
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;
92
93         Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
94         Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
95
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 );
100
101 #ifdef PLAT_UNIX
102         STUB_FUNCTION;
103 #else
104         _asm {
105         
106         push    eax
107         push    ecx
108         push    edx
109         push    ebx
110         push    ebp
111         push    esi
112         push    edi
113
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
117         and             eax, ~0x300L
118         mov             Tmap.FPUCW,ax                                   // store it
119         fldcw           Tmap.FPUCW                                              // load the FPU
120
121
122         mov             ecx, Tmap.loop_count            // ecx = width
123         mov             edi, Tmap.dest_row_data // edi = dest pointer
124
125         // edi = pointer to start pixel in dest dib
126         // ecx = spanwidth
127
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
134 some_left_over:
135         mov             Tmap.Subdivisions,ecx           // store widths
136         mov             Tmap.WidthModLength,eax
137
138         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
139                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
140         fld             Tmap.l.v                                        // V/ZL 
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 
149
150         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
151         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
152
153         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
154
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
160
161         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
162
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
170
171         cmp             ecx,0                                                   // check for any full spans
172         jle      HandleLeftoverPixels
173     
174 SpanLoop:
175
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
178
179         // convert left side coords
180
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
184
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
188
189         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
190
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
195
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
198
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
202
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
205
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
213
214
215         // setup delta values
216     
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
223
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
233
234         // setup initial coordinates
235         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
236
237         mov     ebx,esi                                                 // copy it
238         sar     esi,16                                                          // get integer part
239         shl     ebx,16                                                          // get fractional part
240
241         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
242    
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
249
250         // set up affine registers
251
252         mov     eax, Tmap.fx_l
253         shr     eax, 8
254         mov     bx, ax
255
256         mov     ebp, Tmap.fx_dl_dx
257         shl     ebp, 5  //*32
258         add     Tmap.fx_l, ebp
259
260         mov     ebp, Tmap.fx_l
261         shr     ebp, 8
262         sub     bp, ax
263         shr     bp, 5
264
265         mov     dx, bp
266
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
271
272
273         // 8 pixel span code
274         // edi = dest dib bits at current pixel
275         // esi = texture pointer at current u,v
276         // eax = scratch
277         // ebx = u fraction 0.32
278         // ecx = v fraction 0.32
279         // edx = u frac step
280         // ebp = v carry scratch
281
282         mov     al,[edi]                                                                // preread the destination cache line
283
284         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
285
286         mov     eax, edi
287         sub     eax, Tmap.pScreenBits
288         mov     edx, gr_zbuffer
289         shl     eax, 2
290         add     edx, eax
291
292 // Make ESI =  DV:DU in 5:11,5:11 format
293         mov     eax, Tmap.DeltaV
294         shr     eax, 5
295         mov     esi, Tmap.DeltaU
296         shl     esi, 11
297         mov     si, ax
298         mov     Tmap.DeltaUFrac, esi
299                 
300 // Make ECX = V:U in 5:11,5:11 format
301         mov     eax, Tmap.VFixed
302         shr     eax, 5
303         mov     ecx, Tmap.UFixed
304         shl     ecx, 11
305         mov     cx, ax
306
307         mov     esi, Tmap.fx_w
308
309         // eax = tmp
310         // ebx = light
311         // ecx = V:U in 8.6:10.8
312         // edx = zbuffer pointer
313         // esi = z
314         // edi = screen data
315         // ebp = dl_dx
316
317
318 InnerInnerLoop:
319
320                 // pixel 0
321                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
322                 jle     Skip0                                                           // If pixel is covered, skip drawing
323
324                 mov     [edx+0], esi                                    // Write z
325
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
331
332                 mov     al, [eax]                       
333                 mov     ah, bh  
334                 and     eax, 0ffffh                                             // clear upper bits
335                 mov     al, gr_fade_table[eax]
336                 mov     [edi+0], al
337 Skip0:
338                 add     ecx, Tmap.DeltaUFrac
339                 add     esi, Tmap.fx_dwdx
340                 add     ebx, ebp 
341
342                 // pixel 1
343                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
344                 jle     Skip1                                                           // If pixel is covered, skip drawing
345
346                 mov     [edx+4], esi                                    // Write z
347
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
353
354                 mov     al, [eax]                       
355                 mov     ah, bh  
356                 and     eax, 0ffffh                                             // clear upper bits
357                 mov     al, gr_fade_table[eax]
358                 mov     [edi+1], al
359 Skip1:
360                 add     ecx, Tmap.DeltaUFrac
361                 add     esi, Tmap.fx_dwdx
362                 add     ebx, ebp 
363
364                 // pixel 2
365                 cmp     esi, [edx+8]                                    // Compare the Z depth of this pixel with zbuffer
366                 jle     Skip2                                                           // If pixel is covered, skip drawing
367
368                 mov     [edx+8], esi                                    // Write z
369
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
375
376                 mov     al, [eax]                       
377                 mov     ah, bh  
378                 and     eax, 0ffffh                                             // clear upper bits
379                 mov     al, gr_fade_table[eax]
380                 mov     [edi+2], al
381 Skip2:
382                 add     ecx, Tmap.DeltaUFrac
383                 add     esi, Tmap.fx_dwdx
384                 add     ebx, ebp 
385
386                 // pixel 3
387                 cmp     esi, [edx+12]                                   // Compare the Z depth of this pixel with zbuffer
388                 jle     Skip3                                                           // If pixel is covered, skip drawing
389
390                 mov     [edx+12], esi                                   // Write z
391
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
397
398                 mov     al, [eax]                       
399                 mov     ah, bh  
400                 and     eax, 0ffffh                                             // clear upper bits
401                 mov     al, gr_fade_table[eax]
402                 mov     [edi+3], al
403 Skip3:
404                 add     ecx, Tmap.DeltaUFrac
405                 add     esi, Tmap.fx_dwdx
406                 add     ebx, ebp 
407
408
409         add     edi, 4
410         add     edx, 16
411         dec     Tmap.InnerLooper
412         jnz     InnerInnerLoop
413
414         mov     Tmap.fx_w, esi
415
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
418
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
423
424     dec     Tmap.Subdivisions                   // decrement span count
425     jnz     SpanLoop                                                    // loop back
426
427
428 HandleLeftoverPixels:
429
430     mov     esi,Tmap.pixptr                             // load texture pointer
431
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
436
437     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
438     jz      FPUReturn                   ; nope, pop the FPU and bail
439
440     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
441
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
445
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
449
450     dec     Tmap.WidthModLength            ; calc how many steps to take
451     jz      OnePixelSpan                ; just one, don't do deltas'
452
453     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
454     // r -> R+1
455
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
459
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
466
467     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
468
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
471
472     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
473
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
478
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
482
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
487
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
491
492
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
500         
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
510
511
512 OnePixelSpan:
513
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
519
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
527
528
529         mov     eax, Tmap.fx_l
530         shr     eax, 8
531         mov     bx, ax
532
533 //      mov     edx, Tmap.DeltaUFrac
534
535
536         push    ebx
537         
538         mov     ebx, Tmap.fx_l_right
539         shr     ebx, 8
540         
541         sub     ebx, eax
542         mov     eax, ebx
543         
544         mov     eax, Tmap.fx_dl_dx
545         shr     eax, 8
546
547         mov     bp, ax
548
549         pop     ebx
550
551
552         mov     eax, edi
553         sub     eax, Tmap.pScreenBits
554         mov     edx, gr_zbuffer
555         shl     eax, 2
556         add     edx, eax
557
558         inc     Tmap.WidthModLength
559         mov     eax,Tmap.WidthModLength
560         shr     eax, 1
561         jz              one_more_pix
562         pushf
563         mov     Tmap.WidthModLength, eax
564
565         xor     eax, eax
566
567         mov     al,[edi]                    // preread the destination cache line
568
569 // Make ESI =  DV:DU in 6:10,6:10 format
570         mov     eax, Tmap.DeltaV
571         shr     eax, 5
572         mov     esi, Tmap.DeltaU
573         shl     esi, 11
574         mov     si, ax
575         mov     Tmap.DeltaUFrac, esi
576                 
577 // Make ECX = V:U in 6:10,6:10 format
578         mov     eax, Tmap.VFixed
579         shr     eax, 5
580         mov     ecx, Tmap.UFixed
581         shl     ecx, 11
582         mov     cx, ax
583
584         mov     esi, Tmap.fx_w
585
586         // eax = tmp
587         // ebx = light
588         // ecx = V:U in 8.6:10.8
589         // edx = zbuffer pointer
590         // esi = z
591         // edi = screen data
592         // ebp = dl_dx
593
594
595
596 NextPixel:
597                 // pixel 0
598                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
599                 jle     Skip0a                                                          // If pixel is covered, skip drawing
600
601                 mov     [edx+0], esi                                    // Write z
602
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
608
609                 mov     al, [eax]                       
610                 mov     ah, bh  
611                 and     eax, 0ffffh                                             // clear upper bits
612                 mov     al, gr_fade_table[eax]
613                 mov     [edi+0], al
614 Skip0a:
615                 add     ecx, Tmap.DeltaUFrac
616                 add     esi, Tmap.fx_dwdx
617                 add     ebx, ebp 
618
619                 // pixel 1
620                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
621                 jle     Skip1a                                                          // If pixel is covered, skip drawing
622
623                 mov     [edx+4], esi                                    // Write z
624
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
630
631                 mov     al, [eax]                       
632                 mov     ah, bh  
633                 and     eax, 0ffffh                                             // clear upper bits
634                 mov     al, gr_fade_table[eax]
635                 mov     [edi+1], al
636 Skip1a:
637                 add     ecx, Tmap.DeltaUFrac
638                 add     esi, Tmap.fx_dwdx
639                 add     ebx, ebp 
640
641
642
643         add     edi, 2
644         add     edx, 8
645         dec     Tmap.WidthModLength
646         jg              NextPixel
647
648         popf
649         jnc     FPUReturn
650
651 one_more_pix:   
652                 // pixel 0
653                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
654                 jle     Skip0b                                                          // If pixel is covered, skip drawing
655
656                 mov     [edx+0], esi                                    // Write z
657
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
663
664                 mov     al, [eax]                       
665                 mov     ah, bh  
666                 and     eax, 0ffffh                                             // clear upper bits
667                 mov     al, gr_fade_table[eax]
668                 mov     [edi+0], al
669 Skip0b:
670                 add     ecx, Tmap.DeltaUFrac
671                 add     esi, Tmap.fx_dwdx
672                 add     ebx, ebp 
673
674
675 FPUReturn:
676
677         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
678                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
679         ffree   st(0)
680         ffree   st(1)
681         ffree   st(2)
682         ffree   st(3)
683         ffree   st(4)
684         ffree   st(5)
685         ffree   st(6)
686
687         fldcw   Tmap.OldFPUCW                  // restore the FPU
688
689         pop     edi
690         pop     esi
691         pop     ebp
692         pop     ebx
693         pop     edx
694         pop     ecx
695         pop     eax
696         }
697 #endif
698 }
699
700 void tmapscan_pln8_tiled_32x32()
701 {
702         if (gr_zbuffering) {
703                 switch(gr_zbuffering_mode)      {
704                 case GR_ZBUFF_NONE:
705                         break;
706                 case GR_ZBUFF_FULL:             // both
707                         tmapscan_pln8_zbuffered_tiled_32x32();
708                         return;
709                 case GR_ZBUFF_WRITE:            // write only
710                         tmapscan_pln8_zbuffered_tiled_32x32();
711                         break;
712                 case GR_ZBUFF_READ:             // read only
713                         tmapscan_pln8_zbuffered_tiled_32x32();
714                         return;
715                 }
716         }
717
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);
721
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 );
730         }
731
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;
735
736         Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
737         Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
738
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 );
743
744 #ifdef PLAT_UNIX
745         STUB_FUNCTION;
746 #else
747         _asm {
748         
749         push    eax
750         push    ecx
751         push    edx
752         push    ebx
753         push    ebp
754         push    esi
755         push    edi
756
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
760         and             eax, ~0x300L
761         mov             Tmap.FPUCW,ax                                   // store it
762         fldcw           Tmap.FPUCW                                              // load the FPU
763
764
765         mov             ecx, Tmap.loop_count            // ecx = width
766         mov             edi, Tmap.dest_row_data // edi = dest pointer
767
768         // edi = pointer to start pixel in dest dib
769         // ecx = spanwidth
770
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
777 some_left_over:
778         mov             Tmap.Subdivisions,ecx           // store widths
779         mov             Tmap.WidthModLength,eax
780
781         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
782                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
783         fld             Tmap.l.v                                        // V/ZL 
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 
792
793         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
794         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
795
796         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
797
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
803
804         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
805
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
813
814         cmp             ecx,0                                                   // check for any full spans
815         jle      HandleLeftoverPixels
816     
817 SpanLoop:
818
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
821
822         // convert left side coords
823
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
827
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
831
832         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
833
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
838
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
841
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
845
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
848
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
856
857
858         // setup delta values
859     
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
866
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
876
877         // setup initial coordinates
878         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
879
880         mov     ebx,esi                                                 // copy it
881         sar     esi,16                                                          // get integer part
882         shl     ebx,16                                                          // get fractional part
883
884         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
885    
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
892
893         // set up affine registers
894
895         mov     eax, Tmap.fx_l
896         shr     eax, 8
897         mov     bx, ax
898
899         mov     ebp, Tmap.fx_dl_dx
900         shl     ebp, 5  //*32
901         add     Tmap.fx_l, ebp
902
903         mov     ebp, Tmap.fx_l
904         shr     ebp, 8
905         sub     bp, ax
906         shr     bp, 5
907
908         mov     dx, bp
909
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
914
915
916         // 8 pixel span code
917         // edi = dest dib bits at current pixel
918         // esi = texture pointer at current u,v
919         // eax = scratch
920         // ebx = u fraction 0.32
921         // ecx = v fraction 0.32
922         // edx = u frac step
923         // ebp = v carry scratch
924
925         mov     al,[edi]                                                                // preread the destination cache line
926
927         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
928
929         mov     eax, edi
930         sub     eax, Tmap.pScreenBits
931         mov     edx, gr_zbuffer
932         shl     eax, 2
933         add     edx, eax
934
935 // Make ESI =  DV:DU in 6:10,6:10 format
936         mov     eax, Tmap.DeltaU
937         shr     eax, 5
938         mov     esi, Tmap.DeltaV
939         shl     esi, 11
940         mov     si, ax
941         mov     Tmap.DeltaUFrac, esi
942                 
943 // Make ECX = V:U in 6:10,6:10 format
944         mov     eax, Tmap.UFixed
945         shr     eax, 5
946         mov     ecx, Tmap.VFixed
947         shl     ecx, 11
948         mov     cx, ax
949
950
951         // eax = tmp
952         // ebx = light
953         // ecx = V:U in 8.6:10.8
954         // edx = zbuffer pointer
955         // esi = z
956         // edi = screen data
957         // ebp = dl_dx
958
959
960 InnerInnerLoop:
961
962                 // pixel 0
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
968
969                 mov     al, [eax]                       
970                 mov     ah, bh  
971                 and     eax, 0ffffh                                             // clear upper bits
972                 mov     al, gr_fade_table[eax]
973                 mov     [edi+0], al
974                 add     ecx, Tmap.DeltaUFrac
975                 add     ebx, ebp 
976
977                 // pixel 1
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
983
984                 mov     al, [eax]                       
985                 mov     ah, bh  
986                 and     eax, 0ffffh                                             // clear upper bits
987                 mov     al, gr_fade_table[eax]
988                 mov     [edi+1], al
989                 add     ecx, Tmap.DeltaUFrac
990                 add     ebx, ebp 
991
992                 // pixel 2
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
998
999                 mov     al, [eax]                       
1000                 mov     ah, bh  
1001                 and     eax, 0ffffh                                             // clear upper bits
1002                 mov     al, gr_fade_table[eax]
1003                 mov     [edi+2], al
1004                 add     ecx, Tmap.DeltaUFrac
1005                 add     ebx, ebp 
1006
1007                 // pixel 3
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
1013
1014                 mov     al, [eax]                       
1015                 mov     ah, bh  
1016                 and     eax, 0ffffh                                             // clear upper bits
1017                 mov     al, gr_fade_table[eax]
1018                 mov     [edi+3], al
1019                 add     ecx, Tmap.DeltaUFrac
1020                 add     ebx, ebp 
1021
1022
1023         add     edi, 4
1024         dec     Tmap.InnerLooper
1025         jnz     InnerInnerLoop
1026
1027         mov     Tmap.fx_w, esi
1028
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
1031
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
1036
1037     dec     Tmap.Subdivisions                   // decrement span count
1038     jnz     SpanLoop                                                    // loop back
1039
1040
1041 HandleLeftoverPixels:
1042
1043     mov     esi,Tmap.pixptr                             // load texture pointer
1044
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
1049
1050     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1051     jz      FPUReturn                   ; nope, pop the FPU and bail
1052
1053     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1054
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
1058
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
1062
1063     dec     Tmap.WidthModLength            ; calc how many steps to take
1064     jz      OnePixelSpan                ; just one, don't do deltas'
1065
1066     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1067     // r -> R+1
1068
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
1072
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
1079
1080     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1081
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
1084
1085     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1086
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
1091
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
1095
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
1100
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
1104
1105
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
1113         
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
1123
1124
1125 OnePixelSpan:
1126
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
1132
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
1140
1141
1142         mov     eax, Tmap.fx_l
1143         shr     eax, 8
1144         mov     bx, ax
1145
1146 //      mov     edx, Tmap.DeltaUFrac
1147
1148         push    ebx
1149         
1150         mov     ebx, Tmap.fx_l_right
1151         shr     ebx, 8
1152         
1153         sub     ebx, eax
1154         mov     eax, ebx
1155         
1156         mov     eax, Tmap.fx_dl_dx
1157         shr     eax, 8
1158
1159         mov     bp, ax
1160
1161         pop     ebx
1162
1163
1164         mov     eax, edi
1165         sub     eax, Tmap.pScreenBits
1166         mov     edx, gr_zbuffer
1167         shl     eax, 2
1168         add     edx, eax
1169
1170         inc     Tmap.WidthModLength
1171         mov     eax,Tmap.WidthModLength
1172         shr     eax, 1
1173         jz              one_more_pix
1174         pushf
1175         mov     Tmap.WidthModLength, eax
1176
1177         xor     eax, eax
1178
1179         mov     al,[edi]                    // preread the destination cache line
1180
1181 // Make ESI =  DV:DU in 6:10,6:10 format
1182         mov     eax, Tmap.DeltaU
1183         shr     eax, 5
1184         mov     esi, Tmap.DeltaV
1185         shl     esi, 11
1186         mov     si, ax
1187         mov     Tmap.DeltaUFrac, esi
1188                 
1189 // Make ECX = V:U in 6:10,6:10 format
1190         mov     eax, Tmap.UFixed
1191         shr     eax, 5
1192         mov     ecx, Tmap.VFixed
1193         shl     ecx, 11
1194         mov     cx, ax
1195
1196         mov     esi, Tmap.fx_w
1197
1198         // eax = tmp
1199         // ebx = light
1200         // ecx = V:U in 8.6:10.8
1201         // edx = zbuffer pointer
1202         // esi = z
1203         // edi = screen data
1204         // ebp = dl_dx
1205
1206
1207
1208 NextPixel:
1209                 // pixel 0
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
1215
1216                 mov     al, [eax]                       
1217                 mov     ah, bh  
1218                 and     eax, 0ffffh                                             // clear upper bits
1219                 mov     al, gr_fade_table[eax]
1220                 mov     [edi+0], al
1221                 add     ecx, Tmap.DeltaUFrac
1222                 add     ebx, ebp 
1223
1224                 // pixel 1
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
1230
1231                 mov     al, [eax]                       
1232                 mov     ah, bh  
1233                 and     eax, 0ffffh                                             // clear upper bits
1234                 mov     al, gr_fade_table[eax]
1235                 mov     [edi+1], al
1236                 add     ecx, Tmap.DeltaUFrac
1237                 add     ebx, ebp 
1238
1239
1240
1241         add     edi, 2
1242         add     edx, 8
1243         dec     Tmap.WidthModLength
1244         jg              NextPixel
1245
1246         popf
1247         jnc     FPUReturn
1248
1249 one_more_pix:   
1250                 // pixel 0
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
1256
1257                 mov     al, [eax]                       
1258                 mov     ah, bh  
1259                 and     eax, 0ffffh                                             // clear upper bits
1260                 mov     al, gr_fade_table[eax]
1261                 mov     [edi+0], al
1262                 add     ecx, Tmap.DeltaUFrac
1263                 add     ebx, ebp 
1264
1265
1266 FPUReturn:
1267
1268         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1269                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1270         ffree   st(0)
1271         ffree   st(1)
1272         ffree   st(2)
1273         ffree   st(3)
1274         ffree   st(4)
1275         ffree   st(5)
1276         ffree   st(6)
1277
1278         fldcw   Tmap.OldFPUCW                  // restore the FPU
1279
1280         pop     edi
1281         pop     esi
1282         pop     ebp
1283         pop     ebx
1284         pop     edx
1285         pop     ecx
1286         pop     eax
1287         }
1288 #endif
1289 }
1290