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