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