]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/tmapscantiled32x32.cpp
Initial revision
[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.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 4     11/30/98 5:31p Dave
15  * Fixed up Fred support for software mode.
16  * 
17  * 3     11/30/98 1:07p Dave
18  * 16 bit conversion, first run.
19  * 
20  * 2     10/07/98 10:53a Dave
21  * Initial checkin.
22  * 
23  * 1     10/07/98 10:49a Dave
24  * 
25  * 6     4/23/98 9:55a John
26  * Fixed some bugs in the tiled tmapper causing bright dots to appear all
27  * over models.
28  * 
29  * 5     3/10/98 4:19p John
30  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
31  * & Glide have popups and print screen.  Took out all >8bpp software
32  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
33  * support Fred.  Made zbuffering key off of functions rather than one
34  * global variable.
35  * 
36  * 4     1/23/98 5:08p John
37  * Took L out of vertex structure used B (blue) instead.   Took all small
38  * fireballs out of fireball types and used particles instead.  Fixed some
39  * debris explosion things.  Restructured fireball code.   Restructured
40  * some lighting code.   Made dynamic lighting on by default. Made groups
41  * of lasers only cast one light.  Made fireballs not cast light.
42  * 
43  * 3     12/04/97 10:38a John
44  * Fixed tiled texture mappers that were swapping uvs.
45  * 
46  * 2     10/14/97 9:19a John
47  * removed fdiv warnings.
48  * 
49  * 1     6/18/97 4:02p John
50  * added new code for 16x16 and 32x32 tiled tmaps.
51  *
52  * $NoKeywords: $
53  */
54
55
56 #include "3d.h"
57 #include "2d.h"
58 #include "grinternal.h"
59 #include "tmapper.h"
60 #include "tmapscanline.h"
61 #include "floating.h"
62 #include "palman.h"
63 #include "fix.h"
64
65 // Needed to keep warning 4725 to stay away.  See PsTypes.h for details why.
66 void disable_warning_4725_stub_tst32()
67 {
68 }
69
70 void tmapscan_pln8_zbuffered_tiled_32x32()
71 {
72         Tmap.fx_l = fl2f(Tmap.l.b*32.0); 
73         Tmap.fx_l_right = fl2f(Tmap.r.b*32.0); 
74         Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
75
76         if ( Tmap.fx_dl_dx < 0 )        {
77                 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
78                 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
79                 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
80 //              Assert( Tmap.fx_l > 31*F1_0 );
81 //              Assert( Tmap.fx_l < 66*F1_0 );
82 //              Assert( Tmap.fx_dl_dx >= 0 );
83 //              Assert( Tmap.fx_dl_dx < 31*F1_0 );
84         }
85
86         Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
87         Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
88         Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
89
90         Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
91         Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
92
93 //      Assert(Tmap.fx_w < 65536 );
94 //      Assert(Tmap.fx_w >= 0 );
95 //      Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
96 //      Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
97
98 #ifdef PLAT_UNIX
99         STUB_FUNCTION;
100 #else
101         _asm {
102         
103         push    eax
104         push    ecx
105         push    edx
106         push    ebx
107         push    ebp
108         push    esi
109         push    edi
110
111         // Put the FPU in low precision mode
112         fstcw           Tmap.OldFPUCW                                   // store copy of CW
113         mov             ax,Tmap.OldFPUCW                                // get it in ax
114         and             eax, ~0x300L
115         mov             Tmap.FPUCW,ax                                   // store it
116         fldcw           Tmap.FPUCW                                              // load the FPU
117
118
119         mov             ecx, Tmap.loop_count            // ecx = width
120         mov             edi, Tmap.dest_row_data // edi = dest pointer
121
122         // edi = pointer to start pixel in dest dib
123         // ecx = spanwidth
124
125         mov             eax,ecx                                                 // eax and ecx = width
126         shr             ecx,5                                                           // ecx = width / subdivision length
127         and             eax,31                                                          // eax = width mod subdivision length
128         jnz             some_left_over                                  // any leftover?
129         dec             ecx                                                             // no, so special case last span
130         mov             eax,32                                                          // it's 8 pixels long
131 some_left_over:
132         mov             Tmap.Subdivisions,ecx           // store widths
133         mov             Tmap.WidthModLength,eax
134
135         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
136                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
137         fld             Tmap.l.v                                        // V/ZL 
138         fld             Tmap.l.u                                        // U/ZL V/ZL 
139         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
140         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
141         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
142         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
143         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
144         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
145         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
146
147         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
148         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
149
150         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
151
152         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
153         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
154         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
155         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
156         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
157
158         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
159
160         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
161         // @todo overlap this guy
162         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
163         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
164         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
165         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
166         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
167
168         cmp             ecx,0                                                   // check for any full spans
169         jle      HandleLeftoverPixels
170     
171 SpanLoop:
172
173         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
174                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
175
176         // convert left side coords
177
178         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
179         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
180         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
181
182         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
183         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
184         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
185
186         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
187
188         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
189         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
190         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
191         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
192
193         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
194         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
195
196         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
197         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
198         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
199
200         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
201         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
202
203         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
204         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
205         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
206         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
207         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
208         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
209         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
210
211
212         // setup delta values
213     
214         mov     eax,Tmap.DeltaV                         // get v 16.16 step
215         mov     ebx,eax                                                 // copy it
216         sar     eax,16                                                          // get v int step
217         shl     ebx,16                                                          // get v frac step
218         mov     Tmap.DeltaVFrac,ebx                     // store it
219         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
220
221         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
222         mov     ecx,ebx                                                 // copy it
223         sar     ebx,16                                                          // get u int step
224         shl     ecx,16                                                          // get u frac step
225         mov     Tmap.DeltaUFrac,ecx                     // store it
226         add     eax,ebx                                                 // calculate uint + vint step
227         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
228         add     eax,Tmap.src_offset                     // calculate whole step + v carry
229         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
230
231         // setup initial coordinates
232         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
233
234         mov     ebx,esi                                                 // copy it
235         sar     esi,16                                                          // get integer part
236         shl     ebx,16                                                          // get fractional part
237
238         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
239    
240         mov     edx,ecx                                                 // copy it
241         sar     edx,16                                                          // get integer part
242         shl     ecx,16                                                          // get fractional part
243         imul    edx,Tmap.src_offset                     // calc texture scanline address
244         add     esi,edx                                                 // calc texture offset
245         add     esi,Tmap.pixptr                         // calc address
246
247         // set up affine registers
248
249         mov     eax, Tmap.fx_l
250         shr     eax, 8
251         mov     bx, ax
252
253         mov     ebp, Tmap.fx_dl_dx
254         shl     ebp, 5  //*32
255         add     Tmap.fx_l, ebp
256
257         mov     ebp, Tmap.fx_l
258         shr     ebp, 8
259         sub     bp, ax
260         shr     bp, 5
261
262         mov     dx, bp
263
264         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
265         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
266         // This divide should happen while the pixel span is drawn.
267         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
268
269
270         // 8 pixel span code
271         // edi = dest dib bits at current pixel
272         // esi = texture pointer at current u,v
273         // eax = scratch
274         // ebx = u fraction 0.32
275         // ecx = v fraction 0.32
276         // edx = u frac step
277         // ebp = v carry scratch
278
279         mov     al,[edi]                                                                // preread the destination cache line
280
281         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
282
283         mov     eax, edi
284         sub     eax, Tmap.pScreenBits
285         mov     edx, gr_zbuffer
286         shl     eax, 2
287         add     edx, eax
288
289 // Make ESI =  DV:DU in 5:11,5:11 format
290         mov     eax, Tmap.DeltaV
291         shr     eax, 5
292         mov     esi, Tmap.DeltaU
293         shl     esi, 11
294         mov     si, ax
295         mov     Tmap.DeltaUFrac, esi
296                 
297 // Make ECX = V:U in 5:11,5:11 format
298         mov     eax, Tmap.VFixed
299         shr     eax, 5
300         mov     ecx, Tmap.UFixed
301         shl     ecx, 11
302         mov     cx, ax
303
304         mov     esi, Tmap.fx_w
305
306         // eax = tmp
307         // ebx = light
308         // ecx = V:U in 8.6:10.8
309         // edx = zbuffer pointer
310         // esi = z
311         // edi = screen data
312         // ebp = dl_dx
313
314
315 InnerInnerLoop:
316
317                 // pixel 0
318                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
319                 jle     Skip0                                                           // If pixel is covered, skip drawing
320
321                 mov     [edx+0], esi                                    // Write z
322
323                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
324                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
325                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
326                 and     eax, 03ffh                                              // clear upper bits
327                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
328
329                 mov     al, [eax]                       
330                 mov     ah, bh  
331                 and     eax, 0ffffh                                             // clear upper bits
332                 mov     al, gr_fade_table[eax]
333                 mov     [edi+0], al
334 Skip0:
335                 add     ecx, Tmap.DeltaUFrac
336                 add     esi, Tmap.fx_dwdx
337                 add     ebx, ebp 
338
339                 // pixel 1
340                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
341                 jle     Skip1                                                           // If pixel is covered, skip drawing
342
343                 mov     [edx+4], esi                                    // Write z
344
345                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
346                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
347                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
348                 and     eax, 03ffh                                              // clear upper bits
349                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
350
351                 mov     al, [eax]                       
352                 mov     ah, bh  
353                 and     eax, 0ffffh                                             // clear upper bits
354                 mov     al, gr_fade_table[eax]
355                 mov     [edi+1], al
356 Skip1:
357                 add     ecx, Tmap.DeltaUFrac
358                 add     esi, Tmap.fx_dwdx
359                 add     ebx, ebp 
360
361                 // pixel 2
362                 cmp     esi, [edx+8]                                    // Compare the Z depth of this pixel with zbuffer
363                 jle     Skip2                                                           // If pixel is covered, skip drawing
364
365                 mov     [edx+8], esi                                    // Write z
366
367                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
368                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
369                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
370                 and     eax, 03ffh                                              // clear upper bits
371                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
372
373                 mov     al, [eax]                       
374                 mov     ah, bh  
375                 and     eax, 0ffffh                                             // clear upper bits
376                 mov     al, gr_fade_table[eax]
377                 mov     [edi+2], al
378 Skip2:
379                 add     ecx, Tmap.DeltaUFrac
380                 add     esi, Tmap.fx_dwdx
381                 add     ebx, ebp 
382
383                 // pixel 3
384                 cmp     esi, [edx+12]                                   // Compare the Z depth of this pixel with zbuffer
385                 jle     Skip3                                                           // If pixel is covered, skip drawing
386
387                 mov     [edx+12], esi                                   // Write z
388
389                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
390                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
391                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
392                 and     eax, 03ffh                                              // clear upper bits
393                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
394
395                 mov     al, [eax]                       
396                 mov     ah, bh  
397                 and     eax, 0ffffh                                             // clear upper bits
398                 mov     al, gr_fade_table[eax]
399                 mov     [edi+3], al
400 Skip3:
401                 add     ecx, Tmap.DeltaUFrac
402                 add     esi, Tmap.fx_dwdx
403                 add     ebx, ebp 
404
405
406         add     edi, 4
407         add     edx, 16
408         dec     Tmap.InnerLooper
409         jnz     InnerInnerLoop
410
411         mov     Tmap.fx_w, esi
412
413         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
414                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
415
416     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
417     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
418     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
419     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
420
421     dec     Tmap.Subdivisions                   // decrement span count
422     jnz     SpanLoop                                                    // loop back
423
424
425 HandleLeftoverPixels:
426
427     mov     esi,Tmap.pixptr                             // load texture pointer
428
429     // edi = dest dib bits
430     // esi = current texture dib bits
431     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
432     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
433
434     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
435     jz      FPUReturn                   ; nope, pop the FPU and bail
436
437     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
438
439     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
440     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
441     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
442
443     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
444     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
445     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
446
447     dec     Tmap.WidthModLength            ; calc how many steps to take
448     jz      OnePixelSpan                ; just one, don't do deltas'
449
450     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
451     // r -> R+1
452
453     // @todo rearrange things so we don't need these two instructions
454     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
455     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
456
457     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
458     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
459     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
460     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
461     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
462     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
463
464     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
465
466     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
467     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
468
469     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
470
471     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
472     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
473     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
474     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
475
476     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
477     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
478     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
479
480     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
481     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
482     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
483     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
484
485     // @todo gross!  these are to line up with the other loop
486     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
487     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
488
489
490         // setup delta values
491         mov     eax, Tmap.DeltaV        // get v 16.16 step
492         mov     ebx, eax                                                // copy it
493         sar     eax, 16                                         // get v int step
494         shl     ebx, 16                                         // get v frac step
495         mov     Tmap.DeltaVFrac, ebx    // store it
496         imul    eax, Tmap.src_offset    // calc texture step for v int step
497         
498         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
499         mov     ecx, ebx                                                // copy it
500         sar     ebx, 16                                         // get the u int step
501         shl     ecx, 16                                         // get the u frac step
502         mov     Tmap.DeltaUFrac, ecx                    // store it
503         add     eax, ebx                                                // calc uint + vint step
504         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
505         add     eax, Tmap.src_offset                            // calc whole step + v carry
506         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
507
508
509 OnePixelSpan:
510
511         ; setup initial coordinates
512         mov     esi, Tmap.UFixed                        // get u 16.16
513         mov     ebx, esi                                                // copy it
514         sar     esi, 16                                         // get integer part
515         shl     ebx, 16                                         // get fractional part
516
517         mov     ecx, Tmap.VFixed                        // get v 16.16 
518         mov     edx, ecx                                                // copy it
519         sar     edx, 16                                         // get integer part
520         shl     ecx, 16                                         // get fractional part
521         imul    edx, Tmap.src_offset            // calc texture scanline address
522         add     esi, edx                                                        // calc texture offset
523         add     esi, Tmap.pixptr                        // calc address
524
525
526         mov     eax, Tmap.fx_l
527         shr     eax, 8
528         mov     bx, ax
529
530 //      mov     edx, Tmap.DeltaUFrac
531
532
533         push    ebx
534         
535         mov     ebx, Tmap.fx_l_right
536         shr     ebx, 8
537         
538         sub     ebx, eax
539         mov     eax, ebx
540         
541         mov     eax, Tmap.fx_dl_dx
542         shr     eax, 8
543
544         mov     bp, ax
545
546         pop     ebx
547
548
549         mov     eax, edi
550         sub     eax, Tmap.pScreenBits
551         mov     edx, gr_zbuffer
552         shl     eax, 2
553         add     edx, eax
554
555         inc     Tmap.WidthModLength
556         mov     eax,Tmap.WidthModLength
557         shr     eax, 1
558         jz              one_more_pix
559         pushf
560         mov     Tmap.WidthModLength, eax
561
562         xor     eax, eax
563
564         mov     al,[edi]                    // preread the destination cache line
565
566 // Make ESI =  DV:DU in 6:10,6:10 format
567         mov     eax, Tmap.DeltaV
568         shr     eax, 5
569         mov     esi, Tmap.DeltaU
570         shl     esi, 11
571         mov     si, ax
572         mov     Tmap.DeltaUFrac, esi
573                 
574 // Make ECX = V:U in 6:10,6:10 format
575         mov     eax, Tmap.VFixed
576         shr     eax, 5
577         mov     ecx, Tmap.UFixed
578         shl     ecx, 11
579         mov     cx, ax
580
581         mov     esi, Tmap.fx_w
582
583         // eax = tmp
584         // ebx = light
585         // ecx = V:U in 8.6:10.8
586         // edx = zbuffer pointer
587         // esi = z
588         // edi = screen data
589         // ebp = dl_dx
590
591
592
593 NextPixel:
594                 // pixel 0
595                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
596                 jle     Skip0a                                                          // If pixel is covered, skip drawing
597
598                 mov     [edx+0], esi                                    // Write z
599
600                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
601                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
602                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
603                 and     eax, 03ffh                                              // clear upper bits
604                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
605
606                 mov     al, [eax]                       
607                 mov     ah, bh  
608                 and     eax, 0ffffh                                             // clear upper bits
609                 mov     al, gr_fade_table[eax]
610                 mov     [edi+0], al
611 Skip0a:
612                 add     ecx, Tmap.DeltaUFrac
613                 add     esi, Tmap.fx_dwdx
614                 add     ebx, ebp 
615
616                 // pixel 1
617                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
618                 jle     Skip1a                                                          // If pixel is covered, skip drawing
619
620                 mov     [edx+4], esi                                    // Write z
621
622                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
623                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
624                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
625                 and     eax, 03ffh                                              // clear upper bits
626                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
627
628                 mov     al, [eax]                       
629                 mov     ah, bh  
630                 and     eax, 0ffffh                                             // clear upper bits
631                 mov     al, gr_fade_table[eax]
632                 mov     [edi+1], al
633 Skip1a:
634                 add     ecx, Tmap.DeltaUFrac
635                 add     esi, Tmap.fx_dwdx
636                 add     ebx, ebp 
637
638
639
640         add     edi, 2
641         add     edx, 8
642         dec     Tmap.WidthModLength
643         jg              NextPixel
644
645         popf
646         jnc     FPUReturn
647
648 one_more_pix:   
649                 // pixel 0
650                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
651                 jle     Skip0b                                                          // If pixel is covered, skip drawing
652
653                 mov     [edx+0], esi                                    // Write z
654
655                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
656                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
657                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
658                 and     eax, 03ffh                                              // clear upper bits
659                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
660
661                 mov     al, [eax]                       
662                 mov     ah, bh  
663                 and     eax, 0ffffh                                             // clear upper bits
664                 mov     al, gr_fade_table[eax]
665                 mov     [edi+0], al
666 Skip0b:
667                 add     ecx, Tmap.DeltaUFrac
668                 add     esi, Tmap.fx_dwdx
669                 add     ebx, ebp 
670
671
672 FPUReturn:
673
674         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
675                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
676         ffree   st(0)
677         ffree   st(1)
678         ffree   st(2)
679         ffree   st(3)
680         ffree   st(4)
681         ffree   st(5)
682         ffree   st(6)
683
684         fldcw   Tmap.OldFPUCW                  // restore the FPU
685
686         pop     edi
687         pop     esi
688         pop     ebp
689         pop     ebx
690         pop     edx
691         pop     ecx
692         pop     eax
693         }
694 #endif
695 }
696
697 void tmapscan_pln8_tiled_32x32()
698 {
699         if (gr_zbuffering) {
700                 switch(gr_zbuffering_mode)      {
701                 case GR_ZBUFF_NONE:
702                         break;
703                 case GR_ZBUFF_FULL:             // both
704                         tmapscan_pln8_zbuffered_tiled_32x32();
705                         return;
706                 case GR_ZBUFF_WRITE:            // write only
707                         tmapscan_pln8_zbuffered_tiled_32x32();
708                         break;
709                 case GR_ZBUFF_READ:             // read only
710                         tmapscan_pln8_zbuffered_tiled_32x32();
711                         return;
712                 }
713         }
714
715         Tmap.fx_l = fl2f(Tmap.l.b*32.0); 
716         Tmap.fx_l_right = fl2f(Tmap.r.b*32.0); 
717         Tmap.fx_dl_dx = fl2f(Tmap.deltas.b*32.0);
718
719         if ( Tmap.fx_dl_dx < 0 )        {
720                 Tmap.fx_dl_dx = -Tmap.fx_dl_dx;
721                 Tmap.fx_l = (67*F1_0)-Tmap.fx_l;
722                 Tmap.fx_l_right = (67*F1_0)-Tmap.fx_l_right;
723 //              Assert( Tmap.fx_l > 31*F1_0 );
724 //              Assert( Tmap.fx_l < 66*F1_0 );
725 //              Assert( Tmap.fx_dl_dx >= 0 );
726 //              Assert( Tmap.fx_dl_dx < 31*F1_0 );
727         }
728
729         Tmap.fl_dudx_wide = Tmap.deltas.u*32.0f;
730         Tmap.fl_dvdx_wide = Tmap.deltas.v*32.0f;
731         Tmap.fl_dwdx_wide = Tmap.deltas.sw*32.0f;
732
733         Tmap.fx_w = fl2i(Tmap.l.sw * GR_Z_RANGE)+gr_zoffset;
734         Tmap.fx_dwdx = fl2i(Tmap.deltas.sw * GR_Z_RANGE);
735
736 //      Assert(Tmap.fx_w < 65536 );
737 //      Assert(Tmap.fx_w >= 0 );
738 //      Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count < 65536 );
739 //      Assert(Tmap.fx_w+Tmap.fx_dwdx*Tmap.loop_count >= 0 );
740
741 #ifdef PLAT_UNIX
742         STUB_FUNCTION;
743 #else
744         _asm {
745         
746         push    eax
747         push    ecx
748         push    edx
749         push    ebx
750         push    ebp
751         push    esi
752         push    edi
753
754         // Put the FPU in low precision mode
755         fstcw           Tmap.OldFPUCW                                   // store copy of CW
756         mov             ax,Tmap.OldFPUCW                                // get it in ax
757         and             eax, ~0x300L
758         mov             Tmap.FPUCW,ax                                   // store it
759         fldcw           Tmap.FPUCW                                              // load the FPU
760
761
762         mov             ecx, Tmap.loop_count            // ecx = width
763         mov             edi, Tmap.dest_row_data // edi = dest pointer
764
765         // edi = pointer to start pixel in dest dib
766         // ecx = spanwidth
767
768         mov             eax,ecx                                                 // eax and ecx = width
769         shr             ecx,5                                                           // ecx = width / subdivision length
770         and             eax,31                                                          // eax = width mod subdivision length
771         jnz             some_left_over                                  // any leftover?
772         dec             ecx                                                             // no, so special case last span
773         mov             eax,32                                                          // it's 8 pixels long
774 some_left_over:
775         mov             Tmap.Subdivisions,ecx           // store widths
776         mov             Tmap.WidthModLength,eax
777
778         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
779                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
780         fld             Tmap.l.v                                        // V/ZL 
781         fld             Tmap.l.u                                        // U/ZL V/ZL 
782         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
783         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
784         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
785         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
786         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
787         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
788         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
789
790         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
791         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
792
793         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
794
795         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
796         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
797         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
798         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
799         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
800
801         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
802
803         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
804         // @todo overlap this guy
805         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
806         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
807         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
808         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
809         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
810
811         cmp             ecx,0                                                   // check for any full spans
812         jle      HandleLeftoverPixels
813     
814 SpanLoop:
815
816         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
817                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
818
819         // convert left side coords
820
821         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
822         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
823         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
824
825         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
826         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
827         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
828
829         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
830
831         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
832         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
833         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
834         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
835
836         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
837         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
838
839         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
840         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
841         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
842
843         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
844         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
845
846         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
847         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
848         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
849         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
850         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
851         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
852         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
853
854
855         // setup delta values
856     
857         mov     eax,Tmap.DeltaV                         // get v 16.16 step
858         mov     ebx,eax                                                 // copy it
859         sar     eax,16                                                          // get v int step
860         shl     ebx,16                                                          // get v frac step
861         mov     Tmap.DeltaVFrac,ebx                     // store it
862         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
863
864         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
865         mov     ecx,ebx                                                 // copy it
866         sar     ebx,16                                                          // get u int step
867         shl     ecx,16                                                          // get u frac step
868         mov     Tmap.DeltaUFrac,ecx                     // store it
869         add     eax,ebx                                                 // calculate uint + vint step
870         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
871         add     eax,Tmap.src_offset                     // calculate whole step + v carry
872         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
873
874         // setup initial coordinates
875         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
876
877         mov     ebx,esi                                                 // copy it
878         sar     esi,16                                                          // get integer part
879         shl     ebx,16                                                          // get fractional part
880
881         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
882    
883         mov     edx,ecx                                                 // copy it
884         sar     edx,16                                                          // get integer part
885         shl     ecx,16                                                          // get fractional part
886         imul    edx,Tmap.src_offset                     // calc texture scanline address
887         add     esi,edx                                                 // calc texture offset
888         add     esi,Tmap.pixptr                         // calc address
889
890         // set up affine registers
891
892         mov     eax, Tmap.fx_l
893         shr     eax, 8
894         mov     bx, ax
895
896         mov     ebp, Tmap.fx_dl_dx
897         shl     ebp, 5  //*32
898         add     Tmap.fx_l, ebp
899
900         mov     ebp, Tmap.fx_l
901         shr     ebp, 8
902         sub     bp, ax
903         shr     bp, 5
904
905         mov     dx, bp
906
907         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
908         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
909         // This divide should happen while the pixel span is drawn.
910         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
911
912
913         // 8 pixel span code
914         // edi = dest dib bits at current pixel
915         // esi = texture pointer at current u,v
916         // eax = scratch
917         // ebx = u fraction 0.32
918         // ecx = v fraction 0.32
919         // edx = u frac step
920         // ebp = v carry scratch
921
922         mov     al,[edi]                                                                // preread the destination cache line
923
924         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
925
926         mov     eax, edi
927         sub     eax, Tmap.pScreenBits
928         mov     edx, gr_zbuffer
929         shl     eax, 2
930         add     edx, eax
931
932 // Make ESI =  DV:DU in 6:10,6:10 format
933         mov     eax, Tmap.DeltaU
934         shr     eax, 5
935         mov     esi, Tmap.DeltaV
936         shl     esi, 11
937         mov     si, ax
938         mov     Tmap.DeltaUFrac, esi
939                 
940 // Make ECX = V:U in 6:10,6:10 format
941         mov     eax, Tmap.UFixed
942         shr     eax, 5
943         mov     ecx, Tmap.VFixed
944         shl     ecx, 11
945         mov     cx, ax
946
947
948         // eax = tmp
949         // ebx = light
950         // ecx = V:U in 8.6:10.8
951         // edx = zbuffer pointer
952         // esi = z
953         // edi = screen data
954         // ebp = dl_dx
955
956
957 InnerInnerLoop:
958
959                 // pixel 0
960                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
961                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
962                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
963                 and     eax, 03ffh                                              // clear upper bits
964                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
965
966                 mov     al, [eax]                       
967                 mov     ah, bh  
968                 and     eax, 0ffffh                                             // clear upper bits
969                 mov     al, gr_fade_table[eax]
970                 mov     [edi+0], al
971                 add     ecx, Tmap.DeltaUFrac
972                 add     ebx, ebp 
973
974                 // pixel 1
975                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
976                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
977                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
978                 and     eax, 03ffh                                              // clear upper bits
979                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
980
981                 mov     al, [eax]                       
982                 mov     ah, bh  
983                 and     eax, 0ffffh                                             // clear upper bits
984                 mov     al, gr_fade_table[eax]
985                 mov     [edi+1], al
986                 add     ecx, Tmap.DeltaUFrac
987                 add     ebx, ebp 
988
989                 // pixel 2
990                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
991                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
992                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
993                 and     eax, 03ffh                                              // clear upper bits
994                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
995
996                 mov     al, [eax]                       
997                 mov     ah, bh  
998                 and     eax, 0ffffh                                             // clear upper bits
999                 mov     al, gr_fade_table[eax]
1000                 mov     [edi+2], al
1001                 add     ecx, Tmap.DeltaUFrac
1002                 add     ebx, ebp 
1003
1004                 // pixel 3
1005                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1006                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
1007                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
1008                 and     eax, 03ffh                                              // clear upper bits
1009                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1010
1011                 mov     al, [eax]                       
1012                 mov     ah, bh  
1013                 and     eax, 0ffffh                                             // clear upper bits
1014                 mov     al, gr_fade_table[eax]
1015                 mov     [edi+3], al
1016                 add     ecx, Tmap.DeltaUFrac
1017                 add     ebx, ebp 
1018
1019
1020         add     edi, 4
1021         dec     Tmap.InnerLooper
1022         jnz     InnerInnerLoop
1023
1024         mov     Tmap.fx_w, esi
1025
1026         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
1027                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
1028
1029     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1030     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1031     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1032     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1033
1034     dec     Tmap.Subdivisions                   // decrement span count
1035     jnz     SpanLoop                                                    // loop back
1036
1037
1038 HandleLeftoverPixels:
1039
1040     mov     esi,Tmap.pixptr                             // load texture pointer
1041
1042     // edi = dest dib bits
1043     // esi = current texture dib bits
1044     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
1045     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
1046
1047     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1048     jz      FPUReturn                   ; nope, pop the FPU and bail
1049
1050     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1051
1052     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
1053     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
1054     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
1055
1056     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
1057     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
1058     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
1059
1060     dec     Tmap.WidthModLength            ; calc how many steps to take
1061     jz      OnePixelSpan                ; just one, don't do deltas'
1062
1063     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1064     // r -> R+1
1065
1066     // @todo rearrange things so we don't need these two instructions
1067     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
1068     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
1069
1070     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
1071     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
1072     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
1073     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
1074     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
1075     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
1076
1077     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1078
1079     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
1080     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
1081
1082     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1083
1084     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
1085     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
1086     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
1087     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
1088
1089     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
1090     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
1091     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
1092
1093     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
1094     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
1095     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
1096     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
1097
1098     // @todo gross!  these are to line up with the other loop
1099     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
1100     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
1101
1102
1103         // setup delta values
1104         mov     eax, Tmap.DeltaV        // get v 16.16 step
1105         mov     ebx, eax                                                // copy it
1106         sar     eax, 16                                         // get v int step
1107         shl     ebx, 16                                         // get v frac step
1108         mov     Tmap.DeltaVFrac, ebx    // store it
1109         imul    eax, Tmap.src_offset    // calc texture step for v int step
1110         
1111         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
1112         mov     ecx, ebx                                                // copy it
1113         sar     ebx, 16                                         // get the u int step
1114         shl     ecx, 16                                         // get the u frac step
1115         mov     Tmap.DeltaUFrac, ecx                    // store it
1116         add     eax, ebx                                                // calc uint + vint step
1117         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1118         add     eax, Tmap.src_offset                            // calc whole step + v carry
1119         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1120
1121
1122 OnePixelSpan:
1123
1124         ; setup initial coordinates
1125         mov     esi, Tmap.UFixed                        // get u 16.16
1126         mov     ebx, esi                                                // copy it
1127         sar     esi, 16                                         // get integer part
1128         shl     ebx, 16                                         // get fractional part
1129
1130         mov     ecx, Tmap.VFixed                        // get v 16.16 
1131         mov     edx, ecx                                                // copy it
1132         sar     edx, 16                                         // get integer part
1133         shl     ecx, 16                                         // get fractional part
1134         imul    edx, Tmap.src_offset            // calc texture scanline address
1135         add     esi, edx                                                        // calc texture offset
1136         add     esi, Tmap.pixptr                        // calc address
1137
1138
1139         mov     eax, Tmap.fx_l
1140         shr     eax, 8
1141         mov     bx, ax
1142
1143 //      mov     edx, Tmap.DeltaUFrac
1144
1145         push    ebx
1146         
1147         mov     ebx, Tmap.fx_l_right
1148         shr     ebx, 8
1149         
1150         sub     ebx, eax
1151         mov     eax, ebx
1152         
1153         mov     eax, Tmap.fx_dl_dx
1154         shr     eax, 8
1155
1156         mov     bp, ax
1157
1158         pop     ebx
1159
1160
1161         mov     eax, edi
1162         sub     eax, Tmap.pScreenBits
1163         mov     edx, gr_zbuffer
1164         shl     eax, 2
1165         add     edx, eax
1166
1167         inc     Tmap.WidthModLength
1168         mov     eax,Tmap.WidthModLength
1169         shr     eax, 1
1170         jz              one_more_pix
1171         pushf
1172         mov     Tmap.WidthModLength, eax
1173
1174         xor     eax, eax
1175
1176         mov     al,[edi]                    // preread the destination cache line
1177
1178 // Make ESI =  DV:DU in 6:10,6:10 format
1179         mov     eax, Tmap.DeltaU
1180         shr     eax, 5
1181         mov     esi, Tmap.DeltaV
1182         shl     esi, 11
1183         mov     si, ax
1184         mov     Tmap.DeltaUFrac, esi
1185                 
1186 // Make ECX = V:U in 6:10,6:10 format
1187         mov     eax, Tmap.UFixed
1188         shr     eax, 5
1189         mov     ecx, Tmap.VFixed
1190         shl     ecx, 11
1191         mov     cx, ax
1192
1193         mov     esi, Tmap.fx_w
1194
1195         // eax = tmp
1196         // ebx = light
1197         // ecx = V:U in 8.6:10.8
1198         // edx = zbuffer pointer
1199         // esi = z
1200         // edi = screen data
1201         // ebp = dl_dx
1202
1203
1204
1205 NextPixel:
1206                 // pixel 0
1207                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1208                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
1209                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
1210                 and     eax, 03ffh                                              // clear upper bits
1211                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1212
1213                 mov     al, [eax]                       
1214                 mov     ah, bh  
1215                 and     eax, 0ffffh                                             // clear upper bits
1216                 mov     al, gr_fade_table[eax]
1217                 mov     [edi+0], al
1218                 add     ecx, Tmap.DeltaUFrac
1219                 add     ebx, ebp 
1220
1221                 // pixel 1
1222                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1223                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
1224                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
1225                 and     eax, 03ffh                                              // clear upper bits
1226                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1227
1228                 mov     al, [eax]                       
1229                 mov     ah, bh  
1230                 and     eax, 0ffffh                                             // clear upper bits
1231                 mov     al, gr_fade_table[eax]
1232                 mov     [edi+1], al
1233                 add     ecx, Tmap.DeltaUFrac
1234                 add     ebx, ebp 
1235
1236
1237
1238         add     edi, 2
1239         add     edx, 8
1240         dec     Tmap.WidthModLength
1241         jg              NextPixel
1242
1243         popf
1244         jnc     FPUReturn
1245
1246 one_more_pix:   
1247                 // pixel 0
1248                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1249                 shr     ax, 11                                                          // EAX = V:U in 6.10:16.0
1250                 rol     eax, 5                                                  // EAX = V:U in 0.0:6:6
1251                 and     eax, 03ffh                                              // clear upper bits
1252                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1253
1254                 mov     al, [eax]                       
1255                 mov     ah, bh  
1256                 and     eax, 0ffffh                                             // clear upper bits
1257                 mov     al, gr_fade_table[eax]
1258                 mov     [edi+0], al
1259                 add     ecx, Tmap.DeltaUFrac
1260                 add     ebx, ebp 
1261
1262
1263 FPUReturn:
1264
1265         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1266                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1267         ffree   st(0)
1268         ffree   st(1)
1269         ffree   st(2)
1270         ffree   st(3)
1271         ffree   st(4)
1272         ffree   st(5)
1273         ffree   st(6)
1274
1275         fldcw   Tmap.OldFPUCW                  // restore the FPU
1276
1277         pop     edi
1278         pop     esi
1279         pop     ebp
1280         pop     ebx
1281         pop     edx
1282         pop     ecx
1283         pop     eax
1284         }
1285 #endif
1286 }