]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/tmapscantiled256x256.cpp
Initial revision
[taylor/freespace2.git] / src / graphics / tmapscantiled256x256.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/TmapScanTiled256x256.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Routines for drawing tiled 256x256 textues
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 4     11/30/98 5:31p Dave
15  * Fixed up Fred support for software mode.
16  * 
17  * 3     11/30/98 1:07p Dave
18  * 16 bit conversion, first run.
19  * 
20  * 2     10/07/98 10:53a Dave
21  * Initial checkin.
22  * 
23  * 1     10/07/98 10:49a Dave
24  * 
25  * 11    5/13/98 2:53p John
26  * Made subspace effect work under software.  Had to add new inner loop to
27  * tmapper.  Added glows to end of subspace effect.  Made subspace effect
28  * levels use gamepalette-subspace palette.
29  * 
30  * 10    4/23/98 9:55a John
31  * Fixed some bugs in the tiled tmapper causing bright dots to appear all
32  * over models.
33  * 
34  * 9     3/10/98 4:19p John
35  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
36  * & Glide have popups and print screen.  Took out all >8bpp software
37  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
38  * support Fred.  Made zbuffering key off of functions rather than one
39  * global variable.
40  * 
41  * 8     1/27/98 5:13p John
42  * Moved all float to int conversions out of inner loops and into outer.
43  * Made outer loop use FISTP instead of ftol, saved about 10%.
44  * 
45  * 7     1/23/98 5:08p John
46  * Took L out of vertex structure used B (blue) instead.   Took all small
47  * fireballs out of fireball types and used particles instead.  Fixed some
48  * debris explosion things.  Restructured fireball code.   Restructured
49  * some lighting code.   Made dynamic lighting on by default. Made groups
50  * of lasers only cast one light.  Made fireballs not cast light.
51  * 
52  * 6     12/04/97 10:38a John
53  * Fixed tiled texture mappers that were swapping uvs.
54  * 
55  * 5     10/14/97 9:19a John
56  * removed fdiv warnings.
57  * 
58  * 4     9/10/97 11:38a Sandeep
59  * 
60  * 3     9/09/97 3:39p Sandeep
61  * warning level 4 bugs
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 #include "key.h"
83
84 // Needed to keep warning 4725 to stay away.  See PsTypes.h for details why.
85 void disable_warning_4725_stub_tst256()
86 {
87 }
88
89 void tmapscan_pln8_zbuffered_tiled_256x256()
90 {
91 #ifdef PLAT_UNIX
92         STUB_FUNCTION;
93 #else
94         _asm {
95         
96         push    eax
97         push    ecx
98         push    edx
99         push    ebx
100         push    ebp
101         push    esi
102         push    edi
103
104         // Put the FPU in low precision mode
105         fstcw           Tmap.OldFPUCW                                   // store copy of CW
106         mov             ax,Tmap.OldFPUCW                                // get it in ax
107         and             eax, ~0x300L
108         mov             Tmap.FPUCW,ax                                   // store it
109         fldcw           Tmap.FPUCW                                              // load the FPU
110
111
112         mov             ecx, Tmap.loop_count            // ecx = width
113         mov             edi, Tmap.dest_row_data // edi = dest pointer
114
115         // edi = pointer to start pixel in dest dib
116         // ecx = spanwidth
117
118         mov             eax,ecx                                                 // eax and ecx = width
119         shr             ecx,5                                                           // ecx = width / subdivision length
120         and             eax,31                                                          // eax = width mod subdivision length
121         jnz             some_left_over                                  // any leftover?
122         dec             ecx                                                             // no, so special case last span
123         mov             eax,32                                                          // it's 8 pixels long
124 some_left_over:
125         mov             Tmap.Subdivisions,ecx           // store widths
126         mov             Tmap.WidthModLength,eax
127
128         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
129                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
130         fld             Tmap.l.v                                        // V/ZL 
131         fld             Tmap.l.u                                        // U/ZL V/ZL 
132         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
133         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
134         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
135         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
136         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
137         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
138         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
139
140         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
141         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
142
143         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
144
145         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
146         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
147         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
148         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
149         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
150
151         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
152
153         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
154         // @todo overlap this guy
155         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
156         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
157         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
158         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
159         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
160
161         cmp             ecx,0                                                   // check for any full spans
162         jle      HandleLeftoverPixels
163     
164 SpanLoop:
165
166         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
167                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
168
169         // convert left side coords
170
171         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
172         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
173         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
174
175         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
176         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
177         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
178
179         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
180
181         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
182         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
183         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
184         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
185
186         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
187         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
188
189         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
190         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
191         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
192
193         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
194         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
195
196         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
197         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
198         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
199         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
200         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
201         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
202         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
203
204
205         // setup delta values
206     
207         mov     eax,Tmap.DeltaV                         // get v 16.16 step
208         mov     ebx,eax                                                 // copy it
209         sar     eax,16                                                          // get v int step
210         shl     ebx,16                                                          // get v frac step
211         mov     Tmap.DeltaVFrac,ebx                     // store it
212         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
213
214         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
215         mov     ecx,ebx                                                 // copy it
216         sar     ebx,16                                                          // get u int step
217         shl     ecx,16                                                          // get u frac step
218         mov     Tmap.DeltaUFrac,ecx                     // store it
219         add     eax,ebx                                                 // calculate uint + vint step
220         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
221         add     eax,Tmap.src_offset                     // calculate whole step + v carry
222         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
223
224         // setup initial coordinates
225         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
226
227         mov     ebx,esi                                                 // copy it
228         sar     esi,16                                                          // get integer part
229         shl     ebx,16                                                          // get fractional part
230
231         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
232    
233         mov     edx,ecx                                                 // copy it
234         sar     edx,16                                                          // get integer part
235         shl     ecx,16                                                          // get fractional part
236         imul    edx,Tmap.src_offset                     // calc texture scanline address
237         add     esi,edx                                                 // calc texture offset
238         add     esi,Tmap.pixptr                         // calc address
239
240         // set up affine registers
241
242         mov     eax, Tmap.fx_l
243         shr     eax, 8
244         mov     bx, ax
245
246         mov     ebp, Tmap.fx_dl_dx
247         shl     ebp, 5  //*32
248         add     Tmap.fx_l, ebp
249
250         mov     ebp, Tmap.fx_l
251         shr     ebp, 8
252         sub     bp, ax
253         shr     bp, 5
254
255         mov     dx, bp
256
257         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
258         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
259         // This divide should happen while the pixel span is drawn.
260         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
261
262
263         // 8 pixel span code
264         // edi = dest dib bits at current pixel
265         // esi = texture pointer at current u,v
266         // eax = scratch
267         // ebx = u fraction 0.32
268         // ecx = v fraction 0.32
269         // edx = u frac step
270         // ebp = v carry scratch
271
272         mov     al,[edi]                                                                // preread the destination cache line
273
274         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
275
276         mov     eax, edi
277         sub     eax, Tmap.pScreenBits
278         mov     edx, gr_zbuffer
279         shl     eax, 2
280         add     edx, eax
281
282 // Make ESI =  DV:DU in 8:8,8:8 format
283         mov     eax, Tmap.DeltaV
284         shr     eax, 8
285         mov     esi, Tmap.DeltaU
286         shl     esi, 8
287         mov     si, ax
288         mov     Tmap.DeltaUFrac, esi
289                 
290 // Make ECX = V:U in 8:8,8:8 format
291         mov     eax, Tmap.VFixed
292         shr     eax, 8
293         mov     ecx, Tmap.UFixed
294         shl     ecx, 8
295         mov     cx, ax
296
297         mov     esi, Tmap.fx_w
298
299         // eax = tmp
300         // ebx = light
301         // ecx = V:U in 8.8:8.8
302         // edx = zbuffer pointer
303         // esi = z
304         // edi = screen data
305         // ebp = dl_dx
306
307
308 InnerInnerLoop:
309
310                 // pixel 0
311                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
312                 jle     Skip0                                                           // If pixel is covered, skip drawing
313
314                 mov     [edx+0], esi                                    // Write z
315
316                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
317                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
318                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
319                 and     eax, 0ffffh                                             // clear upper bits
320                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
321
322                 mov     al, [eax]                       
323                 mov     ah, bh  
324                 and     eax, 0ffffh                                             // clear upper bits
325                 mov     al, gr_fade_table[eax]
326                 mov     [edi+0], al
327 Skip0:
328                 add     ecx, Tmap.DeltaUFrac
329                 add     esi, Tmap.fx_dwdx
330                 add     ebx, ebp 
331
332                 // pixel 1
333                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
334                 jle     Skip1                                                           // If pixel is covered, skip drawing
335
336                 mov     [edx+4], esi                                    // Write z
337
338                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
339                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
340                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
341                 and     eax, 0ffffh                                             // clear upper bits
342                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
343
344                 mov     al, [eax]                       
345                 mov     ah, bh  
346                 and     eax, 0ffffh                                             // clear upper bits
347                 mov     al, gr_fade_table[eax]
348                 mov     [edi+1], al
349 Skip1:
350                 add     ecx, Tmap.DeltaUFrac
351                 add     esi, Tmap.fx_dwdx
352                 add     ebx, ebp 
353
354                 // pixel 2
355                 cmp     esi, [edx+8]                                    // Compare the Z depth of this pixel with zbuffer
356                 jle     Skip2                                                           // If pixel is covered, skip drawing
357
358                 mov     [edx+8], esi                                    // Write z
359
360                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
361                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
362                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
363                 and     eax, 0ffffh                                             // clear upper bits
364                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
365
366                 mov     al, [eax]                       
367                 mov     ah, bh  
368                 and     eax, 0ffffh                                             // clear upper bits
369                 mov     al, gr_fade_table[eax]
370                 mov     [edi+2], al
371 Skip2:
372                 add     ecx, Tmap.DeltaUFrac
373                 add     esi, Tmap.fx_dwdx
374                 add     ebx, ebp 
375
376                 // pixel 3
377                 cmp     esi, [edx+12]                                   // Compare the Z depth of this pixel with zbuffer
378                 jle     Skip3                                                           // If pixel is covered, skip drawing
379
380                 mov     [edx+12], esi                                   // Write z
381
382                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
383                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
384                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
385                 and     eax, 0ffffh                                             // clear upper bits
386                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
387
388                 mov     al, [eax]                       
389                 mov     ah, bh  
390                 and     eax, 0ffffh                                             // clear upper bits
391                 mov     al, gr_fade_table[eax]
392                 mov     [edi+3], al
393 Skip3:
394                 add     ecx, Tmap.DeltaUFrac
395                 add     esi, Tmap.fx_dwdx
396                 add     ebx, ebp 
397
398
399         add     edi, 4
400         add     edx, 16
401         dec     Tmap.InnerLooper
402         jnz     InnerInnerLoop
403
404         mov     Tmap.fx_w, esi
405
406         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
407                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
408
409     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
410     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
411     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
412     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
413
414     dec     Tmap.Subdivisions                   // decrement span count
415     jnz     SpanLoop                                                    // loop back
416
417
418 HandleLeftoverPixels:
419
420     mov     esi,Tmap.pixptr                             // load texture pointer
421
422     // edi = dest dib bits
423     // esi = current texture dib bits
424     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
425     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
426
427     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
428     jz      FPUReturn                   ; nope, pop the FPU and bail
429
430     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
431
432     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
433     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
434     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
435
436     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
437     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
438     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
439
440     dec     Tmap.WidthModLength            ; calc how many steps to take
441     jz      OnePixelSpan                ; just one, don't do deltas'
442
443     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
444     // r -> R+1
445
446     // @todo rearrange things so we don't need these two instructions
447     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
448     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
449
450     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
451     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
452     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
453     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
454     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
455     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
456
457     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
458
459     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
460     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
461
462     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
463
464     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
465     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
466     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
467     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
468
469     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
470     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
471     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
472
473     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
474     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
475     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
476     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
477
478     // @todo gross!  these are to line up with the other loop
479     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
480     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
481
482
483         // setup delta values
484         mov     eax, Tmap.DeltaV        // get v 16.16 step
485         mov     ebx, eax                                                // copy it
486         sar     eax, 16                                         // get v int step
487         shl     ebx, 16                                         // get v frac step
488         mov     Tmap.DeltaVFrac, ebx    // store it
489         imul    eax, Tmap.src_offset    // calc texture step for v int step
490         
491         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
492         mov     ecx, ebx                                                // copy it
493         sar     ebx, 16                                         // get the u int step
494         shl     ecx, 16                                         // get the u frac step
495         mov     Tmap.DeltaUFrac, ecx                    // store it
496         add     eax, ebx                                                // calc uint + vint step
497         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
498         add     eax, Tmap.src_offset                            // calc whole step + v carry
499         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
500
501
502 OnePixelSpan:
503
504         ; setup initial coordinates
505         mov     esi, Tmap.UFixed                        // get u 16.16
506         mov     ebx, esi                                                // copy it
507         sar     esi, 16                                         // get integer part
508         shl     ebx, 16                                         // get fractional part
509
510         mov     ecx, Tmap.VFixed                        // get v 16.16 
511         mov     edx, ecx                                                // copy it
512         sar     edx, 16                                         // get integer part
513         shl     ecx, 16                                         // get fractional part
514         imul    edx, Tmap.src_offset            // calc texture scanline address
515         add     esi, edx                                                        // calc texture offset
516         add     esi, Tmap.pixptr                        // calc address
517
518
519         mov     eax, Tmap.fx_l
520         shr     eax, 8
521         mov     bx, ax
522
523 //      mov     edx, Tmap.DeltaUFrac
524
525         push    ebx
526         
527         mov     ebx, Tmap.fx_l_right
528         shr     ebx, 8
529         
530         sub     ebx, eax
531         mov     eax, ebx
532         
533         mov     eax, Tmap.fx_dl_dx
534         shr     eax, 8
535
536         mov     bp, ax
537
538         pop     ebx
539
540
541         mov     eax, edi
542         sub     eax, Tmap.pScreenBits
543         mov     edx, gr_zbuffer
544         shl     eax, 2
545         add     edx, eax
546
547         inc     Tmap.WidthModLength
548         mov     eax,Tmap.WidthModLength
549         shr     eax, 1
550         jz              one_more_pix
551         pushf
552         mov     Tmap.WidthModLength, eax
553
554         xor     eax, eax
555
556         mov     al,[edi]                    // preread the destination cache line
557
558 // Make ESI =  DV:DU in 8:8,8:8 format
559         mov     eax, Tmap.DeltaV
560         shr     eax, 8
561         mov     esi, Tmap.DeltaU
562         shl     esi, 8
563         mov     si, ax
564         mov     Tmap.DeltaUFrac, esi
565                 
566 // Make ECX = V:U in 8:8,8:8 format
567         mov     eax, Tmap.VFixed
568         shr     eax, 8
569         mov     ecx, Tmap.UFixed
570         shl     ecx, 8
571         mov     cx, ax
572
573         mov     esi, Tmap.fx_w
574
575         // eax = tmp
576         // ebx = light
577         // ecx = V:U in 8.8:8.8
578         // edx = zbuffer pointer
579         // esi = z
580         // edi = screen data
581         // ebp = dl_dx
582
583
584
585 NextPixel:
586                 // pixel 0
587                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
588                 jle     Skip0a                                                          // If pixel is covered, skip drawing
589
590                 mov     [edx+0], esi                                    // Write z
591
592                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
593                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
594                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
595                 and     eax, 0ffffh                                             // clear upper bits
596                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
597
598                 mov     al, [eax]                       
599                 mov     ah, bh  
600                 and     eax, 0ffffh                                             // clear upper bits
601                 mov     al, gr_fade_table[eax]
602                 mov     [edi+0], al
603 Skip0a:
604                 add     ecx, Tmap.DeltaUFrac
605                 add     esi, Tmap.fx_dwdx
606                 add     ebx, ebp 
607
608                 // pixel 1
609                 cmp     esi, [edx+4]                                    // Compare the Z depth of this pixel with zbuffer
610                 jle     Skip1a                                                          // If pixel is covered, skip drawing
611
612                 mov     [edx+4], esi                                    // Write z
613
614                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
615                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
616                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
617                 and     eax, 0ffffh                                             // clear upper bits
618                 add     eax, Tmap.pixptr                // EAX = (V*256)+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+1], al
625 Skip1a:
626                 add     ecx, Tmap.DeltaUFrac
627                 add     esi, Tmap.fx_dwdx
628                 add     ebx, ebp 
629
630
631
632         add     edi, 2
633         add     edx, 8
634         dec     Tmap.WidthModLength
635         jg              NextPixel
636
637         popf
638         jnc     FPUReturn
639
640 one_more_pix:   
641                 // pixel 0
642                 cmp     esi, [edx+0]                                    // Compare the Z depth of this pixel with zbuffer
643                 jle     Skip0b                                                          // If pixel is covered, skip drawing
644
645                 mov     [edx+0], esi                                    // Write z
646
647                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
648                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
649                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
650                 and     eax, 0ffffh                                             // clear upper bits
651                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
652
653                 mov     al, [eax]                       
654                 mov     ah, bh  
655                 and     eax, 0ffffh                                             // clear upper bits
656                 mov     al, gr_fade_table[eax]
657                 mov     [edi+0], al
658 Skip0b:
659                 add     ecx, Tmap.DeltaUFrac
660                 add     esi, Tmap.fx_dwdx
661                 add     ebx, ebp 
662
663
664 FPUReturn:
665
666         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
667                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
668         ffree   st(0)
669         ffree   st(1)
670         ffree   st(2)
671         ffree   st(3)
672         ffree   st(4)
673         ffree   st(5)
674         ffree   st(6)
675
676         fldcw   Tmap.OldFPUCW                  // restore the FPU
677
678         pop     edi
679         pop     esi
680         pop     ebp
681         pop     ebx
682         pop     edx
683         pop     ecx
684         pop     eax
685         }
686 #endif
687 }
688
689 void tmapscan_pln8_tiled_256x256()
690 {
691         if (gr_zbuffering) {
692                 switch(gr_zbuffering_mode)      {
693                 case GR_ZBUFF_NONE:
694                         break;
695                 case GR_ZBUFF_FULL:             // both
696                         tmapscan_pln8_zbuffered_tiled_256x256();
697                         return;
698                 case GR_ZBUFF_WRITE:            // write only
699                         tmapscan_pln8_zbuffered_tiled_256x256();
700                         break;
701                 case GR_ZBUFF_READ:             // read only
702                         tmapscan_pln8_zbuffered_tiled_256x256();
703                         return;
704                 }
705         }
706
707 #ifdef PLAT_UNIX
708         STUB_FUNCTION;
709 #else
710         _asm {
711         
712         push    eax
713         push    ecx
714         push    edx
715         push    ebx
716         push    ebp
717         push    esi
718         push    edi
719
720         // Put the FPU in low precision mode
721         fstcw           Tmap.OldFPUCW                                   // store copy of CW
722         mov             ax,Tmap.OldFPUCW                                // get it in ax
723         and             eax, ~0x300L
724         mov             Tmap.FPUCW,ax                                   // store it
725         fldcw           Tmap.FPUCW                                              // load the FPU
726
727
728         mov             ecx, Tmap.loop_count            // ecx = width
729         mov             edi, Tmap.dest_row_data // edi = dest pointer
730
731         // edi = pointer to start pixel in dest dib
732         // ecx = spanwidth
733
734         mov             eax,ecx                                                 // eax and ecx = width
735         shr             ecx,5                                                           // ecx = width / subdivision length
736         and             eax,31                                                          // eax = width mod subdivision length
737         jnz             some_left_over                                  // any leftover?
738         dec             ecx                                                             // no, so special case last span
739         mov             eax,32                                                          // it's 8 pixels long
740 some_left_over:
741         mov             Tmap.Subdivisions,ecx           // store widths
742         mov             Tmap.WidthModLength,eax
743
744         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
745                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
746         fld             Tmap.l.v                                        // V/ZL 
747         fld             Tmap.l.u                                        // U/ZL V/ZL 
748         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
749         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
750         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
751         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
752         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
753         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
754         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
755
756         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
757         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
758
759         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
760
761         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
762         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
763         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
764         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
765         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
766
767         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
768
769         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
770         // @todo overlap this guy
771         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
772         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
773         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
774         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
775         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
776
777         cmp             ecx,0                                                   // check for any full spans
778         jle      HandleLeftoverPixels
779     
780 SpanLoop:
781
782         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
783                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
784
785         // convert left side coords
786
787         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
788         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
789         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
790
791         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
792         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
793         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
794
795         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
796
797         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
798         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
799         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
800         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
801
802         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
803         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
804
805         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
806         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
807         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
808
809         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
810         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
811
812         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
813         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
814         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
815         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
816         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
817         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
818         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
819
820
821         // setup delta values
822     
823         mov     eax,Tmap.DeltaV                         // get v 16.16 step
824         mov     ebx,eax                                                 // copy it
825         sar     eax,16                                                          // get v int step
826         shl     ebx,16                                                          // get v frac step
827         mov     Tmap.DeltaVFrac,ebx                     // store it
828         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
829
830         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
831         mov     ecx,ebx                                                 // copy it
832         sar     ebx,16                                                          // get u int step
833         shl     ecx,16                                                          // get u frac step
834         mov     Tmap.DeltaUFrac,ecx                     // store it
835         add     eax,ebx                                                 // calculate uint + vint step
836         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
837         add     eax,Tmap.src_offset                     // calculate whole step + v carry
838         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
839
840         // setup initial coordinates
841         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
842
843         mov     ebx,esi                                                 // copy it
844         sar     esi,16                                                          // get integer part
845         shl     ebx,16                                                          // get fractional part
846
847         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
848    
849         mov     edx,ecx                                                 // copy it
850         sar     edx,16                                                          // get integer part
851         shl     ecx,16                                                          // get fractional part
852         imul    edx,Tmap.src_offset                     // calc texture scanline address
853         add     esi,edx                                                 // calc texture offset
854         add     esi,Tmap.pixptr                         // calc address
855
856         // set up affine registers
857
858         mov     eax, Tmap.fx_l
859         shr     eax, 8
860         mov     bx, ax
861
862         mov     ebp, Tmap.fx_dl_dx
863         shl     ebp, 5  //*32
864         add     Tmap.fx_l, ebp
865
866         mov     ebp, Tmap.fx_l
867         shr     ebp, 8
868         sub     bp, ax
869         shr     bp, 5
870
871         mov     dx, bp
872
873         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
874         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
875         // This divide should happen while the pixel span is drawn.
876         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
877
878
879         // 8 pixel span code
880         // edi = dest dib bits at current pixel
881         // esi = texture pointer at current u,v
882         // eax = scratch
883         // ebx = u fraction 0.32
884         // ecx = v fraction 0.32
885         // edx = u frac step
886         // ebp = v carry scratch
887
888         mov     al,[edi]                                                                // preread the destination cache line
889
890         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
891
892         mov     eax, edi
893         sub     eax, Tmap.pScreenBits
894         mov     edx, gr_zbuffer
895         shl     eax, 2
896         add     edx, eax
897
898 // Make ESI =  DV:DU in 8:8,8:8 format
899         mov     eax, Tmap.DeltaV
900         shr     eax, 8
901         mov     esi, Tmap.DeltaU
902         shl     esi, 8
903         mov     si, ax
904         mov     Tmap.DeltaUFrac, esi
905                 
906 // Make ECX = V:U in 8:8,8:8 format
907         mov     eax, Tmap.VFixed
908         shr     eax, 8
909         mov     ecx, Tmap.UFixed
910         shl     ecx, 8
911         mov     cx, ax
912
913
914         // eax = tmp
915         // ebx = light
916         // ecx = V:U in 8.8:8.8
917         // edx = zbuffer pointer
918         // esi = z
919         // edi = screen data
920         // ebp = dl_dx
921
922
923 InnerInnerLoop:
924
925                 // pixel 0
926                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
927                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
928                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
929                 and     eax, 0ffffh                                             // clear upper bits
930                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
931
932                 mov     al, [eax]                       
933                 mov     ah, bh  
934                 and     eax, 0ffffh                                             // clear upper bits
935                 mov     al, gr_fade_table[eax]
936                 mov     [edi+0], al
937                 add     ecx, Tmap.DeltaUFrac
938                 add     ebx, ebp 
939
940                 // pixel 1
941                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
942                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
943                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
944                 and     eax, 0ffffh                                             // clear upper bits
945                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
946
947                 mov     al, [eax]                       
948                 mov     ah, bh  
949                 and     eax, 0ffffh                                             // clear upper bits
950                 mov     al, gr_fade_table[eax]
951                 mov     [edi+1], al
952                 add     ecx, Tmap.DeltaUFrac
953                 add     ebx, ebp 
954
955                 // pixel 2
956                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
957                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
958                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
959                 and     eax, 0ffffh                                             // clear upper bits
960                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
961
962                 mov     al, [eax]                       
963                 mov     ah, bh  
964                 and     eax, 0ffffh                                             // clear upper bits
965                 mov     al, gr_fade_table[eax]
966                 mov     [edi+2], al
967                 add     ecx, Tmap.DeltaUFrac
968                 add     ebx, ebp 
969
970                 // pixel 3
971                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
972                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
973                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
974                 and     eax, 0ffffh                                             // clear upper bits
975                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
976
977                 mov     al, [eax]                       
978                 mov     ah, bh  
979                 and     eax, 0ffffh                                             // clear upper bits
980                 mov     al, gr_fade_table[eax]
981                 mov     [edi+3], al
982                 add     ecx, Tmap.DeltaUFrac
983                 add     ebx, ebp 
984
985
986         add     edi, 4
987         dec     Tmap.InnerLooper
988         jnz     InnerInnerLoop
989
990         mov     Tmap.fx_w, esi
991
992         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
993                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
994
995     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
996     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
997     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
998     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
999
1000     dec     Tmap.Subdivisions                   // decrement span count
1001     jnz     SpanLoop                                                    // loop back
1002
1003
1004 HandleLeftoverPixels:
1005
1006     mov     esi,Tmap.pixptr                             // load texture pointer
1007
1008     // edi = dest dib bits
1009     // esi = current texture dib bits
1010     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
1011     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
1012
1013     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1014     jz      FPUReturn                   ; nope, pop the FPU and bail
1015
1016     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1017
1018     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
1019     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
1020     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
1021
1022     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
1023     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
1024     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
1025
1026     dec     Tmap.WidthModLength            ; calc how many steps to take
1027     jz      OnePixelSpan                ; just one, don't do deltas'
1028
1029     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1030     // r -> R+1
1031
1032     // @todo rearrange things so we don't need these two instructions
1033     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
1034     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
1035
1036     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
1037     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
1038     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
1039     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
1040     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
1041     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
1042
1043     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1044
1045     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
1046     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
1047
1048     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1049
1050     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
1051     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
1052     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
1053     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
1054
1055     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
1056     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
1057     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
1058
1059     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
1060     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
1061     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
1062     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
1063
1064     // @todo gross!  these are to line up with the other loop
1065     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
1066     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
1067
1068
1069         // setup delta values
1070         mov     eax, Tmap.DeltaV        // get v 16.16 step
1071         mov     ebx, eax                                                // copy it
1072         sar     eax, 16                                         // get v int step
1073         shl     ebx, 16                                         // get v frac step
1074         mov     Tmap.DeltaVFrac, ebx    // store it
1075         imul    eax, Tmap.src_offset    // calc texture step for v int step
1076         
1077         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
1078         mov     ecx, ebx                                                // copy it
1079         sar     ebx, 16                                         // get the u int step
1080         shl     ecx, 16                                         // get the u frac step
1081         mov     Tmap.DeltaUFrac, ecx                    // store it
1082         add     eax, ebx                                                // calc uint + vint step
1083         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1084         add     eax, Tmap.src_offset                            // calc whole step + v carry
1085         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1086
1087
1088 OnePixelSpan:
1089
1090         ; setup initial coordinates
1091         mov     esi, Tmap.UFixed                        // get u 16.16
1092         mov     ebx, esi                                                // copy it
1093         sar     esi, 16                                         // get integer part
1094         shl     ebx, 16                                         // get fractional part
1095
1096         mov     ecx, Tmap.VFixed                        // get v 16.16 
1097         mov     edx, ecx                                                // copy it
1098         sar     edx, 16                                         // get integer part
1099         shl     ecx, 16                                         // get fractional part
1100         imul    edx, Tmap.src_offset            // calc texture scanline address
1101         add     esi, edx                                                        // calc texture offset
1102         add     esi, Tmap.pixptr                        // calc address
1103
1104
1105         mov     eax, Tmap.fx_l
1106         shr     eax, 8
1107         mov     bx, ax
1108
1109 //      mov     edx, Tmap.DeltaUFrac
1110
1111         push    ebx
1112         
1113         mov     ebx, Tmap.fx_l_right
1114         shr     ebx, 8
1115         
1116         sub     ebx, eax
1117         mov     eax, ebx
1118         
1119         mov     eax, Tmap.fx_dl_dx
1120         shr     eax, 8
1121
1122         mov     bp, ax
1123
1124         pop     ebx
1125
1126         mov     eax, edi
1127         sub     eax, Tmap.pScreenBits
1128         mov     edx, gr_zbuffer
1129         shl     eax, 2
1130         add     edx, eax
1131
1132         inc     Tmap.WidthModLength
1133         mov     eax,Tmap.WidthModLength
1134         shr     eax, 1
1135         jz              one_more_pix
1136         pushf
1137         mov     Tmap.WidthModLength, eax
1138
1139         xor     eax, eax
1140
1141         mov     al,[edi]                    // preread the destination cache line
1142
1143 // Make ESI =  DV:DU in 8:8,8:8 format
1144         mov     eax, Tmap.DeltaV
1145         shr     eax, 8
1146         mov     esi, Tmap.DeltaU
1147         shl     esi, 8
1148         mov     si, ax
1149         mov     Tmap.DeltaUFrac, esi
1150                 
1151 // Make ECX = V:U in 8:8,8:8 format
1152         mov     eax, Tmap.UFixed
1153         shr     eax, 8
1154         mov     ecx, Tmap.VFixed
1155         shl     ecx, 8
1156         mov     cx, ax
1157
1158         // eax = tmp
1159         // ebx = light
1160         // ecx = V:U in 8.8:8.8
1161         // edx = zbuffer pointer
1162         // esi = z
1163         // edi = screen data
1164         // ebp = dl_dx
1165
1166
1167
1168 NextPixel:
1169                 // pixel 0
1170                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1171                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1172                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1173                 and     eax, 0ffffh                                             // clear upper bits
1174                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
1175
1176                 mov     al, [eax]                       
1177                 mov     ah, bh  
1178                 and     eax, 0ffffh                                             // clear upper bits
1179                 mov     al, gr_fade_table[eax]
1180                 mov     [edi+0], al
1181                 add     ecx, Tmap.DeltaUFrac
1182                 add     ebx, ebp 
1183
1184                 // pixel 1
1185                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1186                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1187                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1188                 and     eax, 0ffffh                                             // clear upper bits
1189                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
1190
1191                 mov     al, [eax]                       
1192                 mov     ah, bh  
1193                 and     eax, 0ffffh                                             // clear upper bits
1194                 mov     al, gr_fade_table[eax]
1195                 mov     [edi+1], al
1196                 add     ecx, Tmap.DeltaUFrac
1197                 add     ebx, ebp 
1198
1199
1200
1201         add     edi, 2
1202         add     edx, 8
1203         dec     Tmap.WidthModLength
1204         jg              NextPixel
1205
1206         popf
1207         jnc     FPUReturn
1208
1209 one_more_pix:   
1210                 // pixel 0
1211                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1212                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1213                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1214                 and     eax, 0ffffh                                             // clear upper bits
1215                 add     eax, Tmap.pixptr                // EAX = (V*256)+U + Pixptr
1216
1217                 mov     al, [eax]                       
1218                 mov     ah, bh  
1219                 and     eax, 0ffffh                                             // clear upper bits
1220                 mov     al, gr_fade_table[eax]
1221                 mov     [edi+0], al
1222                 add     ecx, Tmap.DeltaUFrac
1223                 add     ebx, ebp 
1224
1225
1226 FPUReturn:
1227
1228         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1229                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1230         ffree   st(0)
1231         ffree   st(1)
1232         ffree   st(2)
1233         ffree   st(3)
1234         ffree   st(4)
1235         ffree   st(5)
1236         ffree   st(6)
1237
1238         fldcw   Tmap.OldFPUCW                  // restore the FPU
1239
1240         pop     edi
1241         pop     esi
1242         pop     ebp
1243         pop     ebx
1244         pop     edx
1245         pop     ecx
1246         pop     eax
1247         }
1248 #endif
1249 }
1250
1251
1252 // Totally non-general function specifically made for the subpsace effect
1253 void tmapscan_lnn8_tiled_256x256()
1254 {
1255         if ( Tmap.src_offset != 256 )   {
1256                 Int3();         // This only works on 256 wide textures!
1257                 return;
1258         }
1259
1260 //      Tmap.fx_u = fl2f(Tmap.l.u);
1261 //      Tmap.fx_v = fl2f(Tmap.l.v);
1262 //      Tmap.fx_du_dx = fl2f(Tmap.deltas.u);
1263 //      Tmap.fx_dv_dx = fl2f(Tmap.deltas.v);
1264
1265         int i;
1266
1267         ubyte * src = (ubyte *)Tmap.pixptr;
1268         ubyte * dst = (ubyte *)Tmap.dest_row_data;
1269         
1270         for (i=0; i<Tmap.loop_count; i++ )      {
1271                 int u,v;
1272                 u = f2i(Tmap.fx_u) & 255;
1273                 v = f2i(Tmap.fx_v) & 255;
1274
1275                 ubyte c = src[u+v*Tmap.src_offset];
1276                 *dst = c;
1277                 dst++;
1278                                         
1279                 Tmap.fx_u += Tmap.fx_du_dx;
1280                 Tmap.fx_v += Tmap.fx_dv_dx;
1281         }
1282         return;
1283
1284
1285 #ifdef PLAT_UNIX
1286         STUB_FUNCTION;
1287 #else
1288         _asm {
1289         push    eax
1290         push    ecx
1291         push    edx
1292         push    ebx
1293         push    ebp
1294         push    esi
1295         push    edi
1296
1297         // Need ECX = V.VF:U.UF in 8.8:8.8
1298         mov     eax, Tmap.fx_u
1299         shr     eax, 8
1300         mov     ecx, Tmap.fx_v
1301         shl     ecx, 8
1302         mov     cx, ax
1303                 
1304         // Need EDX = delta V:U in 8.8:8.8
1305         mov     eax, Tmap.fx_dv_dx
1306         shr     eax, 8
1307         mov     edx, Tmap.fx_du_dx
1308         shl     edx, 8
1309         mov     dx, ax
1310
1311         // Need EDI = pointer to dest row
1312         mov     edi, Tmap.dest_row_data
1313
1314         // Need ESI = pointer to texture
1315         mov     esi, Tmap.pixptr        
1316
1317         // Set up loop counter
1318         mov     ebp, Tmap.loop_count
1319
1320         shr     ebp, 2
1321         je              DoLeftOverPixels
1322
1323         mov     Tmap.num_big_steps, ebp
1324         and     Tmap.loop_count, 3
1325
1326         // EAX = anything (used as tmp in loop)
1327         // EBX = 
1328         // ECX = V.VF:U.UF in 8.8:8.8
1329         // EDX = delta V:U in 8.8:8.8
1330         // ESP = stack pointer (could be saved to Tmap.saved_esp and then used if needed)
1331         // EBP = loop counter
1332         // EDI = pointer to dest row
1333         // ESI = pointer to texture
1334
1335 NextPixelBlock:
1336
1337                 // Draw 4 pixels
1338                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1339                 add     ecx, edx                                                        // Increment u&v
1340                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1341                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1342                 and     eax, 0ffffh                                             // clear upper bits
1343                 mov     al, [eax+esi]                                   // Get pixel from texture
1344                 mov     [edi+0], al                                             // Write pixel to screen
1345
1346                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1347                 add     ecx, edx                                                        // Increment u&v
1348                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1349                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1350                 and     eax, 0ffffh                                             // clear upper bits
1351                 mov     al, [eax+esi]                                   // Get pixel from texture
1352                 mov     [edi+1], al                                             // Write pixel to screen
1353
1354                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1355                 add     ecx, edx                                                        // Increment u&v
1356                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1357                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1358                 and     eax, 0ffffh                                             // clear upper bits
1359                 mov     al, [eax+esi]                                   // Get pixel from texture
1360                 mov     [edi+2], al                                             // Write pixel to screen
1361
1362                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1363                 add     ecx, edx                                                        // Increment u&v
1364                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1365                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1366                 and     eax, 0ffffh                                             // clear upper bits
1367                 mov     al, [eax+esi]                                   // Get pixel from texture
1368                 mov     [edi+3], al                                             // Write pixel to screen
1369
1370
1371         add     edi, 4
1372         dec     Tmap.num_big_steps
1373         jne     NextPixelBlock
1374         
1375
1376 DoLeftOverPixels:
1377
1378         mov     ebp,Tmap.loop_count
1379         test    ebp, -1
1380         jz              _none_to_do
1381         mov     Tmap.loop_count, ebp
1382
1383 NextPixel:
1384         // Draw one pixel
1385         mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1386         add     ecx, edx                                                        // Increment u&v
1387         shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1388         rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1389         and     eax, 0ffffh                                             // clear upper bits
1390         mov     al, [eax+esi]                                   // Get pixel from texture
1391         mov     [edi], al                                               // Write pixel to screen
1392
1393         add     edi, 1
1394         dec     Tmap.loop_count
1395         jne     NextPixel
1396
1397 _none_to_do:    
1398         pop     edi
1399         pop     esi
1400         pop     ebp
1401         pop     ebx
1402         pop     edx
1403         pop     ecx
1404         pop     eax
1405         }
1406 #endif
1407 }
1408
1409
1410 int Rand_value = 1;
1411
1412 // used only for subpsace effect
1413
1414 #define MASK 0x00ff00ff
1415 //#define MASK 0x0
1416
1417 // not used, but cool
1418 void tmapscan_pnn8_tiled_256x256_subspace_dithered()
1419 {
1420         if ( Tmap.src_offset != 256 )   {
1421                 Int3();         // This only works on 256 wide textures!
1422                 return;
1423         }
1424
1425 #ifdef PLAT_UNIX
1426         STUB_FUNCTION;
1427 #else
1428         _asm {
1429         
1430         push    eax
1431         push    ecx
1432         push    edx
1433         push    ebx
1434         push    ebp
1435         push    esi
1436         push    edi
1437
1438         mov     ebx, Rand_value
1439
1440         // Need EDI = pointer to dest row
1441         mov     edi, Tmap.dest_row_data
1442
1443         // Need ESI = pointer to texture
1444         mov     esi, Tmap.pixptr        
1445
1446
1447         // Put the FPU in low precision mode
1448         fstcw           Tmap.OldFPUCW                                   // store copy of CW
1449         mov             ax,Tmap.OldFPUCW                                // get it in ax
1450         and             eax, ~0x300L
1451         mov             Tmap.FPUCW,ax                                   // store it
1452         fldcw           Tmap.FPUCW                                              // load the FPU
1453
1454         mov             ecx, Tmap.loop_count            // ecx = width
1455
1456         // edi = pointer to start pixel in dest dib
1457         // ecx = spanwidth
1458
1459         mov             eax,ecx                                                 // eax and ecx = width
1460         shr             ecx,5                                                           // ecx = width / subdivision length
1461         and             eax,31                                                          // eax = width mod subdivision length
1462         jnz             some_left_over                                  // any leftover?
1463         dec             ecx                                                             // no, so special case last span
1464         mov             eax,32                                                          // it's 8 pixels long
1465 some_left_over:
1466         mov             Tmap.Subdivisions,ecx           // store widths
1467         mov             Tmap.WidthModLength,eax
1468
1469         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
1470                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
1471         fld             Tmap.l.v                                        // V/ZL 
1472         fld             Tmap.l.u                                        // U/ZL V/ZL 
1473         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
1474         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
1475         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
1476         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
1477         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
1478         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
1479         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
1480
1481         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
1482         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
1483
1484         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
1485
1486         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
1487         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
1488         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
1489         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
1490         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
1491
1492         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
1493
1494         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
1495         // @todo overlap this guy
1496         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
1497         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1498         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1499         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1500         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1501
1502         cmp             ecx,0                                                   // check for any full spans
1503         jle      HandleLeftoverPixels
1504     
1505 SpanLoop:
1506
1507         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
1508                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1509
1510         // convert left side coords
1511
1512         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
1513         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
1514         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
1515
1516         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
1517         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
1518         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
1519
1520         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1521
1522         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
1523         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
1524         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
1525         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
1526
1527         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
1528         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
1529
1530         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
1531         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
1532         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
1533
1534         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
1535         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
1536
1537         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
1538         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
1539         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
1540         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
1541         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
1542         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
1543         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
1544
1545
1546         // setup delta values
1547         // set up affine registers
1548
1549         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
1550         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
1551         // This divide should happen while the pixel span is drawn.
1552         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
1553
1554
1555         // 8 pixel span code
1556         // edi = dest dib bits at current pixel
1557         // esi = texture pointer at current u,v
1558         // eax = scratch
1559         // ebx = u fraction 0.32
1560         // ecx = v fraction 0.32
1561         // edx = u frac step
1562         // ebp = v carry scratch
1563
1564         mov     al,[edi]                                                                // preread the destination cache line
1565
1566         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
1567
1568 // Make EDX =  DV:DU in 8:8,8:8 format
1569         mov     eax, Tmap.DeltaV
1570         shr     eax, 8
1571         mov     edx, Tmap.DeltaU
1572         shl     edx, 8
1573         mov     dx, ax
1574                 
1575 // Make ECX = V:U in 8:8,8:8 format
1576         mov     eax, Tmap.VFixed
1577         shr     eax, 8
1578         mov     ecx, Tmap.UFixed
1579         shl     ecx, 8
1580         mov     cx, ax
1581
1582         // eax = tmp
1583         // ebx = 
1584         // ecx = V:U in 8.8:8.8
1585         // edx = zbuffer pointer
1586         // esi = 
1587         // edi = screen data
1588         // ebp = dl_dx
1589
1590
1591 InnerInnerLoop:
1592
1593                 // pixel 0
1594 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1595                 mov eax, ebx
1596                 shr eax, 1
1597                 jnc L1
1598                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1599 L1:     mov ebx, eax
1600                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1601                 add eax, ecx
1602                 add     ecx, edx
1603                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1604                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1605                 and     eax, 0ffffh                                             // clear upper bits
1606
1607                 mov     al, [esi+eax]                   
1608                 mov     [edi+0], al
1609
1610                 // pixel 1
1611 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1612                 mov eax, ebx
1613                 shr eax, 1
1614                 jnc L2
1615                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1616 L2:     mov ebx, eax
1617                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1618                 add eax, ecx
1619                 add     ecx, edx
1620                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1621                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1622                 and     eax, 0ffffh                                             // clear upper bits
1623
1624                 mov     al, [esi+eax]                   
1625                 mov     [edi+1], al
1626
1627                 // pixel 2
1628 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1629                 mov eax, ebx
1630                 shr eax, 1
1631                 jnc L3
1632                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1633 L3:     mov ebx, eax
1634                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1635                 add eax, ecx
1636                 add     ecx, edx
1637                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1638                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1639                 and     eax, 0ffffh                                             // clear upper bits
1640
1641                 mov     al, [esi+eax]                   
1642                 mov     [edi+2], al
1643
1644                 // pixel 3
1645 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1646                 mov eax, ebx
1647                 shr eax, 1
1648                 jnc L4
1649                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1650 L4:     mov ebx, eax
1651                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1652                 add eax, ecx
1653                 add     ecx, edx
1654                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1655                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1656                 and     eax, 0ffffh                                             // clear upper bits
1657
1658                 mov     al, [esi+eax]                   
1659                 mov     [edi+3], al
1660
1661
1662         add     edi, 4
1663         dec     Tmap.InnerLooper
1664         jnz     InnerInnerLoop
1665
1666         mov     Tmap.fx_w, esi
1667
1668         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
1669                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
1670
1671     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1672     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1673     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1674     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1675
1676     dec     Tmap.Subdivisions                   // decrement span count
1677     jnz     SpanLoop                                                    // loop back
1678
1679
1680 HandleLeftoverPixels:
1681
1682     // edi = dest dib bits
1683     // esi = current texture dib bits
1684     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
1685     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
1686
1687     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1688     jz      FPUReturn                   ; nope, pop the FPU and bail
1689
1690     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1691
1692     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
1693     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
1694     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
1695
1696     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
1697     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
1698     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
1699
1700     dec     Tmap.WidthModLength            ; calc how many steps to take
1701     jz      OnePixelSpan                ; just one, don't do deltas'
1702
1703     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1704     // r -> R+1
1705
1706     // @todo rearrange things so we don't need these two instructions
1707     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
1708     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
1709
1710     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
1711     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
1712     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
1713     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
1714     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
1715     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
1716
1717     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1718
1719     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
1720     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
1721
1722     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1723
1724     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
1725     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
1726     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
1727     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
1728
1729     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
1730     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
1731     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
1732
1733     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
1734     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
1735     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
1736     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
1737
1738     // @todo gross!  these are to line up with the other loop
1739     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
1740     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
1741
1742
1743 OnePixelSpan:
1744
1745 // Make EDX =  DV:DU in 8:8,8:8 format
1746         mov     eax, Tmap.DeltaV
1747         shr     eax, 8
1748         mov     edx, Tmap.DeltaU
1749         shl     edx, 8
1750         mov     dx, ax
1751                 
1752 // Make ECX = V:U in 8:8,8:8 format
1753         mov     eax, Tmap.VFixed
1754         shr     eax, 8
1755         mov     ecx, Tmap.UFixed
1756         shl     ecx, 8
1757         mov     cx, ax
1758
1759         inc     Tmap.WidthModLength
1760         mov     eax,Tmap.WidthModLength
1761         shr     eax, 1
1762         jz              one_more_pix
1763         pushf
1764         mov     Tmap.WidthModLength, eax
1765
1766         // eax = tmp
1767         // ebx = light
1768         // ecx = V:U in 8.8:8.8
1769         // edx = zbuffer pointer
1770         // esi = z
1771         // edi = screen data
1772         // ebp = dl_dx
1773
1774
1775 NextPixel:
1776                 // pixel 0
1777 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1778                 mov eax, ebx
1779                 shr eax, 1
1780                 jnc L5
1781                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1782 L5:     mov ebx, eax
1783                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1784                 add eax, ecx
1785                 add     ecx, edx
1786                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1787                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1788                 and     eax, 0ffffh                                             // clear upper bits
1789
1790                 mov     al, [esi+eax]                   
1791                 mov     [edi+0], al
1792
1793                 // pixel 1
1794 //              mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1795                 mov eax, ebx
1796                 shr eax, 1
1797                 jnc L6
1798                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1799 L6:     mov ebx, eax
1800                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1801                 add eax, ecx
1802                 add     ecx, edx
1803                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1804                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1805                 and     eax, 0ffffh                                             // clear upper bits
1806
1807                 mov     al, [esi+eax]                   
1808                 mov     [edi+1], al
1809
1810
1811         add     edi, 2
1812         dec     Tmap.WidthModLength
1813         jg              NextPixel
1814
1815         popf
1816         jnc     FPUReturn
1817
1818 one_more_pix:   
1819                 // pixel 0
1820                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
1821                 mov eax, ebx
1822                 shr eax, 1
1823                 jnc L7
1824                 xor eax, 0xA3000000 ; This makes 'r' take 2^32 iterations to repeat
1825 L7:     mov ebx, eax
1826                 and eax, MASK ; mask out all bits except 8.8:8.8 fraction
1827                 add eax, ecx
1828                 add     ecx, edx
1829                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
1830                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
1831                 and     eax, 0ffffh                                             // clear upper bits
1832
1833                 mov     al, [esi+eax]                   
1834                 mov     [edi+0], al
1835
1836 FPUReturn:
1837
1838         mov     Rand_value, ebx
1839
1840         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1841                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1842         ffree   st(0)
1843         ffree   st(1)
1844         ffree   st(2)
1845         ffree   st(3)
1846         ffree   st(4)
1847         ffree   st(5)
1848         ffree   st(6)
1849
1850         fldcw   Tmap.OldFPUCW                  // restore the FPU
1851
1852         pop     edi
1853         pop     esi
1854         pop     ebp
1855         pop     ebx
1856         pop     edx
1857         pop     ecx
1858         pop     eax
1859         }
1860 #endif
1861 }
1862
1863
1864 void tmapscan_pnn8_tiled_256x256_subspace()
1865 {
1866         if ( Tmap.src_offset != 256 )   {
1867                 Int3();         // This only works on 256 wide textures!
1868                 return;
1869         }
1870
1871 #ifdef PLAT_UNIX
1872         STUB_FUNCTION;
1873 #else
1874         _asm {
1875         
1876         push    eax
1877         push    ecx
1878         push    edx
1879         push    ebx
1880         push    ebp
1881         push    esi
1882         push    edi
1883
1884         // Need EDI = pointer to dest row
1885         mov     edi, Tmap.dest_row_data
1886
1887         // Need ESI = pointer to texture
1888         mov     esi, Tmap.pixptr        
1889
1890
1891         // Put the FPU in low precision mode
1892         fstcw           Tmap.OldFPUCW                                   // store copy of CW
1893         mov             ax,Tmap.OldFPUCW                                // get it in ax
1894         and             eax, ~0x300L
1895         mov             Tmap.FPUCW,ax                                   // store it
1896         fldcw           Tmap.FPUCW                                              // load the FPU
1897
1898         mov             ecx, Tmap.loop_count            // ecx = width
1899
1900         // edi = pointer to start pixel in dest dib
1901         // ecx = spanwidth
1902
1903         mov             eax,ecx                                                 // eax and ecx = width
1904         shr             ecx,5                                                           // ecx = width / subdivision length
1905         and             eax,31                                                          // eax = width mod subdivision length
1906         jnz             some_left_over                                  // any leftover?
1907         dec             ecx                                                             // no, so special case last span
1908         mov             eax,32                                                          // it's 8 pixels long
1909 some_left_over:
1910         mov             Tmap.Subdivisions,ecx           // store widths
1911         mov             Tmap.WidthModLength,eax
1912
1913         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
1914                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
1915         fld             Tmap.l.v                                        // V/ZL 
1916         fld             Tmap.l.u                                        // U/ZL V/ZL 
1917         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
1918         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
1919         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
1920         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
1921         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
1922         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
1923         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
1924
1925         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
1926         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
1927
1928         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
1929
1930         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
1931         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
1932         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
1933         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
1934         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
1935
1936         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
1937
1938         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
1939         // @todo overlap this guy
1940         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
1941         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1942         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1943         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1944         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1945
1946         cmp             ecx,0                                                   // check for any full spans
1947         jle      HandleLeftoverPixels
1948     
1949 SpanLoop:
1950
1951         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
1952                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1953
1954         // convert left side coords
1955
1956         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
1957         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
1958         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
1959
1960         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
1961         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
1962         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
1963
1964         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1965
1966         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
1967         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
1968         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
1969         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
1970
1971         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
1972         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
1973
1974         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
1975         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
1976         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
1977
1978         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
1979         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
1980
1981         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
1982         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
1983         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
1984         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
1985         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
1986         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
1987         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
1988
1989
1990         // setup delta values
1991         // set up affine registers
1992
1993         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
1994         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
1995         // This divide should happen while the pixel span is drawn.
1996         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
1997
1998
1999         // 8 pixel span code
2000         // edi = dest dib bits at current pixel
2001         // esi = texture pointer at current u,v
2002         // eax = scratch
2003         // ebx = u fraction 0.32
2004         // ecx = v fraction 0.32
2005         // edx = u frac step
2006         // ebp = v carry scratch
2007
2008         mov     al,[edi]                                                                // preread the destination cache line
2009
2010         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
2011
2012 // Make EDX =  DV:DU in 8:8,8:8 format
2013         mov     eax, Tmap.DeltaV
2014         shr     eax, 8
2015         mov     edx, Tmap.DeltaU
2016         shl     edx, 8
2017         mov     dx, ax
2018                 
2019 // Make ECX = V:U in 8:8,8:8 format
2020         mov     eax, Tmap.VFixed
2021         shr     eax, 8
2022         mov     ecx, Tmap.UFixed
2023         shl     ecx, 8
2024         mov     cx, ax
2025
2026         // eax = tmp
2027         // ebx = 
2028         // ecx = V:U in 8.8:8.8
2029         // edx = zbuffer pointer
2030         // esi = 
2031         // edi = screen data
2032         // ebp = dl_dx
2033
2034
2035 InnerInnerLoop:
2036
2037                 // pixel 0
2038                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2039                 add     ecx, edx
2040                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2041                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2042                 and     eax, 0ffffh                                             // clear upper bits
2043
2044                 mov     al, [esi+eax]                   
2045                 mov     [edi+0], al
2046
2047                 // pixel 1
2048                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2049                 add     ecx, edx
2050                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2051                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2052                 and     eax, 0ffffh                                             // clear upper bits
2053
2054                 mov     al, [esi+eax]                   
2055                 mov     [edi+1], al
2056
2057                 // pixel 2
2058                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2059                 add     ecx, edx
2060                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2061                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2062                 and     eax, 0ffffh                                             // clear upper bits
2063
2064                 mov     al, [esi+eax]                   
2065                 mov     [edi+2], al
2066
2067                 // pixel 3
2068                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2069                 add     ecx, edx
2070                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2071                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2072                 and     eax, 0ffffh                                             // clear upper bits
2073
2074                 mov     al, [esi+eax]                   
2075                 mov     [edi+3], al
2076
2077
2078         add     edi, 4
2079         dec     Tmap.InnerLooper
2080         jnz     InnerInnerLoop
2081
2082         mov     Tmap.fx_w, esi
2083
2084         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
2085                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
2086
2087     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
2088     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
2089     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
2090     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
2091
2092     dec     Tmap.Subdivisions                   // decrement span count
2093     jnz     SpanLoop                                                    // loop back
2094
2095
2096 HandleLeftoverPixels:
2097
2098     // edi = dest dib bits
2099     // esi = current texture dib bits
2100     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
2101     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
2102
2103     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
2104     jz      FPUReturn                   ; nope, pop the FPU and bail
2105
2106     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
2107
2108     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
2109     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
2110     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
2111
2112     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
2113     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
2114     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
2115
2116     dec     Tmap.WidthModLength            ; calc how many steps to take
2117     jz      OnePixelSpan                ; just one, don't do deltas'
2118
2119     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
2120     // r -> R+1
2121
2122     // @todo rearrange things so we don't need these two instructions
2123     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
2124     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
2125
2126     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
2127     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
2128     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
2129     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
2130     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
2131     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
2132
2133     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
2134
2135     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
2136     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
2137
2138     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
2139
2140     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
2141     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
2142     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
2143     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
2144
2145     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
2146     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
2147     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
2148
2149     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
2150     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
2151     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
2152     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
2153
2154     // @todo gross!  these are to line up with the other loop
2155     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
2156     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
2157
2158
2159 OnePixelSpan:
2160
2161 // Make EDX =  DV:DU in 8:8,8:8 format
2162         mov     eax, Tmap.DeltaV
2163         shr     eax, 8
2164         mov     edx, Tmap.DeltaU
2165         shl     edx, 8
2166         mov     dx, ax
2167                 
2168 // Make ECX = V:U in 8:8,8:8 format
2169         mov     eax, Tmap.VFixed
2170         shr     eax, 8
2171         mov     ecx, Tmap.UFixed
2172         shl     ecx, 8
2173         mov     cx, ax
2174
2175         inc     Tmap.WidthModLength
2176         mov     eax,Tmap.WidthModLength
2177         shr     eax, 1
2178         jz              one_more_pix
2179         pushf
2180         mov     Tmap.WidthModLength, eax
2181
2182         // eax = tmp
2183         // ebx = light
2184         // ecx = V:U in 8.8:8.8
2185         // edx = zbuffer pointer
2186         // esi = z
2187         // edi = screen data
2188         // ebp = dl_dx
2189
2190
2191 NextPixel:
2192                 // pixel 0
2193                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2194                 add     ecx, edx
2195                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2196                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2197                 and     eax, 0ffffh                                             // clear upper bits
2198
2199                 mov     al, [esi+eax]                   
2200                 mov     [edi+0], al
2201
2202                 // pixel 1
2203                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2204                 add     ecx, edx
2205                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2206                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2207                 and     eax, 0ffffh                                             // clear upper bits
2208
2209                 mov     al, [esi+eax]                   
2210                 mov     [edi+1], al
2211
2212
2213         add     edi, 2
2214         dec     Tmap.WidthModLength
2215         jg              NextPixel
2216
2217         popf
2218         jnc     FPUReturn
2219
2220 one_more_pix:   
2221                 // pixel 0
2222                 mov     eax, ecx                                                        // EAX = V.VF:U.UF in 8.8:8.8
2223                 add     ecx, edx
2224                 shr     ax, 8                                                           // EAX = V:U in 8.8:8.0
2225                 rol     eax, 8                                                  // EAX = V:U in 0.0:8:8
2226                 and     eax, 0ffffh                                             // clear upper bits
2227
2228                 mov     al, [esi+eax]                   
2229                 mov     [edi+0], al
2230
2231 FPUReturn:
2232
2233         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
2234                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
2235         ffree   st(0)
2236         ffree   st(1)
2237         ffree   st(2)
2238         ffree   st(3)
2239         ffree   st(4)
2240         ffree   st(5)
2241         ffree   st(6)
2242
2243         fldcw   Tmap.OldFPUCW                  // restore the FPU
2244
2245         pop     edi
2246         pop     esi
2247         pop     ebp
2248         pop     ebx
2249         pop     edx
2250         pop     ecx
2251         pop     eax
2252         }
2253 #endif
2254 }
2255
2256