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