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