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