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