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