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