]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/tmapscantiled16x16.cpp
Initial revision
[taylor/freespace2.git] / src / graphics / tmapscantiled16x16.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/TmapScanTiled16x16.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Routines for drawing tiled 16x16 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_tst16()
67 {
68 }
69
70 void tmapscan_pln8_zbuffered_tiled_16x16()
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     edx, gr_zbuffer
284
285         mov     eax, edi
286         sub     eax, Tmap.pScreenBits
287         shl     eax, 2
288         add     edx, eax
289
290 // Make ESI =  DV:DU in 5:11,5:11 format
291         mov     eax, Tmap.DeltaV
292         shr     eax, 4
293         mov     esi, Tmap.DeltaU
294         shl     esi, 12
295         mov     si, ax
296         mov     Tmap.DeltaUFrac, esi
297                 
298 // Make ECX = V:U in 5:11,5:11 format
299         mov     eax, Tmap.VFixed
300         shr     eax, 4
301         mov     ecx, Tmap.UFixed
302         shl     ecx, 12
303         mov     cx, ax
304
305         mov     esi, Tmap.fx_w
306
307         // eax = tmp
308         // ebx = light
309         // ecx = V:U in 8.6:10.8
310         // edx = zbuffer pointer
311         // esi = z
312         // edi = screen data
313         // ebp = dl_dx
314
315
316 InnerInnerLoop:
317
318                 // pixel 0
319                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
320                 jle     Skip0                                                           // If pixel is covered, skip drawing
321
322                 mov     [edx+0], esi                                    // Write z
323
324                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
325                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
326                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
327                 and     eax, 0ffh                                               // clear upper bits
328                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
329
330                 mov     al, [eax]                       
331                 mov     ah, bh  
332                 and     eax, 0ffffh                                             // clear upper bits
333                 mov     al, gr_fade_table[eax]
334                 mov     [edi+0], al
335 Skip0:
336                 add     ecx, Tmap.DeltaUFrac
337                 add     esi, Tmap.fx_dwdx
338                 add     ebx, ebp 
339
340                 // pixel 1
341                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
342                 jle     Skip1                                                           // If pixel is covered, skip drawing
343
344                 mov     [edx+4], esi                                    // Write z
345
346                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
347                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
348                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
349                 and     eax, 0ffh                                               // clear upper bits
350                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
351
352                 mov     al, [eax]                       
353                 mov     ah, bh  
354                 and     eax, 0ffffh                                             // clear upper bits
355                 mov     al, gr_fade_table[eax]
356                 mov     [edi+1], al
357 Skip1:
358                 add     ecx, Tmap.DeltaUFrac
359                 add     esi, Tmap.fx_dwdx
360                 add     ebx, ebp 
361
362                 // pixel 2
363                 cmp     esi, [edx+8]                                    // Compare the Z depth of this pixel with zbuffer
364                 jle     Skip2                                                           // If pixel is covered, skip drawing
365
366                 mov     [edx+8], esi                                    // Write z
367
368                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
369                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
370                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
371                 and     eax, 0ffh                                               // clear upper bits
372                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
373
374                 mov     al, [eax]                       
375                 mov     ah, bh  
376                 and     eax, 0ffffh                                             // clear upper bits
377                 mov     al, gr_fade_table[eax]
378                 mov     [edi+2], al
379 Skip2:
380                 add     ecx, Tmap.DeltaUFrac
381                 add     esi, Tmap.fx_dwdx
382                 add     ebx, ebp 
383
384                 // pixel 3
385                 cmp     esi, [edx+12]                                   // Compare the Z depth of this pixel with zbuffer
386                 jle     Skip3                                                           // If pixel is covered, skip drawing
387
388                 mov     [edx+12], esi                                   // Write z
389
390                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
391                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
392                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
393                 and     eax, 0ffh                                               // clear upper bits
394                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
395
396                 mov     al, [eax]                       
397                 mov     ah, bh  
398                 and     eax, 0ffffh                                             // clear upper bits
399                 mov     al, gr_fade_table[eax]
400                 mov     [edi+3], al
401 Skip3:
402                 add     ecx, Tmap.DeltaUFrac
403                 add     esi, Tmap.fx_dwdx
404                 add     ebx, ebp 
405
406
407         add     edi, 4
408         add     edx, 16
409         dec     Tmap.InnerLooper
410         jnz     InnerInnerLoop
411
412         mov     Tmap.fx_w, esi
413
414         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
415                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
416
417     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
418     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
419     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
420     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
421
422     dec     Tmap.Subdivisions                   // decrement span count
423     jnz     SpanLoop                                                    // loop back
424
425
426 HandleLeftoverPixels:
427
428     mov     esi,Tmap.pixptr                             // load texture pointer
429
430     // edi = dest dib bits
431     // esi = current texture dib bits
432     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
433     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
434
435     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
436     jz      FPUReturn                   ; nope, pop the FPU and bail
437
438     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
439
440     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
441     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
442     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
443
444     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
445     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
446     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
447
448     dec     Tmap.WidthModLength            ; calc how many steps to take
449     jz      OnePixelSpan                ; just one, don't do deltas'
450
451     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
452     // r -> R+1
453
454     // @todo rearrange things so we don't need these two instructions
455     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
456     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
457
458     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
459     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
460     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
461     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
462     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
463     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
464
465     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
466
467     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
468     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
469
470     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
471
472     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
473     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
474     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
475     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
476
477     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
478     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
479     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
480
481     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
482     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
483     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
484     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
485
486     // @todo gross!  these are to line up with the other loop
487     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
488     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
489
490
491         // setup delta values
492         mov     eax, Tmap.DeltaV        // get v 16.16 step
493         mov     ebx, eax                                                // copy it
494         sar     eax, 16                                         // get v int step
495         shl     ebx, 16                                         // get v frac step
496         mov     Tmap.DeltaVFrac, ebx    // store it
497         imul    eax, Tmap.src_offset    // calc texture step for v int step
498         
499         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
500         mov     ecx, ebx                                                // copy it
501         sar     ebx, 16                                         // get the u int step
502         shl     ecx, 16                                         // get the u frac step
503         mov     Tmap.DeltaUFrac, ecx                    // store it
504         add     eax, ebx                                                // calc uint + vint step
505         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
506         add     eax, Tmap.src_offset                            // calc whole step + v carry
507         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
508
509
510 OnePixelSpan:
511
512         ; setup initial coordinates
513         mov     esi, Tmap.UFixed                        // get u 16.16
514         mov     ebx, esi                                                // copy it
515         sar     esi, 16                                         // get integer part
516         shl     ebx, 16                                         // get fractional part
517
518         mov     ecx, Tmap.VFixed                        // get v 16.16 
519         mov     edx, ecx                                                // copy it
520         sar     edx, 16                                         // get integer part
521         shl     ecx, 16                                         // get fractional part
522         imul    edx, Tmap.src_offset            // calc texture scanline address
523         add     esi, edx                                                        // calc texture offset
524         add     esi, Tmap.pixptr                        // calc address
525
526
527         mov     eax, Tmap.fx_l
528         shr     eax, 8
529         mov     bx, ax
530
531 //      mov     edx, Tmap.DeltaUFrac
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, 4
569         mov     esi, Tmap.DeltaU
570         shl     esi, 12
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, 4
577         mov     ecx, Tmap.UFixed
578         shl     ecx, 12
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, 12                                                          // EAX = V:U in 6.10:16.0
602                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
603                 and     eax, 0ffh                                               // 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, 12                                                          // EAX = V:U in 6.10:16.0
624                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
625                 and     eax, 0ffh                                               // 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, 12                                                          // EAX = V:U in 6.10:16.0
657                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
658                 and     eax, 0ffh                                               // 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_16x16()
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_16x16();
705                         return;
706                 case GR_ZBUFF_WRITE:            // write only
707                         tmapscan_pln8_zbuffered_tiled_16x16();
708                         break;
709                 case GR_ZBUFF_READ:             // read only
710                         tmapscan_pln8_zbuffered_tiled_16x16();
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     edx, gr_zbuffer
927
928         mov     eax, edi
929         sub     eax, Tmap.pScreenBits
930         shl     eax, 2
931         add     edx, eax
932
933 // Make ESI =  DV:DU in 6:10,6:10 format
934         mov     eax, Tmap.DeltaV
935         shr     eax, 4
936         mov     esi, Tmap.DeltaU
937         shl     esi, 12
938         mov     si, ax
939         mov     Tmap.DeltaUFrac, esi
940                 
941 // Make ECX = V:U in 6:10,6:10 format
942         mov     eax, Tmap.VFixed
943         shr     eax, 4
944         mov     ecx, Tmap.UFixed
945         shl     ecx, 12
946         mov     cx, ax
947
948
949         // eax = tmp
950         // ebx = light
951         // ecx = V:U in 8.6:10.8
952         // edx = zbuffer pointer
953         // esi = z
954         // edi = screen data
955         // ebp = dl_dx
956
957
958 InnerInnerLoop:
959
960                 // pixel 0
961                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
962                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
963                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
964                 and     eax, 0ffh                                               // clear upper bits
965                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
966
967                 mov     al, [eax]                       
968                 mov     ah, bh  
969                 and     eax, 0ffffh                                             // clear upper bits
970                 mov     al, gr_fade_table[eax]
971                 mov     [edi+0], al
972                 add     ecx, Tmap.DeltaUFrac
973                 add     ebx, ebp 
974
975                 // pixel 1
976                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
977                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
978                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
979                 and     eax, 0ffh                                               // clear upper bits
980                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
981
982                 mov     al, [eax]                       
983                 mov     ah, bh  
984                 and     eax, 0ffffh                                             // clear upper bits
985                 mov     al, gr_fade_table[eax]
986                 mov     [edi+1], al
987                 add     ecx, Tmap.DeltaUFrac
988                 add     ebx, ebp 
989
990                 // pixel 2
991                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
992                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
993                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
994                 and     eax, 0ffh                                               // clear upper bits
995                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
996
997                 mov     al, [eax]                       
998                 mov     ah, bh  
999                 and     eax, 0ffffh                                             // clear upper bits
1000                 mov     al, gr_fade_table[eax]
1001                 mov     [edi+2], al
1002                 add     ecx, Tmap.DeltaUFrac
1003                 add     ebx, ebp 
1004
1005                 // pixel 3
1006                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1007                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
1008                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
1009                 and     eax, 0ffh                                               // clear upper bits
1010                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1011
1012                 mov     al, [eax]                       
1013                 mov     ah, bh  
1014                 and     eax, 0ffffh                                             // clear upper bits
1015                 mov     al, gr_fade_table[eax]
1016                 mov     [edi+3], al
1017                 add     ecx, Tmap.DeltaUFrac
1018                 add     ebx, ebp 
1019
1020
1021         add     edi, 4
1022         dec     Tmap.InnerLooper
1023         jnz     InnerInnerLoop
1024
1025         mov     Tmap.fx_w, esi
1026
1027         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
1028                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
1029
1030     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1031     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1032     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1033     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1034
1035     dec     Tmap.Subdivisions                   // decrement span count
1036     jnz     SpanLoop                                                    // loop back
1037
1038
1039 HandleLeftoverPixels:
1040
1041     mov     esi,Tmap.pixptr                             // load texture pointer
1042
1043     // edi = dest dib bits
1044     // esi = current texture dib bits
1045     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
1046     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
1047
1048     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1049     jz      FPUReturn                   ; nope, pop the FPU and bail
1050
1051     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1052
1053     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
1054     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
1055     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
1056
1057     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
1058     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
1059     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
1060
1061     dec     Tmap.WidthModLength            ; calc how many steps to take
1062     jz      OnePixelSpan                ; just one, don't do deltas'
1063
1064     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1065     // r -> R+1
1066
1067     // @todo rearrange things so we don't need these two instructions
1068     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
1069     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
1070
1071     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
1072     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
1073     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
1074     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
1075     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
1076     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
1077
1078     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1079
1080     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
1081     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
1082
1083     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1084
1085     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
1086     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
1087     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
1088     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
1089
1090     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
1091     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
1092     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
1093
1094     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
1095     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
1096     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
1097     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
1098
1099     // @todo gross!  these are to line up with the other loop
1100     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
1101     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
1102
1103
1104         // setup delta values
1105         mov     eax, Tmap.DeltaV        // get v 16.16 step
1106         mov     ebx, eax                                                // copy it
1107         sar     eax, 16                                         // get v int step
1108         shl     ebx, 16                                         // get v frac step
1109         mov     Tmap.DeltaVFrac, ebx    // store it
1110         imul    eax, Tmap.src_offset    // calc texture step for v int step
1111         
1112         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
1113         mov     ecx, ebx                                                // copy it
1114         sar     ebx, 16                                         // get the u int step
1115         shl     ecx, 16                                         // get the u frac step
1116         mov     Tmap.DeltaUFrac, ecx                    // store it
1117         add     eax, ebx                                                // calc uint + vint step
1118         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1119         add     eax, Tmap.src_offset                            // calc whole step + v carry
1120         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1121
1122
1123 OnePixelSpan:
1124
1125         ; setup initial coordinates
1126         mov     esi, Tmap.UFixed                        // get u 16.16
1127         mov     ebx, esi                                                // copy it
1128         sar     esi, 16                                         // get integer part
1129         shl     ebx, 16                                         // get fractional part
1130
1131         mov     ecx, Tmap.VFixed                        // get v 16.16 
1132         mov     edx, ecx                                                // copy it
1133         sar     edx, 16                                         // get integer part
1134         shl     ecx, 16                                         // get fractional part
1135         imul    edx, Tmap.src_offset            // calc texture scanline address
1136         add     esi, edx                                                        // calc texture offset
1137         add     esi, Tmap.pixptr                        // calc address
1138
1139
1140         mov     eax, Tmap.fx_l
1141         shr     eax, 8
1142         mov     bx, ax
1143
1144 //      mov     edx, Tmap.DeltaUFrac
1145
1146         push    ebx
1147         
1148         mov     ebx, Tmap.fx_l_right
1149         shr     ebx, 8
1150         
1151         sub     ebx, eax
1152         mov     eax, ebx
1153         
1154         mov     eax, Tmap.fx_dl_dx
1155         shr     eax, 8
1156
1157         mov     bp, ax
1158
1159         pop     ebx
1160
1161
1162         mov     eax, edi
1163         sub     eax, Tmap.pScreenBits
1164         mov     edx, gr_zbuffer
1165         shl     eax, 2
1166         add     edx, eax
1167
1168         inc     Tmap.WidthModLength
1169         mov     eax,Tmap.WidthModLength
1170         shr     eax, 1
1171         jz              one_more_pix
1172         pushf
1173         mov     Tmap.WidthModLength, eax
1174
1175         xor     eax, eax
1176
1177         mov     al,[edi]                    // preread the destination cache line
1178
1179 // Make ESI =  DV:DU in 6:10,6:10 format
1180         mov     eax, Tmap.DeltaV
1181         shr     eax, 4
1182         mov     esi, Tmap.DeltaU
1183         shl     esi, 12
1184         mov     si, ax
1185         mov     Tmap.DeltaUFrac, esi
1186                 
1187 // Make ECX = V:U in 6:10,6:10 format
1188         mov     eax, Tmap.VFixed
1189         shr     eax, 4
1190         mov     ecx, Tmap.UFixed
1191         shl     ecx, 12
1192         mov     cx, ax
1193
1194         mov     esi, Tmap.fx_w
1195
1196         // eax = tmp
1197         // ebx = light
1198         // ecx = V:U in 8.6:10.8
1199         // edx = zbuffer pointer
1200         // esi = z
1201         // edi = screen data
1202         // ebp = dl_dx
1203
1204
1205
1206 NextPixel:
1207                 // pixel 0
1208                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1209                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
1210                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
1211                 and     eax, 0ffh                                               // clear upper bits
1212                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1213
1214                 mov     al, [eax]                       
1215                 mov     ah, bh  
1216                 and     eax, 0ffffh                                             // clear upper bits
1217                 mov     al, gr_fade_table[eax]
1218                 mov     [edi+0], al
1219                 add     ecx, Tmap.DeltaUFrac
1220                 add     ebx, ebp 
1221
1222                 // pixel 1
1223                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1224                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
1225                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
1226                 and     eax, 0ffh                                               // clear upper bits
1227                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1228
1229                 mov     al, [eax]                       
1230                 mov     ah, bh  
1231                 and     eax, 0ffffh                                             // clear upper bits
1232                 mov     al, gr_fade_table[eax]
1233                 mov     [edi+1], al
1234                 add     ecx, Tmap.DeltaUFrac
1235                 add     ebx, ebp 
1236
1237
1238
1239         add     edi, 2
1240         add     edx, 8
1241         dec     Tmap.WidthModLength
1242         jg              NextPixel
1243
1244         popf
1245         jnc     FPUReturn
1246
1247 one_more_pix:   
1248                 // pixel 0
1249                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 6.10:6.10
1250                 shr     ax, 12                                                          // EAX = V:U in 6.10:16.0
1251                 rol     eax, 4                                                  // EAX = V:U in 0.0:6:6
1252                 and     eax, 0ffh                                               // clear upper bits
1253                 add     eax, Tmap.pixptr                // EAX = (V*64)+U + Pixptr
1254
1255                 mov     al, [eax]                       
1256                 mov     ah, bh  
1257                 and     eax, 0ffffh                                             // clear upper bits
1258                 mov     al, gr_fade_table[eax]
1259                 mov     [edi+0], al
1260                 add     ecx, Tmap.DeltaUFrac
1261                 add     ebx, ebp 
1262
1263
1264 FPUReturn:
1265
1266         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1267                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1268         ffree   st(0)
1269         ffree   st(1)
1270         ffree   st(2)
1271         ffree   st(3)
1272         ffree   st(4)
1273         ffree   st(5)
1274         ffree   st(6)
1275
1276         fldcw   Tmap.OldFPUCW                  // restore the FPU
1277
1278         pop     edi
1279         pop     esi
1280         pop     ebp
1281         pop     ebx
1282         pop     edx
1283         pop     ecx
1284         pop     eax
1285         }
1286 #endif
1287 }