]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/tmapscanline.cpp
BGRA
[taylor/freespace2.git] / src / graphics / tmapscanline.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/TmapScanline.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Routines to draw one textured mapped scanline.
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 5     12/02/98 5:47p Dave
15  * Put in interface xstr code. Converted barracks screen to new format.
16  * 
17  * 4     11/30/98 5:31p Dave
18  * Fixed up Fred support for software mode.
19  * 
20  * 3     11/30/98 1:07p Dave
21  * 16 bit conversion, first run.
22  * 
23  * 2     10/07/98 10:53a Dave
24  * Initial checkin.
25  * 
26  * 1     10/07/98 10:49a Dave
27  * 
28  * 21    4/20/98 4:44p John
29  * Fixed problems with black being xparent on model cache rneders.  Made
30  * model cache key off of detail level setting and framerate.
31  * 
32  * 20    4/09/98 7:58p John
33  * Cleaned up tmapper code a bit.   Put NDEBUG around some ndebug stuff.
34  * Took out XPARENT flag settings in all the alpha-blended texture stuff.
35  * 
36  * 19    3/22/98 2:33p John
37  * Took out fx_v/v_right.  Made fx_u etc get calculated in tmapper.
38  * 
39  * 18    3/10/98 4:19p John
40  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
41  * & Glide have popups and print screen.  Took out all >8bpp software
42  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
43  * support Fred.  Made zbuffering key off of functions rather than one
44  * global variable.
45  * 
46  * 17    12/10/96 10:37a John
47  * Restructured texture mapper to remove some overhead from each scanline
48  * setup.  This gave about a 30% improvement drawing trans01.pof, which is
49  * a really complex model.  In the process, I cleaned up the scanline
50  * functions and separated them into different modules for each pixel
51  * depth.   
52  * 
53  * 16    12/02/96 4:03p John
54  * made texture divide pipeline better. 2.5% speedup.
55  * 
56  * 15    11/26/96 6:50p John
57  * Added some more hicolor primitives.  Made windowed mode run as current
58  * bpp, if bpp is 8,16,or 32.
59  * 
60  * 14    11/18/96 9:58a John
61  * Fixed warnings
62  * 
63  * 13    11/07/96 6:19p John
64  * Added a bunch of 16bpp primitives so the game sort of runs in 16bpp
65  * mode.
66  * 
67  * 12    11/07/96 3:49p John
68  * Fixed some old 'c' inner loop code for testing.
69  * 
70  * 11    11/07/96 2:17p John
71  * Took out the OldTmapper stuff.
72  * 
73  * 10    11/05/96 4:05p John
74  * Added roller.  Added code to draw a distant planet.  Made bm_load
75  * return -1 if invalid bitmap.
76  * 
77  * 9     10/31/96 7:20p John
78  * Added per,tiled tmapper.  Made models tile if they use 64x64 textures.
79  * 
80  * 8     10/26/96 1:40p John
81  * Added some now primitives to the 2d library and
82  * cleaned up some old ones.
83  *
84  * $NoKeywords: $
85  */
86
87 #include "3d.h"
88 #include "2d.h"
89 #include "grinternal.h"
90 #include "tmapper.h"
91 #include "tmapscanline.h"
92 #include "floating.h"
93 #include "palman.h"
94 #include "fix.h"
95 #include "key.h"
96
97 // Needed to keep warning 4725 to stay away.  See PsTypes.h for details why.
98 void disable_warning_4725_stub_ts32()
99 {
100 }
101
102
103 extern void tmapscan_pln8_tiled_256x256();
104 extern void tmapscan_pln8_tiled_128x128();
105 extern void tmapscan_pln8_tiled_64x64();
106 extern void tmapscan_pln8_tiled_32x32();
107 extern void tmapscan_pln8_tiled_16x16();
108
109
110 void tmapscan_pln8_tiled()
111 {
112         if ( (Tmap.bp->w == 256) && (Tmap.bp->h == 256) )       {
113                 tmapscan_pln8_tiled_256x256();
114         } else if ( (Tmap.bp->w == 128) && (Tmap.bp->h == 128) )        {
115                 tmapscan_pln8_tiled_128x128();
116         } else if ( (Tmap.bp->w == 64) && (Tmap.bp->h == 64) )  {
117                 tmapscan_pln8_tiled_64x64();
118         } else if ( (Tmap.bp->w == 32) && (Tmap.bp->h == 32) )  {
119                 tmapscan_pln8_tiled_32x32();
120         } else if ( (Tmap.bp->w == 16) && (Tmap.bp->h == 16) )  {
121                 tmapscan_pln8_tiled_16x16();
122         } else {
123                 // argh! write another texure mapper!
124                 tmapscan_pln8();
125         }
126 }
127
128
129 void tmapscan_write_z()
130 {
131         int i;
132         ubyte * dptr;
133         uint w, dw;
134         
135         dptr = (ubyte *)Tmap.dest_row_data;
136
137         w = Tmap.fx_w;
138         dw = Tmap.fx_dwdx;
139
140         uint *zbuf = (uint *)&gr_zbuffer[(uint)dptr-(uint)Tmap.pScreenBits];
141         
142         for (i=0; i<Tmap.loop_count; i++ )      {
143                 *zbuf = w;
144                 zbuf++;
145                 w += dw;
146         }
147 }
148
149
150 void tmapscan_flat_gouraud_zbuffered()
151 {
152         int i;
153         ubyte * dptr,c;
154         fix l, dl;
155         uint w, dw;
156         
157         dptr = (ubyte *)Tmap.dest_row_data;
158         c = gr_screen.current_color.raw8;
159
160         w = Tmap.fx_w;
161         dw = Tmap.fx_dwdx;
162
163         l = Tmap.fx_l;
164         dl = Tmap.fx_dl_dx;
165
166         uint *zbuf = (uint *)&gr_zbuffer[(uint)dptr-(uint)Tmap.pScreenBits];
167         
168         for (i=0; i<Tmap.loop_count; i++ )      {
169                 if ( w > *zbuf )        {
170                         *zbuf = w;
171                         *dptr = gr_fade_table[(f2i(l)<<8)+c];
172                 }
173                 zbuf++;
174                 w += dw;
175                 l+=dl;
176                 dptr++;
177         }
178 }
179
180 // ADAM: Change Nebula colors here:
181 #define NEBULA_COLORS 20
182
183 void tmapscan_nebula8()
184 {
185         ubyte * dptr;
186         int l1,l2, dldx;
187         
188         dptr = (ubyte *)Tmap.dest_row_data;
189
190         float max_neb_color = i2fl(NEBULA_COLORS-1);
191
192         l1 = (int)(Tmap.l.b*max_neb_color*256.0f);
193         l2 = l1 + 256/2;                // dithering
194         dldx = (int)(Tmap.deltas.b*max_neb_color*2.0f*256.0f);
195
196                 #ifdef USE_INLINE_ASM
197 //                      memset( dptr, 31, Tmap.loop_count );
198 #ifdef PLAT_UNIX
199         STUB_FUNCTION;
200 #else
201                         _asm    push    eax
202                         _asm    push    ebx
203                         _asm    push    ecx
204                         _asm    push    edx
205                         _asm    push    edi
206
207                         // eax - l1
208                         // ebx - l2
209                         // ecx - count
210                         // edx - dldx
211                         // edi - dest
212                         _asm    mov     eax, l1
213                         _asm    mov     ebx, l2
214                         _asm    mov     edx, dldx
215                         _asm    mov     edi, dptr
216                 
217                         _asm    mov     ecx, Tmap.loop_count
218                         _asm    shr     ecx, 1
219                         _asm    jz              DoFinal
220                         _asm    pushf
221
222                 Next2Pixels:
223                         _asm    mov     [edi], ah
224                         _asm    add     eax, edx
225
226                         _asm    mov     [edi+1], bh
227                         _asm    add     ebx, edx
228                         
229                         _asm    add     edi, 2
230                         _asm    dec     ecx
231                         _asm    jnz     Next2Pixels
232
233                         _asm    popf
234                 DoFinal:
235                         _asm    jnc     NotDoFinal
236                         _asm    mov     [edi], ah
237                 NotDoFinal:
238
239                         _asm    pop     edi
240                         _asm    pop     edx
241                         _asm    pop     ecx
242                         _asm    pop     ebx
243                         _asm    pop     eax
244 #endif
245
246                 #else
247                         int i;
248                         if ( Tmap.loop_count > 1 )      {
249                                 for (i=0; i<Tmap.loop_count/2; i++ )    {
250                                         dptr[0] = (ubyte)((l1&0xFF00)>>8);
251                                         l1+=dldx;
252                                         dptr[1] = (ubyte)((l2&0xFF00)>>8);
253                                         l2+=dldx;
254                                         dptr+=2;
255                                 }
256                         }
257                         if ( Tmap.loop_count & 1 )      {
258                                 dptr[0] = (ubyte)((l1&0xFF00)>>8);
259                                 dptr++;
260                         }
261                 #endif
262 }
263
264
265 void tmapscan_flat_gouraud()
266 {
267         if (gr_zbuffering) {
268                 switch(gr_zbuffering_mode)      {
269                 case GR_ZBUFF_NONE:
270                         break;
271                 case GR_ZBUFF_FULL:             // both
272                         tmapscan_flat_gouraud_zbuffered();
273                         return;
274                 case GR_ZBUFF_WRITE:            // write only
275                         tmapscan_flat_gouraud_zbuffered();
276                         break;
277                 case GR_ZBUFF_READ:             // read only
278                         tmapscan_flat_gouraud_zbuffered();
279                         return;
280                 }
281         }
282
283         /* HARDWARE_ONLY
284         if ( Current_alphacolor )       {
285                 ubyte *lookup = &Current_alphacolor->table.lookup[0][0];
286
287                 int i;
288                 ubyte * dptr;
289                 fix l, dl;
290                 
291                 dptr = (ubyte *)Tmap.dest_row_data;
292
293                 l = Tmap.fx_l;
294                 dl = Tmap.fx_dl_dx;
295                 
296                 for (i=0; i<Tmap.loop_count; i++ )      {
297                         *dptr = lookup[f2i(l*16)*256+*dptr];
298                         l+=dl;
299                         dptr++;
300                 }
301
302         } else {
303         */
304                 int i;
305                 ubyte * dptr,c;
306                 fix l, dl;
307                 
308                 dptr = (ubyte *)Tmap.dest_row_data;
309                 c = gr_screen.current_color.raw8;
310
311                 l = Tmap.fx_l;
312                 dl = Tmap.fx_dl_dx;
313                 
314                 for (i=0; i<Tmap.loop_count; i++ )      {
315                         *dptr = gr_fade_table[f2i(l*32)*256+c];
316                         l+=dl;
317                         dptr++;
318                 }       
319 }
320
321
322 void tmapscan_flat8_zbuffered()
323 {
324         int i;
325         ubyte * dptr,c;
326
327         dptr = (ubyte *)Tmap.dest_row_data;
328         c = gr_screen.current_color.raw8;
329
330
331         for (i=0; i<Tmap.loop_count; i++ )      {
332                 int tmp = (uint)dptr-Tmap.pScreenBits;
333                 if ( Tmap.fx_w > (int)gr_zbuffer[tmp] ) {
334                         gr_zbuffer[tmp] = Tmap.fx_w;
335                         *dptr = c;
336                 }
337                 Tmap.fx_w += Tmap.fx_dwdx;
338                 dptr++;
339         }
340 }
341
342 void tmapscan_flat8()
343 {
344         if (gr_zbuffering) {
345                 switch(gr_zbuffering_mode)      {
346                 case GR_ZBUFF_NONE:
347                         break;
348                 case GR_ZBUFF_FULL:             // both
349                         tmapscan_flat8_zbuffered();
350                         return;
351                 case GR_ZBUFF_WRITE:            // write only
352                         tmapscan_write_z();
353                         break;
354                 case GR_ZBUFF_READ:             // read only
355                         tmapscan_flat8_zbuffered();
356                         return;
357                 }
358         }
359
360         memset( (ubyte *)Tmap.dest_row_data, gr_screen.current_color.raw8, Tmap.loop_count );
361 }
362
363 void tmapscan_pln8_zbuffered();
364
365
366 void tmapscan_pln8_ppro()
367 {
368 #ifdef PLAT_UNIX
369         STUB_FUNCTION;
370 #else
371         _asm {
372         
373         push    eax
374         push    ecx
375         push    edx
376         push    ebx
377         push    ebp
378         push    esi
379         push    edi
380
381         // Put the FPU in low precision mode
382         fstcw           Tmap.OldFPUCW                                   // store copy of CW
383         mov             ax,Tmap.OldFPUCW                                // get it in ax
384         and             eax, ~0x300L
385         mov             Tmap.FPUCW,ax                                   // store it
386         fldcw           Tmap.FPUCW                                              // load the FPU
387
388         mov             ecx, Tmap.loop_count            // ecx = width
389         mov             edi, Tmap.dest_row_data // edi = dest pointer
390
391         // edi = pointer to start pixel in dest dib
392         // ecx = spanwidth
393
394         mov             eax,ecx                                                 // eax and ecx = width
395         shr             ecx,5                                                           // ecx = width / subdivision length
396         and             eax,31                                                          // eax = width mod subdivision length
397         jnz             some_left_over                                  // any leftover?
398         dec             ecx                                                             // no, so special case last span
399         mov             eax,32                                                          // it's 8 pixels long
400 some_left_over:
401         mov             Tmap.Subdivisions,ecx           // store widths
402         mov             Tmap.WidthModLength,eax
403
404         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
405                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
406         fld             Tmap.l.v                                        // V/ZL 
407         fld             Tmap.l.u                                        // U/ZL V/ZL 
408         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
409         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
410         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
411         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
412         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
413         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
414         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
415
416         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
417         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
418
419         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
420
421         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
422         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
423         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
424         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
425         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
426
427         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
428
429         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
430         // @todo overlap this guy
431         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
432         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
433         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
434         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
435         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
436
437         cmp             ecx,0                                                   // check for any full spans
438         jle      HandleLeftoverPixels
439     
440 SpanLoop:
441
442         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
443                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
444
445         // convert left side coords
446
447         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
448         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
449         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
450
451         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
452         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
453         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
454
455         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
456
457         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
458         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
459         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
460         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
461
462         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
463         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
464
465         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
466         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
467         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
468
469         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
470         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
471
472         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
473         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
474         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
475         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
476         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
477         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
478         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
479
480
481         // setup delta values
482     
483         mov     eax,Tmap.DeltaV                         // get v 16.16 step
484         mov     ebx,eax                                                 // copy it
485         sar     eax,16                                                          // get v int step
486         shl     ebx,16                                                          // get v frac step
487         mov     Tmap.DeltaVFrac,ebx                     // store it
488         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
489
490         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
491         mov     ecx,ebx                                                 // copy it
492         sar     ebx,16                                                          // get u int step
493         shl     ecx,16                                                          // get u frac step
494         mov     Tmap.DeltaUFrac,ecx                     // store it
495         add     eax,ebx                                                 // calculate uint + vint step
496         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
497         add     eax,Tmap.src_offset                     // calculate whole step + v carry
498         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
499
500         // setup initial coordinates
501         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
502
503         mov     ebx,esi                                                 // copy it
504         sar     esi,16                                                          // get integer part
505         shl     ebx,16                                                          // get fractional part
506
507         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
508    
509         mov     edx,ecx                                                 // copy it
510         sar     edx,16                                                          // get integer part
511         shl     ecx,16                                                          // get fractional part
512         imul    edx,Tmap.src_offset                     // calc texture scanline address
513         add     esi,edx                                                 // calc texture offset
514         add     esi,Tmap.pixptr                         // calc address
515
516         // set up affine registers
517         mov     edx,Tmap.DeltaUFrac                     // get register copy
518
519         mov     eax, Tmap.fx_l
520         shr     eax, 8
521         mov     bx, ax
522
523         mov     ebp, Tmap.fx_dl_dx
524         shl     ebp, 5  //*32
525         add     Tmap.fx_l, ebp
526
527         mov     ebp, Tmap.fx_l
528         shr     ebp, 8
529         sub     bp, ax
530         shr     bp, 5
531
532         mov     dx, bp
533
534         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
535         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
536         // This divide should happen while the pixel span is drawn.
537         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
538
539
540         // 8 pixel span code
541         // edi = dest dib bits at current pixel
542         // esi = texture pointer at current u,v
543         // eax = scratch
544         // ebx = u fraction 0.32
545         // ecx = v fraction 0.32
546         // edx = u frac step
547         // ebp = v carry scratch
548
549         xor     eax, eax
550         mov     al,[edi]                                                                // preread the destination cache line
551         xor     eax, eax
552         mov     al,[esi]                                                                // get texture pixel 0
553
554         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
555
556 InnerInnerLoop:
557
558         push    ebx
559         and     ebx, 0ff00h
560         mov     eax, DWORD PTR gr_fade_table[eax+ebx]   // Get shaded pixel
561         pop     ebx
562         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
563         sbb     ebp,ebp                                                         // get -1 if carry
564         mov     [edi+0],al                                                      // store pixel
565         xor     eax, eax
566         mov     al,[esi]                                                                // get texture pixel
567         add     ebx,edx                                                         // increment u fraction
568         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
569
570         push    ebx
571         and     ebx, 0ff00h
572         mov     eax, DWORD PTR gr_fade_table[eax+ebx]   // Get shaded pixel
573         pop     ebx
574         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
575         sbb     ebp,ebp                                                         // get -1 if carry
576         mov     [edi+1],al                                                      // store pixel
577         xor     eax, eax
578         mov     al,[esi]                                                                // get texture pixel
579         add     ebx,edx                                                         // increment u fraction
580         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
581
582         push    ebx
583         and     ebx, 0ff00h
584         mov     eax, DWORD PTR gr_fade_table[eax+ebx]   // Get shaded pixel
585         pop     ebx
586         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
587         sbb     ebp,ebp                                                         // get -1 if carry
588         mov     [edi+2],al                                                      // store pixel
589         xor     eax, eax
590         mov     al,[esi]                                                                // get texture pixel
591         add     ebx,edx                                                         // increment u fraction
592         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
593
594         push    ebx
595         and     ebx, 0ff00h
596         mov     eax, DWORD PTR gr_fade_table[eax+ebx]   // Get shaded pixel
597         pop     ebx
598         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
599         sbb     ebp,ebp                                                         // get -1 if carry
600         mov     [edi+3],al                                                      // store pixel
601         xor     eax, eax
602         mov     al,[esi]                                                                // get texture pixel
603         add     ebx,edx                                                         // increment u fraction
604         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
605
606         add     edi, 4
607         dec     Tmap.InnerLooper
608         jnz     InnerInnerLoop
609
610         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
611                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
612
613     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
614     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
615     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
616     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
617
618     dec     Tmap.Subdivisions                   // decrement span count
619     jnz     SpanLoop                                                    // loop back
620
621
622 HandleLeftoverPixels:
623
624     mov     esi,Tmap.pixptr                             // load texture pointer
625
626     // edi = dest dib bits
627     // esi = current texture dib bits
628     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
629     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
630
631     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
632     jz      FPUReturn                   ; nope, pop the FPU and bail
633
634     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
635
636     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
637     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
638     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
639
640     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
641     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
642     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
643
644     dec     Tmap.WidthModLength            ; calc how many steps to take
645     jz      OnePixelSpan                ; just one, do not do deltas
646
647     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
648     // r -> R+1
649
650     // @todo rearrange things so we don't need these two instructions
651     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
652     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
653
654     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
655     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
656     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
657     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
658     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
659     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
660
661     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
662
663     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
664     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
665
666     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
667
668     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
669     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
670     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
671     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
672
673     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
674     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
675     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
676
677     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
678     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
679     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
680     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
681
682     // @todo gross!  these are to line up with the other loop
683     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
684     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
685
686
687         // setup delta values
688         mov     eax, Tmap.DeltaV        // get v 16.16 step
689         mov     ebx, eax                                                // copy it
690         sar     eax, 16                                         // get v int step
691         shl     ebx, 16                                         // get v frac step
692         mov     Tmap.DeltaVFrac, ebx    // store it
693         imul    eax, Tmap.src_offset    // calc texture step for v int step
694         
695         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
696         mov     ecx, ebx                                                // copy it
697         sar     ebx, 16                                         // get the u int step
698         shl     ecx, 16                                         // get the u frac step
699         mov     Tmap.DeltaUFrac, ecx                    // store it
700         add     eax, ebx                                                // calc uint + vint step
701         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
702         add     eax, Tmap.src_offset                            // calc whole step + v carry
703         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
704
705
706 OnePixelSpan:
707
708         ; setup initial coordinates
709         mov     esi, Tmap.UFixed                        // get u 16.16
710         mov     ebx, esi                                                // copy it
711         sar     esi, 16                                         // get integer part
712         shl     ebx, 16                                         // get fractional part
713
714         mov     ecx, Tmap.VFixed                        // get v 16.16 
715         mov     edx, ecx                                                // copy it
716         sar     edx, 16                                         // get integer part
717         shl     ecx, 16                                         // get fractional part
718         imul    edx, Tmap.src_offset            // calc texture scanline address
719         add     esi, edx                                                        // calc texture offset
720         add     esi, Tmap.pixptr                        // calc address
721
722
723         mov     eax, Tmap.fx_l
724         shr     eax, 8
725         mov     bx, ax
726
727         mov     edx, Tmap.DeltaUFrac
728
729         cmp     Tmap.WidthModLength, 1
730         jle     NoDeltaLight
731
732         push    ebx
733         
734         mov     ebx, Tmap.fx_l_right
735         shr     ebx, 8
736         
737         sub     ebx, eax
738         mov     eax, ebx
739         
740         mov     eax, Tmap.fx_dl_dx
741         shr     eax, 8
742
743         mov     dx, ax
744
745         pop     ebx
746
747 NoDeltaLight:
748
749         inc     Tmap.WidthModLength
750         mov     eax,Tmap.WidthModLength
751         shr     eax, 1
752         jz              one_more_pix
753         pushf
754         mov     Tmap.WidthModLength, eax
755
756         xor     eax, eax
757
758         mov     al,[edi]                    // preread the destination cache line
759         mov     al,[esi]
760
761 NextPixel:
762         mov     ah, bh                                                          // move lighting value into place
763         mov     al, gr_fade_table[eax]                  // Get shaded pixel
764         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
765         sbb     ebp,ebp                                                         // get -1 if carry
766         mov     [edi+0],al                                                      // store pixel
767         mov     al,[esi]                                                                // get texture pixel
768         add     ebx,edx                                                         // increment u fraction
769         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
770
771         mov     ah, bh                                                          // move lighting value into place
772         mov     al, gr_fade_table[eax]                  // Get shaded pixel
773         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
774         sbb     ebp,ebp                                                         // get -1 if carry
775         mov     [edi+1],al                                                      // store pixel
776         mov     al,[esi]                                                                // get texture pixel
777         add     ebx,edx                                                         // increment u fraction
778         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
779
780         add     edi, 2
781         dec     Tmap.WidthModLength
782         jg              NextPixel
783
784         popf
785         jnc     FPUReturn
786
787 one_more_pix:   
788
789         mov     al,[esi]                    // get texture pixel 2
790         mov     ah, bh
791         mov     al, gr_fade_table[eax]
792         mov     [edi],al                  // store pixel 2
793
794
795 FPUReturn:
796
797         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
798                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
799         ffree   st(0)
800         ffree   st(1)
801         ffree   st(2)
802         ffree   st(3)
803         ffree   st(4)
804         ffree   st(5)
805         ffree   st(6)
806
807         fldcw   Tmap.OldFPUCW                  // restore the FPU
808
809         pop     edi
810         pop     esi
811         pop     ebp
812         pop     ebx
813         pop     edx
814         pop     ecx
815         pop     eax
816         }
817 #endif
818 }
819
820
821 void tmapscan_pln8_pentium()
822 {
823 #ifdef PLAT_UNIX
824         STUB_FUNCTION;
825 #else
826         _asm {
827         
828         push    eax
829         push    ecx
830         push    edx
831         push    ebx
832         push    ebp
833         push    esi
834         push    edi
835
836         // Put the FPU in low precision mode
837         fstcw           Tmap.OldFPUCW                                   // store copy of CW
838         mov             ax,Tmap.OldFPUCW                                // get it in ax
839         and             eax, ~0x300L
840         mov             Tmap.FPUCW,ax                                   // store it
841         fldcw           Tmap.FPUCW                                              // load the FPU
842
843         mov             ecx, Tmap.loop_count            // ecx = width
844         mov             edi, Tmap.dest_row_data // edi = dest pointer
845
846         // edi = pointer to start pixel in dest dib
847         // ecx = spanwidth
848
849         mov             eax,ecx                                                 // eax and ecx = width
850         shr             ecx,5                                                           // ecx = width / subdivision length
851         and             eax,31                                                          // eax = width mod subdivision length
852         jnz             some_left_over                                  // any leftover?
853         dec             ecx                                                             // no, so special case last span
854         mov             eax,32                                                          // it's 8 pixels long
855 some_left_over:
856         mov             Tmap.Subdivisions,ecx           // store widths
857         mov             Tmap.WidthModLength,eax
858
859         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
860                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
861         fld             Tmap.l.v                                        // V/ZL 
862         fld             Tmap.l.u                                        // U/ZL V/ZL 
863         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
864         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
865         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
866         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
867         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
868         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
869         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
870
871         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
872         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
873
874         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
875
876         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
877         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
878         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
879         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
880         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
881
882         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
883
884         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
885         // @todo overlap this guy
886         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
887         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
888         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
889         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
890         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
891
892         cmp             ecx,0                                                   // check for any full spans
893         jle      HandleLeftoverPixels
894     
895 SpanLoop:
896
897         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
898                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
899
900         // convert left side coords
901
902         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
903         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
904         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
905
906         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
907         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
908         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
909
910         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
911
912         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
913         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
914         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
915         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
916
917         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
918         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
919
920         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
921         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
922         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
923
924         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
925         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
926
927         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
928         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
929         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
930         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
931         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
932         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
933         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
934
935
936         // setup delta values
937     
938         mov     eax,Tmap.DeltaV                         // get v 16.16 step
939         mov     ebx,eax                                                 // copy it
940         sar     eax,16                                                          // get v int step
941         shl     ebx,16                                                          // get v frac step
942         mov     Tmap.DeltaVFrac,ebx                     // store it
943         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
944
945         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
946         mov     ecx,ebx                                                 // copy it
947         sar     ebx,16                                                          // get u int step
948         shl     ecx,16                                                          // get u frac step
949         mov     Tmap.DeltaUFrac,ecx                     // store it
950         add     eax,ebx                                                 // calculate uint + vint step
951         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
952         add     eax,Tmap.src_offset                     // calculate whole step + v carry
953         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
954
955         // setup initial coordinates
956         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
957
958         mov     ebx,esi                                                 // copy it
959         sar     esi,16                                                          // get integer part
960         shl     ebx,16                                                          // get fractional part
961
962         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
963    
964         mov     edx,ecx                                                 // copy it
965         sar     edx,16                                                          // get integer part
966         shl     ecx,16                                                          // get fractional part
967         imul    edx,Tmap.src_offset                     // calc texture scanline address
968         add     esi,edx                                                 // calc texture offset
969         add     esi,Tmap.pixptr                         // calc address
970
971         // set up affine registers
972         mov     edx,Tmap.DeltaUFrac                     // get register copy
973
974         mov     eax, Tmap.fx_l
975         shr     eax, 8
976         mov     bx, ax
977
978         mov     ebp, Tmap.fx_dl_dx
979         shl     ebp, 5  //*32
980         add     Tmap.fx_l, ebp
981
982         mov     ebp, Tmap.fx_l
983         shr     ebp, 8
984         sub     bp, ax
985         shr     bp, 5
986
987         mov     dx, bp
988
989         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
990         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
991         // This divide should happen while the pixel span is drawn.
992         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
993
994
995         // 8 pixel span code
996         // edi = dest dib bits at current pixel
997         // esi = texture pointer at current u,v
998         // eax = scratch
999         // ebx = u fraction 0.32
1000         // ecx = v fraction 0.32
1001         // edx = u frac step
1002         // ebp = v carry scratch
1003
1004
1005         mov     al,[edi]                                                                // preread the destination cache line
1006
1007         mov     al,[esi]                                                                // get texture pixel 0
1008
1009         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
1010
1011 InnerInnerLoop:
1012
1013         mov     ah, bh                                                          // move lighting value into place
1014         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1015
1016
1017         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1018         sbb     ebp,ebp                                                         // get -1 if carry
1019         mov     [edi+0],al                                                      // store pixel
1020
1021         mov     al,[esi]                                                                // get texture pixel
1022         add     ebx,edx                                                         // increment u fraction
1023         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1024
1025         mov     ah, bh                                                          // move lighting value into place
1026         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1027
1028
1029         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1030         sbb     ebp,ebp                                                         // get -1 if carry
1031         mov     [edi+1],al                                                      // store pixel
1032
1033         mov     al,[esi]                                                                // get texture pixel
1034         add     ebx,edx                                                         // increment u fraction
1035         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1036
1037         mov     ah, bh                                                          // move lighting value into place
1038         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1039
1040
1041         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1042         sbb     ebp,ebp                                                         // get -1 if carry
1043         mov     [edi+2],al                                                      // store pixel
1044
1045         mov     al,[esi]                                                                // get texture pixel
1046         add     ebx,edx                                                         // increment u fraction
1047         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1048
1049         mov     ah, bh                                                          // move lighting value into place
1050         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1051
1052
1053         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1054         sbb     ebp,ebp                                                         // get -1 if carry
1055         mov     [edi+3],al                                                      // store pixel
1056
1057         mov     al,[esi]                                                                // get texture pixel
1058         add     ebx,edx                                                         // increment u fraction
1059         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1060
1061         add     edi, 4
1062         dec     Tmap.InnerLooper
1063         jnz     InnerInnerLoop
1064
1065         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
1066                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
1067
1068     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
1069     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
1070     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
1071     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
1072
1073     dec     Tmap.Subdivisions                   // decrement span count
1074     jnz     SpanLoop                                                    // loop back
1075
1076
1077 HandleLeftoverPixels:
1078
1079     mov     esi,Tmap.pixptr                             // load texture pointer
1080
1081     // edi = dest dib bits
1082     // esi = current texture dib bits
1083     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
1084     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
1085
1086     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
1087     jz      FPUReturn                   ; nope, pop the FPU and bail
1088
1089     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
1090
1091     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
1092     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
1093     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
1094
1095     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
1096     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
1097     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
1098
1099     dec     Tmap.WidthModLength            ; calc how many steps to take
1100     jz      OnePixelSpan                ; just one, do not do deltas
1101
1102     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
1103     // r -> R+1
1104
1105     // @todo rearrange things so we don't need these two instructions
1106     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
1107     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
1108
1109     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
1110     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
1111     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
1112     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
1113     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
1114     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
1115
1116     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
1117
1118     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
1119     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
1120
1121     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
1122
1123     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
1124     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
1125     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
1126     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
1127
1128     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
1129     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
1130     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
1131
1132     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
1133     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
1134     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
1135     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
1136
1137     // @todo gross!  these are to line up with the other loop
1138     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
1139     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
1140
1141
1142         // setup delta values
1143         mov     eax, Tmap.DeltaV        // get v 16.16 step
1144         mov     ebx, eax                                                // copy it
1145         sar     eax, 16                                         // get v int step
1146         shl     ebx, 16                                         // get v frac step
1147         mov     Tmap.DeltaVFrac, ebx    // store it
1148         imul    eax, Tmap.src_offset    // calc texture step for v int step
1149         
1150         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
1151         mov     ecx, ebx                                                // copy it
1152         sar     ebx, 16                                         // get the u int step
1153         shl     ecx, 16                                         // get the u frac step
1154         mov     Tmap.DeltaUFrac, ecx                    // store it
1155         add     eax, ebx                                                // calc uint + vint step
1156         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1157         add     eax, Tmap.src_offset                            // calc whole step + v carry
1158         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1159
1160
1161 OnePixelSpan:
1162
1163         ; setup initial coordinates
1164         mov     esi, Tmap.UFixed                        // get u 16.16
1165         mov     ebx, esi                                                // copy it
1166         sar     esi, 16                                         // get integer part
1167         shl     ebx, 16                                         // get fractional part
1168
1169         mov     ecx, Tmap.VFixed                        // get v 16.16 
1170         mov     edx, ecx                                                // copy it
1171         sar     edx, 16                                         // get integer part
1172         shl     ecx, 16                                         // get fractional part
1173         imul    edx, Tmap.src_offset            // calc texture scanline address
1174         add     esi, edx                                                        // calc texture offset
1175         add     esi, Tmap.pixptr                        // calc address
1176
1177
1178         mov     eax, Tmap.fx_l
1179         shr     eax, 8
1180         mov     bx, ax
1181
1182         mov     edx, Tmap.DeltaUFrac
1183
1184         cmp     Tmap.WidthModLength, 1
1185         jle     NoDeltaLight
1186
1187         push    ebx
1188         
1189         mov     ebx, Tmap.fx_l_right
1190         shr     ebx, 8
1191         
1192         sub     ebx, eax
1193         mov     eax, ebx
1194         
1195         mov     eax, Tmap.fx_dl_dx
1196         shr     eax, 8
1197
1198         mov     dx, ax
1199
1200         pop     ebx
1201
1202 NoDeltaLight:
1203
1204         inc     Tmap.WidthModLength
1205         mov     eax,Tmap.WidthModLength
1206         shr     eax, 1
1207         jz              one_more_pix
1208         pushf
1209         mov     Tmap.WidthModLength, eax
1210
1211         xor     eax, eax
1212
1213         mov     al,[edi]                    // preread the destination cache line
1214         mov     al,[esi]
1215
1216 NextPixel:
1217         mov     ah, bh                                                          // move lighting value into place
1218         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1219         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1220         sbb     ebp,ebp                                                         // get -1 if carry
1221         mov     [edi+0],al                                                      // store pixel
1222         mov     al,[esi]                                                                // get texture pixel
1223         add     ebx,edx                                                         // increment u fraction
1224         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1225
1226         mov     ah, bh                                                          // move lighting value into place
1227         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1228         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1229         sbb     ebp,ebp                                                         // get -1 if carry
1230         mov     [edi+1],al                                                      // store pixel
1231         mov     al,[esi]                                                                // get texture pixel
1232         add     ebx,edx                                                         // increment u fraction
1233         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1234
1235         add     edi, 2
1236         dec     Tmap.WidthModLength
1237         jg              NextPixel
1238
1239         popf
1240         jnc     FPUReturn
1241
1242 one_more_pix:   
1243
1244         mov     al,[esi]                    // get texture pixel 2
1245         mov     ah, bh
1246         mov     al, gr_fade_table[eax]
1247         mov     [edi],al                  // store pixel 2
1248
1249
1250 FPUReturn:
1251
1252         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
1253                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
1254         ffree   st(0)
1255         ffree   st(1)
1256         ffree   st(2)
1257         ffree   st(3)
1258         ffree   st(4)
1259         ffree   st(5)
1260         ffree   st(6)
1261
1262         fldcw   Tmap.OldFPUCW                  // restore the FPU
1263
1264         pop     edi
1265         pop     esi
1266         pop     ebp
1267         pop     ebx
1268         pop     edx
1269         pop     ecx
1270         pop     eax
1271         }
1272 #endif
1273 }
1274
1275
1276
1277
1278 void tmapscan_pln8()
1279 {
1280         if (gr_zbuffering) {
1281                 switch(gr_zbuffering_mode)      {
1282                 case GR_ZBUFF_NONE:
1283                         break;
1284                 case GR_ZBUFF_FULL:             // both
1285                         tmapscan_pln8_zbuffered();
1286                         return;
1287                 case GR_ZBUFF_WRITE:            // write only
1288                         tmapscan_write_z();
1289                         break;
1290                 case GR_ZBUFF_READ:             // read only
1291                         tmapscan_pln8_zbuffered();
1292                         return;
1293                 }
1294
1295         }
1296
1297         if ( Gr_cpu > 5 )       {
1298                 tmapscan_pln8_ppro();
1299         } else {
1300                 tmapscan_pln8_pentium();
1301         }
1302 }
1303
1304
1305 void tmapscan_lln8()
1306 {
1307 #ifdef PLAT_UNIX
1308         STUB_FUNCTION;
1309 #else
1310         _asm {
1311         push    eax
1312         push    ecx
1313         push    edx
1314         push    ebx
1315         push    ebp
1316         push    esi
1317         push    edi
1318
1319         ; setup delta values
1320         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
1321         mov     ebx, eax                                                // copy it
1322         sar     eax, 16                                         // get v int step
1323         shl     ebx, 16                                         // get v frac step
1324         mov     Tmap.DeltaVFrac, ebx    // store it
1325         imul    eax, Tmap.src_offset    // calc texture step for v int step
1326         
1327         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
1328         mov     ecx, ebx                                                // copy it
1329         sar     ebx, 16                                         // get the u int step
1330         shl     ecx, 16                                         // get the u frac step
1331         mov     Tmap.DeltaUFrac, ecx                    // store it
1332         add     eax, ebx                                                // calc uint + vint step
1333
1334         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1335         add     eax, Tmap.src_offset                            // calc whole step + v carry
1336         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1337
1338         ; setup initial coordinates
1339         mov     esi, Tmap.fx_u                  // get u 16.16
1340         mov     ebx, esi                                                // copy it
1341         sar     esi, 16                                         // get integer part
1342         shl     ebx, 16                                         // get fractional part
1343
1344         mov     ecx, Tmap.fx_v                  // get v 16.16 
1345         mov     edx, ecx                                                // copy it
1346         sar     edx, 16                                         // get integer part
1347         shl     ecx, 16                                         // get fractional part
1348         imul    edx, Tmap.src_offset            // calc texture scanline address
1349         add     esi, edx                                                        // calc texture offset
1350         add     esi, Tmap.pixptr                        // calc address
1351         
1352         ; set edi = address of first pixel to modify
1353         mov     edi, Tmap.dest_row_data
1354         
1355         mov     edx, Tmap.DeltaUFrac
1356
1357         mov     eax, Tmap.loop_count
1358         shr     eax, 2
1359         je              DoLeftOverPixels
1360
1361         mov     Tmap.num_big_steps, eax
1362         and     Tmap.loop_count, 3
1363
1364         mov     al,[edi]                    // preread the destination cache line
1365         mov     al,[esi]                    // get texture pixel 0
1366
1367 NextPixelBlock:
1368
1369         push    eax
1370         mov     eax, Tmap.fx_l
1371         shr     eax, 8
1372         mov     bx, ax
1373
1374         mov     ebp, Tmap.fx_dl_dx
1375         shl     ebp, 2  //*4
1376         add     Tmap.fx_l, ebp
1377
1378         mov     ebp, Tmap.fx_l
1379         shr     ebp, 8
1380         sub     bp, ax
1381         shr     bp, 2
1382
1383         mov     dx, bp
1384         pop     eax
1385
1386
1387     // 8 pixel span code
1388     // edi = dest dib bits at current pixel
1389     // esi = texture pointer at current u,v
1390     // eax = scratch
1391     // ebx = u fraction 0.32
1392     // ecx = v fraction 0.32
1393     // edx = u frac step
1394     // ebp = v carry scratch
1395
1396         mov     ah, bh                                                          // move lighting value into place
1397         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1398         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1399         sbb     ebp,ebp                                                         // get -1 if carry
1400         mov     [edi+0],al                                                      // store pixel
1401         mov     al,[esi]                                                                // get texture pixel
1402         add     ebx,edx                                                         // increment u fraction
1403         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1404
1405         mov     ah, bh                                                          // move lighting value into place
1406         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1407         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1408         sbb     ebp,ebp                                                         // get -1 if carry
1409         mov     [edi+1],al                                                      // store pixel
1410         mov     al,[esi]                                                                // get texture pixel
1411         add     ebx,edx                                                         // increment u fraction
1412         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1413
1414         mov     ah, bh                                                          // move lighting value into place
1415         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1416         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1417         sbb     ebp,ebp                                                         // get -1 if carry
1418         mov     [edi+2],al                                                      // store pixel
1419         mov     al,[esi]                                                                // get texture pixel
1420         add     ebx,edx                                                         // increment u fraction
1421         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1422
1423         mov     ah, bh                                                          // move lighting value into place
1424         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1425         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1426         sbb     ebp,ebp                                                         // get -1 if carry
1427         mov     [edi+3],al                                                      // store pixel
1428         mov     al,[esi]                                                                // get texture pixel
1429         add     ebx,edx                                                         // increment u fraction
1430         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1431
1432         add     edi, 4
1433         dec     Tmap.num_big_steps
1434         jne     NextPixelBlock
1435         
1436
1437 DoLeftOverPixels:
1438
1439         mov     ebp, Tmap.fx_l
1440         shr     ebp, 8
1441         mov     bx, bp
1442
1443         mov     ebp, Tmap.fx_dl_dx
1444         shr     ebp, 8
1445         mov     dx, bp
1446
1447         mov     eax,Tmap.loop_count
1448         test    eax, -1
1449         jz      _none_to_do
1450         shr     eax, 1
1451         je      one_more_pix
1452         mov     Tmap.loop_count, eax
1453         pushf
1454
1455         xor     eax, eax
1456
1457         mov     al, [edi]                    // preread the destination cache line
1458         mov     al, [esi]                                                       // Get first texel
1459
1460 NextPixel:
1461
1462         mov     ah, bh                                                          // move lighting value into place
1463         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1464         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1465         sbb     ebp,ebp                                                         // get -1 if carry
1466         mov     [edi+0],al                                                      // store pixel
1467         mov     al,[esi]                                                                // get texture pixel
1468         add     ebx,edx                                                         // increment u fraction
1469         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1470
1471         mov     ah, bh                                                          // move lighting value into place
1472         mov     al, gr_fade_table[eax]                  // Get shaded pixel
1473         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1474         sbb     ebp,ebp                                                         // get -1 if carry
1475         mov     [edi+1],al                                                      // store pixel
1476         mov     al,[esi]                                                                // get texture pixel
1477         add     ebx,edx                                                         // increment u fraction
1478         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
1479
1480         add     edi, 2
1481         dec     Tmap.loop_count
1482         jne     NextPixel
1483
1484         popf
1485         jnc     _none_to_do
1486
1487 one_more_pix:   
1488         xor     eax, eax
1489         mov     al, [esi]                                                       // Get first texel
1490         mov     ah, bh
1491         mov     al, gr_fade_table[eax]
1492    mov  [edi],al                  // store pixel 2
1493
1494 _none_to_do:    
1495         pop     edi
1496         pop     esi
1497         pop     ebp
1498         pop     ebx
1499         pop     edx
1500         pop     ecx
1501         pop     eax
1502         }
1503 #endif
1504 }
1505
1506
1507 void tmapscan_lna8_zbuffered_ppro()
1508 {
1509 #ifdef PLAT_UNIX
1510         STUB_FUNCTION;
1511 #else
1512         _asm {
1513         push    eax
1514         push    ecx
1515         push    edx
1516         push    ebx
1517         push    ebp
1518         push    esi
1519         push    edi
1520
1521         ; setup delta values
1522         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
1523         mov     ebx, eax                                                // copy it
1524         sar     eax, 16                                         // get v int step
1525         shl     ebx, 16                                         // get v frac step
1526         mov     Tmap.DeltaVFrac, ebx    // store it
1527         imul    eax, Tmap.src_offset    // calc texture step for v int step
1528         
1529         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
1530         mov     ecx, ebx                                                // copy it
1531         sar     ebx, 16                                         // get the u int step
1532         shl     ecx, 16                                         // get the u frac step
1533         mov     Tmap.DeltaUFrac, ecx                    // store it
1534         add     eax, ebx                                                // calc uint + vint step
1535
1536         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1537         add     eax, Tmap.src_offset                            // calc whole step + v carry
1538         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1539
1540         ; setup initial coordinates
1541         mov     esi, Tmap.fx_u                  // get u 16.16
1542         mov     ebx, esi                                                // copy it
1543         sar     esi, 16                                         // get integer part
1544         shl     ebx, 16                                         // get fractional part
1545
1546         mov     ecx, Tmap.fx_v                  // get v 16.16 
1547         mov     edx, ecx                                                // copy it
1548         sar     edx, 16                                         // get integer part
1549         shl     ecx, 16                                         // get fractional part
1550         imul    edx, Tmap.src_offset            // calc texture scanline address
1551         add     esi, edx                                                        // calc texture offset
1552         add     esi, Tmap.pixptr                        // calc address
1553         
1554         ; set edi = address of first pixel to modify
1555         mov     edi, Tmap.dest_row_data
1556         
1557         xor     eax, eax
1558         mov     al,[edi]                                                        // get the destination pixel
1559
1560         mov     ebp, Tmap.fx_w
1561         mov     edx, gr_zbuffer
1562         mov     eax, edi
1563         sub     eax, Tmap.pScreenBits
1564         shl     eax, 2
1565         add     edx, eax
1566
1567         mov     eax, Tmap.loop_count
1568
1569         shr     eax, 2
1570         je              DoLeftOverPixels
1571
1572         mov     Tmap.num_big_steps, eax
1573         and     Tmap.loop_count, 3
1574
1575 NextPixelBlock:
1576
1577         // 8 pixel span code
1578         // eax = scratch
1579         // ebx = u fraction 0.32
1580         // ecx = v fraction 0.32
1581         // edx = zbuffer pointer
1582         // edi = dest dib bits at current pixel
1583         // esi = texture pointer at current u,v
1584         // ebp = zvalue
1585         // esp = stack
1586
1587         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
1588         jle     Skip0a                                                          // If pixel is covered, skip drawing
1589 //      mov     [edx+4*0], ebp                                          // Write new Z value
1590
1591         // Get pixel and blend it
1592         push    ebx
1593         xor     ebx, ebx
1594         mov     bl, [edi+0]
1595         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
1596         mov     ah, [esi]                                                               // Get texel into AL
1597         add     eax, Tmap.BlendLookup
1598         mov     eax, [eax+ebx]          // Lookup pixel in lighting table
1599         pop     ebx
1600
1601         mov     [edi+0],al                                                      // store pixel
1602 Skip0a:
1603         add     ebp,Tmap.fx_dwdx                                        // increment z value
1604         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1605         sbb     eax,eax                                                         // get -1 if carry
1606         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1607         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1608
1609
1610         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
1611         jle     Skip1a                                                          // If pixel is covered, skip drawing
1612 //      mov     [edx+4*1], ebp                                          // Write new Z value
1613
1614         // Get pixel and blend it
1615         push    ebx
1616         xor     ebx, ebx
1617         mov     bl, [edi+1]
1618         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
1619         mov     ah, [esi]                                                               // Get texel into AL
1620         add     eax, Tmap.BlendLookup
1621         mov     eax, [eax+ebx]          // Lookup pixel in lighting table
1622         pop     ebx
1623
1624         mov     [edi+1],al                                                      // store pixel
1625 Skip1a:
1626         add     ebp, Tmap.fx_dwdx
1627         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1628         sbb     eax,eax                                                         // get -1 if carry
1629         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1630         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1631
1632         cmp     ebp, [edx+4*2]                                          // Compare the Z depth of this pixel with zbuffer
1633         jle     Skip2a                                                          // If pixel is covered, skip drawing
1634 //      mov     [edx+4*2], ebp                                          // Write new Z value
1635
1636         push    ebx
1637         xor     ebx, ebx
1638         mov     bl, [edi+2]
1639         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
1640         mov     ah, [esi]                                                               // Get texel into AL
1641         add     eax, Tmap.BlendLookup
1642         mov     eax, [eax+ebx]          // Lookup pixel in lighting table
1643         pop     ebx
1644
1645         mov     [edi+2],al                                                      // store pixel
1646 Skip2a:
1647         add     ebp, Tmap.fx_dwdx
1648         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1649         sbb     eax,eax                                                         // get -1 if carry
1650         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1651         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1652
1653         cmp     ebp, [edx+4*3]                                          // Compare the Z depth of this pixel with zbuffer
1654         jle     Skip3a                                                          // If pixel is covered, skip drawing
1655 //      mov     [edx+4*3], ebp                                          // Write new Z value
1656
1657         push    ebx
1658         xor     ebx, ebx
1659         mov     bl, [edi+3]
1660         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
1661         mov     ah, [esi]                                                               // Get texel into AL
1662         add     eax, Tmap.BlendLookup
1663         mov     eax, [eax+ebx]          // Lookup pixel in lighting table
1664         pop     ebx
1665
1666         mov     [edi+3],al                                                      // store pixel
1667 Skip3a:
1668         add     ebp, Tmap.fx_dwdx
1669         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1670         sbb     eax,eax                                                         // get -1 if carry
1671         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1672         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1673
1674         add     edx, 16
1675         add     edi, 4
1676         dec     Tmap.num_big_steps
1677         jne     NextPixelBlock
1678         
1679
1680 DoLeftOverPixels:
1681
1682         mov     eax,Tmap.loop_count
1683         test    eax, -1
1684         jz      _none_to_do
1685         shr     eax, 1
1686         je      one_more_pix
1687         mov     Tmap.loop_count, eax
1688         pushf
1689
1690         xor     eax, eax
1691         mov     al,[edi]                                                        // get the destination pixel
1692
1693 NextPixel:
1694
1695         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
1696         jle     Skip0b                                                          // If pixel is covered, skip drawing
1697 //      mov     [edx+4*0], ebp                                          // Write new Z value
1698         mov     al,[edi+0]                                                      // get the destination pixel
1699         mov     ah,[esi]                                                                // get texture pixel 0
1700         and     eax, 0ffffh
1701         add     eax, Tmap.BlendLookup
1702         mov     al, [eax]                                                       // blend them
1703         mov     [edi+0],al                                                      // store pixel
1704 Skip0b:
1705         add     ebp, Tmap.fx_dwdx
1706         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1707         sbb     eax,eax                                                         // get -1 if carry
1708         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1709         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1710
1711         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
1712         jle     Skip1b                                                          // If pixel is covered, skip drawing
1713 //      mov     [edx+4*1], ebp                                          // Write new Z value
1714         mov     al,[edi+1]                                                      // get the destination pixel
1715         mov     ah,[esi]                                                                // get texture pixel 0
1716         and     eax, 0ffffh
1717         add     eax, Tmap.BlendLookup
1718         mov     al, [eax]                                                       // blend them
1719         mov     [edi+1],al                                                      // store pixel
1720 Skip1b:
1721         add     ebp, Tmap.fx_dwdx
1722         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1723         sbb     eax,eax                                                         // get -1 if carry
1724         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1725         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1726
1727         add     edi, 2
1728         add     edx, 8
1729         dec     Tmap.loop_count
1730         jne     NextPixel
1731
1732         popf
1733         jnc     _none_to_do
1734
1735 one_more_pix:   
1736         cmp     ebp, [edx]                                              // Compare the Z depth of this pixel with zbuffer
1737         jle     Skip0c                                                          // If pixel is covered, skip drawing
1738 //      mov     [edx], ebp                                              // Write new Z value
1739         mov     al,[edi]                                                        // get the destination pixel
1740         mov     ah,[esi]                                                        // get texture pixel 0
1741         and     eax, 0ffffh
1742         add     eax, Tmap.BlendLookup
1743         mov     al, [eax]                                                       // blend them
1744         mov     [edi],al                                                        // store pixel
1745 Skip0c:
1746
1747 _none_to_do:    
1748         pop     edi
1749         pop     esi
1750         pop     ebp
1751         pop     ebx
1752         pop     edx
1753         pop     ecx
1754         pop     eax
1755         }       
1756 #endif
1757 }
1758
1759 void tmapscan_lna8_zbuffered_pentium()
1760 {
1761 #ifdef PLAT_UNIX
1762         STUB_FUNCTION;
1763 #else
1764         _asm {
1765         push    eax
1766         push    ecx
1767         push    edx
1768         push    ebx
1769         push    ebp
1770         push    esi
1771         push    edi
1772
1773         ; setup delta values
1774         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
1775         mov     ebx, eax                                                // copy it
1776         sar     eax, 16                                         // get v int step
1777         shl     ebx, 16                                         // get v frac step
1778         mov     Tmap.DeltaVFrac, ebx    // store it
1779         imul    eax, Tmap.src_offset    // calc texture step for v int step
1780         
1781         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
1782         mov     ecx, ebx                                                // copy it
1783         sar     ebx, 16                                         // get the u int step
1784         shl     ecx, 16                                         // get the u frac step
1785         mov     Tmap.DeltaUFrac, ecx                    // store it
1786         add     eax, ebx                                                // calc uint + vint step
1787
1788         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
1789         add     eax, Tmap.src_offset                            // calc whole step + v carry
1790         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
1791
1792         ; setup initial coordinates
1793         mov     esi, Tmap.fx_u                  // get u 16.16
1794         mov     ebx, esi                                                // copy it
1795         sar     esi, 16                                         // get integer part
1796         shl     ebx, 16                                         // get fractional part
1797
1798         mov     ecx, Tmap.fx_v                  // get v 16.16 
1799         mov     edx, ecx                                                // copy it
1800         sar     edx, 16                                         // get integer part
1801         shl     ecx, 16                                         // get fractional part
1802         imul    edx, Tmap.src_offset            // calc texture scanline address
1803         add     esi, edx                                                        // calc texture offset
1804         add     esi, Tmap.pixptr                        // calc address
1805         
1806         ; set edi = address of first pixel to modify
1807         mov     edi, Tmap.dest_row_data
1808         
1809         xor     eax, eax
1810         mov     al,[edi]                                                        // get the destination pixel
1811
1812         mov     ebp, Tmap.fx_w
1813         mov     edx, gr_zbuffer
1814         mov     eax, edi
1815         sub     eax, Tmap.pScreenBits
1816         shl     eax, 2
1817         add     edx, eax
1818
1819         mov     eax, Tmap.loop_count
1820
1821         shr     eax, 2
1822         je              DoLeftOverPixels
1823
1824         mov     Tmap.num_big_steps, eax
1825         and     Tmap.loop_count, 3
1826
1827 NextPixelBlock:
1828
1829         // 8 pixel span code
1830         // eax = scratch
1831         // ebx = u fraction 0.32
1832         // ecx = v fraction 0.32
1833         // edx = zbuffer pointer
1834         // edi = dest dib bits at current pixel
1835         // esi = texture pointer at current u,v
1836         // ebp = zvalue
1837         // esp = stack
1838
1839         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
1840         jle     Skip0a                                                          // If pixel is covered, skip drawing
1841 //      mov     [edx+4*0], ebp                                          // Write new Z value
1842         mov     al,[edi+0]                                                      // get the destination pixel
1843         mov     ah,[esi]                                                                // get texture pixel 0
1844         and     eax, 0ffffh
1845
1846
1847
1848
1849         add     eax, Tmap.BlendLookup
1850         mov     al, [eax]                                                       // blend them
1851
1852
1853         mov     [edi+0],al                                                      // store pixel
1854 Skip0a:
1855         add     ebp,Tmap.fx_dwdx                                        // increment z value
1856         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1857         sbb     eax,eax                                                         // get -1 if carry
1858         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1859         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1860
1861
1862         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
1863         jle     Skip1a                                                          // If pixel is covered, skip drawing
1864 //      mov     [edx+4*1], ebp                                          // Write new Z value
1865         mov     al,[edi+1]                                                      // get the destination pixel
1866         mov     ah,[esi]                                                                // get texture pixel 0
1867         and     eax, 0ffffh
1868
1869
1870
1871
1872         add     eax, Tmap.BlendLookup
1873         mov     al, [eax]                                                       // blend them
1874
1875
1876         mov     [edi+1],al                                                      // store pixel
1877 Skip1a:
1878         add     ebp, Tmap.fx_dwdx
1879         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1880         sbb     eax,eax                                                         // get -1 if carry
1881         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1882         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1883
1884         cmp     ebp, [edx+4*2]                                          // Compare the Z depth of this pixel with zbuffer
1885         jle     Skip2a                                                          // If pixel is covered, skip drawing
1886 //      mov     [edx+4*2], ebp                                          // Write new Z value
1887         mov     al,[edi+2]                                                      // get the destination pixel
1888         mov     ah,[esi]                                                                // get texture pixel 0
1889         and     eax, 0ffffh
1890
1891
1892
1893         add     eax, Tmap.BlendLookup
1894         mov     al, [eax]                                                       // blend them
1895
1896
1897         mov     [edi+2],al                                                      // store pixel
1898 Skip2a:
1899         add     ebp, Tmap.fx_dwdx
1900         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1901         sbb     eax,eax                                                         // get -1 if carry
1902         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1903         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1904
1905         cmp     ebp, [edx+4*3]                                          // Compare the Z depth of this pixel with zbuffer
1906         jle     Skip3a                                                          // If pixel is covered, skip drawing
1907 //      mov     [edx+4*3], ebp                                          // Write new Z value
1908         mov     al,[edi+3]                                                      // get the destination pixel
1909         mov     ah,[esi]                                                                // get texture pixel 0
1910         and     eax, 0ffffh
1911
1912
1913
1914         add     eax, Tmap.BlendLookup
1915         mov     al, [eax]                                                       // blend them
1916
1917
1918         mov     [edi+3],al                                                      // store pixel
1919 Skip3a:
1920         add     ebp, Tmap.fx_dwdx
1921         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1922         sbb     eax,eax                                                         // get -1 if carry
1923         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1924         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1925
1926         add     edx, 16
1927         add     edi, 4
1928         dec     Tmap.num_big_steps
1929         jne     NextPixelBlock
1930         
1931
1932 DoLeftOverPixels:
1933
1934         mov     eax,Tmap.loop_count
1935         test    eax, -1
1936         jz      _none_to_do
1937         shr     eax, 1
1938         je      one_more_pix
1939         mov     Tmap.loop_count, eax
1940         pushf
1941
1942         xor     eax, eax
1943         mov     al,[edi]                                                        // get the destination pixel
1944
1945 NextPixel:
1946
1947         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
1948         jle     Skip0b                                                          // If pixel is covered, skip drawing
1949 //      mov     [edx+4*0], ebp                                          // Write new Z value
1950         mov     al,[edi+0]                                                      // get the destination pixel
1951         mov     ah,[esi]                                                                // get texture pixel 0
1952         and     eax, 0ffffh
1953         add     eax, Tmap.BlendLookup
1954         mov     al, [eax]                                                       // blend them
1955         mov     [edi+0],al                                                      // store pixel
1956 Skip0b:
1957         add     ebp, Tmap.fx_dwdx
1958         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1959         sbb     eax,eax                                                         // get -1 if carry
1960         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1961         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1962
1963         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
1964         jle     Skip1b                                                          // If pixel is covered, skip drawing
1965 //      mov     [edx+4*1], ebp                                          // Write new Z value
1966         mov     al,[edi+1]                                                      // get the destination pixel
1967         mov     ah,[esi]                                                                // get texture pixel 0
1968         and     eax, 0ffffh
1969         add     eax, Tmap.BlendLookup
1970         mov     al, [eax]                                                       // blend them
1971         mov     [edi+1],al                                                      // store pixel
1972 Skip1b:
1973         add     ebp, Tmap.fx_dwdx
1974         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
1975         sbb     eax,eax                                                         // get -1 if carry
1976         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
1977         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
1978
1979         add     edi, 2
1980         add     edx, 8
1981         dec     Tmap.loop_count
1982         jne     NextPixel
1983
1984         popf
1985         jnc     _none_to_do
1986
1987 one_more_pix:   
1988         cmp     ebp, [edx]                                              // Compare the Z depth of this pixel with zbuffer
1989         jle     Skip0c                                                          // If pixel is covered, skip drawing
1990 //      mov     [edx], ebp                                              // Write new Z value
1991         mov     al,[edi]                                                        // get the destination pixel
1992         mov     ah,[esi]                                                        // get texture pixel 0
1993         and     eax, 0ffffh
1994         add     eax, Tmap.BlendLookup
1995         mov     al, [eax]                                                       // blend them
1996         mov     [edi],al                                                        // store pixel
1997 Skip0c:
1998
1999 _none_to_do:    
2000         pop     edi
2001         pop     esi
2002         pop     ebp
2003         pop     ebx
2004         pop     edx
2005         pop     ecx
2006         pop     eax
2007         }
2008 #endif
2009 }
2010
2011 void tmapscan_lna8_zbuffered()
2012 {
2013         if ( Gr_cpu > 5 )       {
2014                 tmapscan_lna8_zbuffered_ppro();
2015         } else {
2016                 tmapscan_lna8_zbuffered_pentium();
2017         }
2018 }
2019
2020
2021
2022 extern float Tmap_clipped_left;
2023
2024 void tmapscan_lna8()
2025 {
2026         if (gr_zbuffering) {
2027                 switch(gr_zbuffering_mode)      {
2028                 case GR_ZBUFF_NONE:
2029                         break;
2030                 case GR_ZBUFF_FULL:             // both
2031                 case GR_ZBUFF_WRITE:            // write only
2032                 case GR_ZBUFF_READ:             // read only
2033                         tmapscan_lna8_zbuffered();
2034                         return;
2035                 }
2036
2037         }
2038         
2039 #ifdef PLAT_UNIX
2040         STUB_FUNCTION;
2041 #else
2042         _asm {
2043         push    eax
2044         push    ecx
2045         push    edx
2046         push    ebx
2047         push    ebp
2048         push    esi
2049         push    edi
2050
2051         ; setup delta values
2052         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
2053         mov     ebx, eax                                                // copy it
2054         sar     eax, 16                                         // get v int step
2055         shl     ebx, 16                                         // get v frac step
2056         mov     Tmap.DeltaVFrac, ebx    // store it
2057         imul    eax, Tmap.src_offset    // calc texture step for v int step
2058         
2059         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
2060         mov     ecx, ebx                                                // copy it
2061         sar     ebx, 16                                         // get the u int step
2062         shl     ecx, 16                                         // get the u frac step
2063         mov     Tmap.DeltaUFrac, ecx                    // store it
2064         add     eax, ebx                                                // calc uint + vint step
2065
2066         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
2067         add     eax, Tmap.src_offset                            // calc whole step + v carry
2068         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
2069
2070         ; setup initial coordinates
2071         mov     esi, Tmap.fx_u                  // get u 16.16
2072         mov     ebx, esi                                                // copy it
2073         sar     esi, 16                                         // get integer part
2074         shl     ebx, 16                                         // get fractional part
2075
2076         mov     ecx, Tmap.fx_v                  // get v 16.16 
2077         mov     edx, ecx                                                // copy it
2078         sar     edx, 16                                         // get integer part
2079         shl     ecx, 16                                         // get fractional part
2080         imul    edx, Tmap.src_offset            // calc texture scanline address
2081         add     esi, edx                                                        // calc texture offset
2082         add     esi, Tmap.pixptr                        // calc address
2083         
2084         ; set edi = address of first pixel to modify
2085         mov     edi, Tmap.dest_row_data
2086         
2087         mov     edx, Tmap.DeltaUFrac
2088
2089         xor     eax, eax
2090         mov     al,[edi]                                                        // get the destination pixel
2091
2092         mov     ebp, Tmap.loop_count
2093
2094         shr     ebp, 2
2095         je              DoLeftOverPixels
2096
2097         mov     Tmap.num_big_steps, ebp
2098         and     Tmap.loop_count, 3
2099
2100         mov     eax, 0
2101
2102 NextPixelBlock:
2103
2104     // 8 pixel span code
2105     // edi = dest dib bits at current pixel
2106     // esi = texture pointer at current u,v
2107     // eax = scratch
2108     // ebx = u fraction 0.32
2109     // ecx = v fraction 0.32
2110     // edx = u frac step
2111     // ebp = v carry scratch
2112
2113
2114         xor     eax, eax
2115         mov     al,[edi+0]                                                      // get the destination pixel
2116         mov     ah,[esi]                                                                // get texture pixel 0
2117         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2118         sbb     ebp,ebp                                                         // get -1 if carry
2119         add     ebx,edx                                                         // increment u fraction
2120         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2121         add     eax, Tmap.BlendLookup
2122         mov     al, [eax]                                                       // blend them
2123         mov     [edi+0],al                                                      // store pixel
2124
2125         xor     eax, eax
2126         mov     al,[edi+1]                                                      // get the destination pixel
2127         mov     ah,[esi]                                                                // get texture pixel 0
2128         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2129         sbb     ebp,ebp                                                         // get -1 if carry
2130         add     ebx,edx                                                         // increment u fraction
2131         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2132         add     eax, Tmap.BlendLookup
2133         mov     al, [eax]                                                       // blend them
2134         mov     [edi+1],al                                                      // store pixel
2135
2136         xor     eax, eax
2137         mov     al,[edi+2]                                                      // get the destination pixel
2138         mov     ah,[esi]                                                                // get texture pixel 0
2139         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2140         sbb     ebp,ebp                                                         // get -1 if carry
2141         add     ebx,edx                                                         // increment u fraction
2142         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2143         add     eax, Tmap.BlendLookup
2144         mov     al, [eax]                                                       // blend them
2145         mov     [edi+2],al                                                      // store pixel
2146
2147         xor     eax, eax
2148         mov     al,[edi+3]                                                      // get the destination pixel
2149         mov     ah,[esi]                                                                // get texture pixel 0
2150         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2151         sbb     ebp,ebp                                                         // get -1 if carry
2152         add     ebx,edx                                                         // increment u fraction
2153         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2154         add     eax, Tmap.BlendLookup
2155         mov     al, [eax]                                                       // blend them
2156         mov     [edi+3],al                                                      // store pixel
2157
2158         add     edi, 4
2159         dec     Tmap.num_big_steps
2160         jne     NextPixelBlock
2161         
2162
2163 DoLeftOverPixels:
2164
2165         mov     ebp,Tmap.loop_count
2166         test    ebp, -1
2167         jz      _none_to_do
2168         shr     ebp, 1
2169         je      one_more_pix
2170         mov     Tmap.loop_count, ebp
2171         pushf
2172
2173         mov     al,[edi]                                                        // get the destination pixel
2174
2175 NextPixel:
2176
2177         xor     eax, eax
2178         mov     al,[edi+0]                                                      // get the destination pixel
2179         mov     ah,[esi]                                                                // get texture pixel 0
2180         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2181         sbb     ebp,ebp                                                         // get -1 if carry
2182         add     ebx,edx                                                         // increment u fraction
2183         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2184         add     eax, Tmap.BlendLookup
2185         mov     al, [eax]                                                       // blend them
2186         mov     [edi+0],al                                                      // store pixel
2187
2188         xor     eax, eax
2189         mov     al,[edi+1]                                                      // get the destination pixel
2190         mov     ah,[esi]                                                                // get texture pixel 0
2191         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2192         sbb     ebp,ebp                                                         // get -1 if carry
2193         add     ebx,edx                                                         // increment u fraction
2194         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2195         add     eax, Tmap.BlendLookup
2196         mov     al, [eax]                                                       // blend them
2197         mov     [edi+1],al                                                      // store pixel
2198
2199         add     edi, 2
2200         dec     Tmap.loop_count
2201         jne     NextPixel
2202
2203         popf
2204         jnc     _none_to_do
2205
2206 one_more_pix:   
2207         mov     eax, 0
2208         mov     al,[edi]                                                        // get the destination pixel
2209         mov     ah,[esi]                                                        // get texture pixel 0
2210         add     eax, Tmap.BlendLookup
2211         mov     al, [eax]                                                       // blend them
2212         mov     [edi],al                                                        // store pixel
2213
2214 _none_to_do:    
2215         pop     edi
2216         pop     esi
2217         pop     ebp
2218         pop     ebx
2219         pop     edx
2220         pop     ecx
2221         pop     eax
2222         }
2223 #endif
2224 }
2225
2226 // HACKED IN SYSTEM FOR DOING MODEL CACHING
2227 int Tmap_scan_read = 0;         // 0 = normal mapper, 1=read, 2=write
2228
2229 // HACKED IN SYSTEM FOR DOING MODEL CACHING
2230 void tmapscan_lnn8_read()
2231 {
2232         Tmap.fx_u = fl2f(Tmap.l.u);
2233         Tmap.fx_v = fl2f(Tmap.l.v);
2234         Tmap.fx_du_dx = fl2f(Tmap.deltas.u);
2235         Tmap.fx_dv_dx = fl2f(Tmap.deltas.v);
2236
2237 /*
2238         int i;
2239
2240         ubyte * src = (ubyte *)Tmap.pixptr;
2241         ubyte * dst = (ubyte *)Tmap.dest_row_data;
2242         
2243         for (i=0; i<Tmap.loop_count; i++ )      {
2244                 int u,v;
2245                 u = f2i(Tmap.fx_u);
2246                 v = f2i(Tmap.fx_v);
2247                 
2248                 src[u+v*Tmap.src_offset] = *dst++;
2249                                                 
2250                 Tmap.fx_u += Tmap.fx_du_dx;
2251                 Tmap.fx_v += Tmap.fx_dv_dx;
2252         }
2253 */
2254
2255 #ifdef PLAT_UNIX
2256         STUB_FUNCTION;
2257 #else
2258         _asm {
2259         push    eax
2260         push    ecx
2261         push    edx
2262         push    ebx
2263         push    ebp
2264         push    esi
2265         push    edi
2266
2267         ; setup delta values
2268         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
2269         mov     ebx, eax                                                // copy it
2270         sar     eax, 16                                         // get v int step
2271         shl     ebx, 16                                         // get v frac step
2272         mov     Tmap.DeltaVFrac, ebx    // store it
2273         imul    eax, Tmap.src_offset    // calc texture step for v int step
2274         
2275         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
2276         mov     ecx, ebx                                                // copy it
2277         sar     ebx, 16                                         // get the u int step
2278         shl     ecx, 16                                         // get the u frac step
2279         mov     Tmap.DeltaUFrac, ecx                    // store it
2280         add     eax, ebx                                                // calc uint + vint step
2281
2282         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
2283         add     eax, Tmap.src_offset                            // calc whole step + v carry
2284         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
2285
2286         ; setup initial coordinates
2287         mov     esi, Tmap.fx_u                  // get u 16.16
2288         mov     ebx, esi                                                // copy it
2289         sar     esi, 16                                         // get integer part
2290         shl     ebx, 16                                         // get fractional part
2291
2292         mov     ecx, Tmap.fx_v                  // get v 16.16 
2293         mov     edx, ecx                                                // copy it
2294         sar     edx, 16                                         // get integer part
2295         shl     ecx, 16                                         // get fractional part
2296         imul    edx, Tmap.src_offset            // calc texture scanline address
2297         add     esi, edx                                                        // calc texture offset
2298         add     esi, Tmap.pixptr                        // calc address
2299         
2300         ; set edi = address of first pixel to modify
2301         mov     edi, Tmap.dest_row_data
2302         
2303         mov     edx, Tmap.DeltaUFrac
2304
2305         mov     al,[edi]                    // preread the destination cache line
2306
2307         mov     ebp, Tmap.loop_count
2308
2309         shr     ebp, 2
2310         je              DoLeftOverPixels
2311
2312         mov     Tmap.num_big_steps, ebp
2313         and     Tmap.loop_count, 3
2314
2315
2316 NextPixelBlock:
2317
2318     // 8 pixel span code
2319     // edi = dest dib bits at current pixel
2320     // esi = texture pointer at current u,v
2321     // eax = scratch
2322     // ebx = u fraction 0.32
2323     // ecx = v fraction 0.32
2324     // edx = u frac step
2325     // ebp = v carry scratch
2326
2327         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2328         sbb     ebp,ebp                                                         // get -1 if carry
2329         mov     al,[edi+0]                                                      // get texture pixel
2330         mov     [esi],al                                                                // store pixel
2331         add     ebx,edx                                                         // increment u fraction
2332         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2333
2334         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2335         sbb     ebp,ebp                                                         // get -1 if carry
2336         mov     al,[edi+1]                                                      // get texture pixel
2337         mov     [esi],al                                                                // store pixel
2338         add     ebx,edx                                                         // increment u fraction
2339         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2340
2341         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2342         sbb     ebp,ebp                                                         // get -1 if carry
2343         mov     al,[edi+2]                                                      // get texture pixel
2344         mov     [esi],al                                                                // store pixel
2345         add     ebx,edx                                                         // increment u fraction
2346         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2347
2348         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2349         sbb     ebp,ebp                                                         // get -1 if carry
2350         mov     al,[edi+3]                                                      // get texture pixel
2351         mov     [esi],al                                                                // store pixel
2352         add     ebx,edx                                                         // increment u fraction
2353         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2354
2355         add     edi, 4
2356         dec     Tmap.num_big_steps
2357         jne     NextPixelBlock
2358         
2359
2360 DoLeftOverPixels:
2361
2362         mov     ebp,Tmap.loop_count
2363         test    ebp, -1
2364         jz      _none_to_do
2365         shr     ebp, 1
2366         je      one_more_pix
2367         mov     Tmap.loop_count, ebp
2368         pushf
2369
2370         xor     eax, eax
2371
2372         mov     al, [edi]                    // preread the destination cache line
2373
2374 NextPixel:
2375
2376         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2377         sbb     ebp,ebp                                                         // get -1 if carry
2378         mov     al,[edi+0]                                                      // get texture pixel
2379         mov     [esi],al                                                                // store pixel
2380         add     ebx,edx                                                         // increment u fraction
2381         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2382
2383         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2384         sbb     ebp,ebp                                                         // get -1 if carry
2385         mov     al,[edi+1]                                                      // get texture pixel
2386         mov     [esi],al                                                                // store pixel
2387         add     ebx,edx                                                         // increment u fraction
2388         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2389
2390         add     edi, 2
2391         dec     Tmap.loop_count
2392         jne     NextPixel
2393
2394         popf
2395         jnc     _none_to_do
2396
2397 one_more_pix:   
2398         mov     al,[edi]                                                                // get texture pixel
2399    mov  [esi],al                  // store pixel 2
2400
2401 _none_to_do:    
2402         pop     edi
2403         pop     esi
2404         pop     ebp
2405         pop     ebx
2406         pop     edx
2407         pop     ecx
2408         pop     eax
2409         }
2410 #endif
2411 }
2412
2413
2414 // HACKED IN SYSTEM FOR DOING MODEL CACHING
2415 void tmapscan_lnn8_write()
2416 {
2417         Tmap.fx_u = fl2f(Tmap.l.u);
2418         Tmap.fx_v = fl2f(Tmap.l.v);
2419         Tmap.fx_du_dx = fl2f(Tmap.deltas.u);
2420         Tmap.fx_dv_dx = fl2f(Tmap.deltas.v);
2421
2422 /*
2423         int i;
2424
2425         ubyte * src = (ubyte *)Tmap.pixptr;
2426         ubyte * dst = (ubyte *)Tmap.dest_row_data;
2427         
2428         for (i=0; i<Tmap.loop_count; i++ )      {
2429                 int u,v;
2430                 u = f2i(Tmap.fx_u);
2431                 v = f2i(Tmap.fx_v);
2432
2433                 ubyte c = src[u+v*Tmap.src_offset];
2434                 if ( c != 0 )   {
2435                         *dst = c;
2436                 }
2437                 dst++;
2438                                         
2439                 Tmap.fx_u += Tmap.fx_du_dx;
2440                 Tmap.fx_v += Tmap.fx_dv_dx;
2441         }
2442 */
2443
2444 #ifdef PLAT_UNIX
2445         STUB_FUNCTION;
2446 #else
2447         _asm {
2448         push    eax
2449         push    ecx
2450         push    edx
2451         push    ebx
2452         push    ebp
2453         push    esi
2454         push    edi
2455
2456         ; setup delta values
2457         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
2458         mov     ebx, eax                                                // copy it
2459         sar     eax, 16                                         // get v int step
2460         shl     ebx, 16                                         // get v frac step
2461         mov     Tmap.DeltaVFrac, ebx    // store it
2462         imul    eax, Tmap.src_offset    // calc texture step for v int step
2463         
2464         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
2465         mov     ecx, ebx                                                // copy it
2466         sar     ebx, 16                                         // get the u int step
2467         shl     ecx, 16                                         // get the u frac step
2468         mov     Tmap.DeltaUFrac, ecx                    // store it
2469         add     eax, ebx                                                // calc uint + vint step
2470
2471         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
2472         add     eax, Tmap.src_offset                            // calc whole step + v carry
2473         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
2474
2475         ; setup initial coordinates
2476         mov     esi, Tmap.fx_u                  // get u 16.16
2477         mov     ebx, esi                                                // copy it
2478         sar     esi, 16                                         // get integer part
2479         shl     ebx, 16                                         // get fractional part
2480
2481         mov     ecx, Tmap.fx_v                  // get v 16.16 
2482         mov     edx, ecx                                                // copy it
2483         sar     edx, 16                                         // get integer part
2484         shl     ecx, 16                                         // get fractional part
2485         imul    edx, Tmap.src_offset            // calc texture scanline address
2486         add     esi, edx                                                        // calc texture offset
2487         add     esi, Tmap.pixptr                        // calc address
2488         
2489         ; set edi = address of first pixel to modify
2490         mov     edi, Tmap.dest_row_data
2491         
2492         mov     edx, Tmap.DeltaUFrac
2493
2494         mov     al,[edi]                    // preread the destination cache line
2495
2496         mov     ebp, Tmap.loop_count
2497
2498         shr     ebp, 2
2499         je              DoLeftOverPixels
2500
2501         mov     Tmap.num_big_steps, ebp
2502         and     Tmap.loop_count, 3
2503
2504
2505 NextPixelBlock:
2506
2507     // 8 pixel span code
2508     // edi = dest dib bits at current pixel
2509     // esi = texture pointer at current u,v
2510     // eax = scratch
2511     // ebx = u fraction 0.32
2512     // ecx = v fraction 0.32
2513     // edx = u frac step
2514     // ebp = v carry scratch
2515
2516         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2517         sbb     ebp,ebp                                                         // get -1 if carry
2518         mov     al,[esi]                                                                // get texture pixel
2519         add     ebx,edx                                                         // increment u fraction
2520         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2521         cmp     al, 255
2522         je              Skip0
2523         mov     [edi+0],al                                                      // store pixel
2524 Skip0:
2525
2526         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2527         sbb     ebp,ebp                                                         // get -1 if carry
2528         mov     al,[esi]                                                                // get texture pixel
2529         add     ebx,edx                                                         // increment u fraction
2530         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2531         cmp     al, 255
2532         je              Skip1
2533         mov     [edi+1],al                                                      // store pixel
2534 Skip1:
2535
2536         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2537         sbb     ebp,ebp                                                         // get -1 if carry
2538         mov     al,[esi]                                                                // get texture pixel
2539         add     ebx,edx                                                         // increment u fraction
2540         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2541         cmp     al, 255
2542         je              Skip2
2543         mov     [edi+2],al                                                      // store pixel
2544 Skip2:
2545
2546         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2547         sbb     ebp,ebp                                                         // get -1 if carry
2548         mov     al,[esi]                                                                // get texture pixel
2549         add     ebx,edx                                                         // increment u fraction
2550         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2551         cmp     al, 255
2552         je              Skip3
2553         mov     [edi+3],al                                                      // store pixel
2554 Skip3:
2555
2556         add     edi, 4
2557         dec     Tmap.num_big_steps
2558         jne     NextPixelBlock
2559         
2560
2561 DoLeftOverPixels:
2562
2563         mov     ebp,Tmap.loop_count
2564         test    ebp, -1
2565         jz      _none_to_do
2566         shr     ebp, 1
2567         je      one_more_pix
2568         mov     Tmap.loop_count, ebp
2569         pushf
2570
2571         xor     eax, eax
2572
2573         mov     al, [edi]                    // preread the destination cache line
2574
2575 NextPixel:
2576
2577         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2578         sbb     ebp,ebp                                                         // get -1 if carry
2579         mov     al,[esi]                                                                // get texture pixel
2580         add     ebx,edx                                                         // increment u fraction
2581         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2582         cmp     al, 255
2583         je              Skip0a
2584         mov     [edi+0],al                                                      // store pixel
2585 Skip0a:
2586
2587         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2588         sbb     ebp,ebp                                                         // get -1 if carry
2589         mov     al,[esi]                                                                // get texture pixel
2590         add     ebx,edx                                                         // increment u fraction
2591         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
2592         cmp     al, 255
2593         je              Skip1a
2594         mov     [edi+1],al                                                      // store pixel
2595 Skip1a:
2596
2597         add     edi, 2
2598         dec     Tmap.loop_count
2599         jne     NextPixel
2600
2601         popf
2602         jnc     _none_to_do
2603
2604 one_more_pix:   
2605         mov     al,[esi]                                                                // get texture pixel
2606         cmp     al, 255
2607         je              Skip0b
2608         mov     [edi],al                                                        // store pixel
2609 Skip0b:
2610
2611 _none_to_do:    
2612         pop     edi
2613         pop     esi
2614         pop     ebp
2615         pop     ebx
2616         pop     edx
2617         pop     ecx
2618         pop     eax
2619         }
2620 #endif
2621 }
2622
2623 void tmapscan_lnn8()
2624 {
2625         // HACKED IN SYSTEM FOR DOING MODEL CACHING
2626         if ( Tmap_scan_read==1 )        {
2627                 tmapscan_lnn8_read();
2628                 return;
2629         } else if ( Tmap_scan_read==2 ) {
2630                 tmapscan_lnn8_write();
2631                 //tmapscan_lnt8();
2632                 return;
2633         }
2634
2635         if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER )                {
2636                 tmapscan_lna8();
2637                 return;
2638         }
2639
2640 #ifdef PLAT_UNIX
2641         STUB_FUNCTION;
2642 #else
2643         _asm {
2644         push    eax
2645         push    ecx
2646         push    edx
2647         push    ebx
2648         push    ebp
2649         push    esi
2650         push    edi
2651
2652         ; setup delta values
2653         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
2654         mov     ebx, eax                                                // copy it
2655         sar     eax, 16                                         // get v int step
2656         shl     ebx, 16                                         // get v frac step
2657         mov     Tmap.DeltaVFrac, ebx    // store it
2658         imul    eax, Tmap.src_offset    // calc texture step for v int step
2659         
2660         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
2661         mov     ecx, ebx                                                // copy it
2662         sar     ebx, 16                                         // get the u int step
2663         shl     ecx, 16                                         // get the u frac step
2664         mov     Tmap.DeltaUFrac, ecx                    // store it
2665         add     eax, ebx                                                // calc uint + vint step
2666
2667         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
2668         add     eax, Tmap.src_offset                            // calc whole step + v carry
2669         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
2670
2671         ; setup initial coordinates
2672         mov     esi, Tmap.fx_u                  // get u 16.16
2673         mov     ebx, esi                                                // copy it
2674         sar     esi, 16                                         // get integer part
2675         shl     ebx, 16                                         // get fractional part
2676
2677         mov     ecx, Tmap.fx_v                  // get v 16.16 
2678         mov     edx, ecx                                                // copy it
2679         sar     edx, 16                                         // get integer part
2680         shl     ecx, 16                                         // get fractional part
2681         imul    edx, Tmap.src_offset            // calc texture scanline address
2682         add     esi, edx                                                        // calc texture offset
2683         add     esi, Tmap.pixptr                        // calc address
2684         
2685         ; set edi = address of first pixel to modify
2686         mov     edi, Tmap.dest_row_data
2687         
2688         mov     edx, Tmap.DeltaUFrac
2689
2690         mov     al,[edi]                    // preread the destination cache line
2691         mov     al,[esi]                    // get texture pixel 0
2692
2693         mov     ebp, Tmap.loop_count
2694
2695         shr     ebp, 2
2696         je              DoLeftOverPixels
2697
2698         mov     Tmap.num_big_steps, ebp
2699         and     Tmap.loop_count, 3
2700
2701
2702 NextPixelBlock:
2703
2704     // 8 pixel span code
2705     // edi = dest dib bits at current pixel
2706     // esi = texture pointer at current u,v
2707     // eax = scratch
2708     // ebx = u fraction 0.32
2709     // ecx = v fraction 0.32
2710     // edx = u frac step
2711     // ebp = v carry scratch
2712
2713         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2714         sbb     ebp,ebp                                                         // get -1 if carry
2715         mov     [edi+0],al                                                      // store pixel
2716         mov     al,[esi]                                                                // get texture pixel
2717         add     ebx,edx                                                         // increment u fraction
2718         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2719
2720         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2721         sbb     ebp,ebp                                                         // get -1 if carry
2722         mov     [edi+1],al                                                      // store pixel
2723         mov     al,[esi]                                                                // get texture pixel
2724         add     ebx,edx                                                         // increment u fraction
2725         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2726
2727         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2728         sbb     ebp,ebp                                                         // get -1 if carry
2729         mov     [edi+2],al                                                      // store pixel
2730         mov     al,[esi]                                                                // get texture pixel
2731         add     ebx,edx                                                         // increment u fraction
2732         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2733
2734         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2735         sbb     ebp,ebp                                                         // get -1 if carry
2736         mov     [edi+3],al                                                      // store pixel
2737         mov     al,[esi]                                                                // get texture pixel
2738         add     ebx,edx                                                         // increment u fraction
2739         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2740
2741         add     edi, 4
2742         dec     Tmap.num_big_steps
2743         jne     NextPixelBlock
2744         
2745
2746 DoLeftOverPixels:
2747
2748         mov     ebp,Tmap.loop_count
2749         test    ebp, -1
2750         jz      _none_to_do
2751         shr     ebp, 1
2752         je      one_more_pix
2753         mov     Tmap.loop_count, ebp
2754         pushf
2755
2756         xor     eax, eax
2757
2758         mov     al, [edi]                    // preread the destination cache line
2759         mov     al, [esi]                                                       // Get first texel
2760
2761 NextPixel:
2762
2763         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2764         sbb     ebp,ebp                                                         // get -1 if carry
2765         mov     [edi+0],al                                                      // store pixel
2766         mov     al,[esi]                                                                // get texture pixel
2767         add     ebx,edx                                                         // increment u fraction
2768         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2769
2770         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2771         sbb     ebp,ebp                                                         // get -1 if carry
2772         mov     [edi+1],al                                                      // store pixel
2773         mov     al,[esi]                                                                // get texture pixel
2774         add     ebx,edx                                                         // increment u fraction
2775         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2776
2777         add     edi, 2
2778         dec     Tmap.loop_count
2779         jne     NextPixel
2780
2781         popf
2782         jnc     _none_to_do
2783
2784 one_more_pix:   
2785    mov     [edi],al                  // store pixel 2
2786
2787 _none_to_do:    
2788         pop     edi
2789         pop     esi
2790         pop     ebp
2791         pop     ebx
2792         pop     edx
2793         pop     ecx
2794         pop     eax
2795         }
2796 #endif
2797 }
2798
2799 void tmapscan_lnt8()
2800 {
2801         if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER )                {
2802                 tmapscan_lna8();
2803                 return;
2804         }
2805
2806 #ifdef PLAT_UNIX
2807         STUB_FUNCTION;
2808 #else
2809         _asm {
2810         push    eax
2811         push    ecx
2812         push    edx
2813         push    ebx
2814         push    ebp
2815         push    esi
2816         push    edi
2817
2818         ; setup delta values
2819         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
2820         mov     ebx, eax                                                // copy it
2821         sar     eax, 16                                         // get v int step
2822         shl     ebx, 16                                         // get v frac step
2823         mov     Tmap.DeltaVFrac, ebx    // store it
2824         imul    eax, Tmap.src_offset    // calc texture step for v int step
2825         
2826         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
2827         mov     ecx, ebx                                                // copy it
2828         sar     ebx, 16                                         // get the u int step
2829         shl     ecx, 16                                         // get the u frac step
2830         mov     Tmap.DeltaUFrac, ecx                    // store it
2831         add     eax, ebx                                                // calc uint + vint step
2832
2833         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
2834         add     eax, Tmap.src_offset                            // calc whole step + v carry
2835         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
2836
2837         ; setup initial coordinates
2838         mov     esi, Tmap.fx_u                  // get u 16.16
2839         mov     ebx, esi                                                // copy it
2840         sar     esi, 16                                         // get integer part
2841         shl     ebx, 16                                         // get fractional part
2842
2843         mov     ecx, Tmap.fx_v                  // get v 16.16 
2844         mov     edx, ecx                                                // copy it
2845         sar     edx, 16                                         // get integer part
2846         shl     ecx, 16                                         // get fractional part
2847         imul    edx, Tmap.src_offset            // calc texture scanline address
2848         add     esi, edx                                                        // calc texture offset
2849         add     esi, Tmap.pixptr                        // calc address
2850         
2851         ; set edi = address of first pixel to modify
2852         mov     edi, Tmap.dest_row_data
2853         
2854         mov     edx, Tmap.DeltaUFrac
2855
2856         mov     al,[edi]                    // preread the destination cache line
2857         mov     al,[esi]                    // get texture pixel 0
2858
2859         mov     ebp, Tmap.loop_count
2860
2861         shr     ebp, 2
2862         je              DoLeftOverPixels
2863
2864         mov     Tmap.num_big_steps, ebp
2865         and     Tmap.loop_count, 3
2866
2867 NextPixelBlock:
2868
2869     // 8 pixel span code
2870     // edi = dest dib bits at current pixel
2871     // esi = texture pointer at current u,v
2872     // eax = scratch
2873     // ebx = u fraction 0.32
2874     // ecx = v fraction 0.32
2875     // edx = u frac step
2876     // ebp = v carry scratch
2877
2878         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2879         sbb     ebp,ebp                                                         // get -1 if carry
2880         cmp     al, 255
2881         je              skip0
2882         mov     [edi+0],al                                                      // store pixel
2883 skip0:
2884         mov     al,[esi]                                                                // get texture pixel
2885         add     ebx,edx                                                         // increment u fraction
2886         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2887
2888         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2889         sbb     ebp,ebp                                                         // get -1 if carry
2890         cmp     al, 255
2891         je              skip1
2892         mov     [edi+1],al                                                      // store pixel
2893 skip1:
2894         mov     al,[esi]                                                                // get texture pixel
2895         add     ebx,edx                                                         // increment u fraction
2896         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2897
2898         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2899         sbb     ebp,ebp                                                         // get -1 if carry
2900         cmp     al, 255
2901         je              skip2
2902         mov     [edi+2],al                                                      // store pixel
2903 skip2:
2904         mov     al,[esi]                                                                // get texture pixel
2905         add     ebx,edx                                                         // increment u fraction
2906         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2907
2908         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2909         sbb     ebp,ebp                                                         // get -1 if carry
2910         cmp     al, 255
2911         je              skip3
2912         mov     [edi+3],al                                                      // store pixel
2913 skip3:
2914         mov     al,[esi]                                                                // get texture pixel
2915         add     ebx,edx                                                         // increment u fraction
2916         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2917
2918         add     edi, 4
2919         dec     Tmap.num_big_steps
2920         jne     NextPixelBlock
2921         
2922
2923 DoLeftOverPixels:
2924
2925         mov     ebp,Tmap.loop_count
2926         test    ebp, -1
2927         jz      _none_to_do
2928         shr     ebp, 1
2929         je      one_more_pix
2930         mov     Tmap.loop_count, ebp
2931         pushf
2932
2933         xor     eax, eax
2934
2935         mov     al, [edi]                    // preread the destination cache line
2936         mov     al, [esi]                                                       // Get first texel
2937
2938 NextPixel:
2939
2940         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2941         sbb     ebp,ebp                                                         // get -1 if carry
2942         cmp     al, 255
2943         je              skipa0
2944         mov     [edi+0],al                                                      // store pixel
2945 skipa0:
2946         mov     al,[esi]                                                                // get texture pixel
2947         add     ebx,edx                                                         // increment u fraction
2948         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2949
2950         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
2951         sbb     ebp,ebp                                                         // get -1 if carry
2952         cmp     al, 255
2953         je              skipa1
2954         mov     [edi+1],al                                                      // store pixel
2955 skipa1:
2956         mov     al,[esi]                                                                // get texture pixel
2957         add     ebx,edx                                                         // increment u fraction
2958         adc     esi,Tmap.uv_delta[4*ebp+4]      // add in step ints & carries
2959
2960         add     edi, 2
2961         dec     Tmap.loop_count
2962         jne     NextPixel
2963
2964         popf
2965         jnc     _none_to_do
2966
2967 one_more_pix:   
2968         cmp     al, 255
2969         je              skipb0
2970         mov     [edi],al                                                        // store pixel
2971 skipb0:
2972
2973 _none_to_do:    
2974         pop     edi
2975         pop     esi
2976         pop     ebp
2977         pop     ebx
2978         pop     edx
2979         pop     ecx
2980         pop     eax
2981         }
2982 #endif
2983 }
2984
2985
2986
2987 void tmapscan_pln8_zbuffered_ppro()
2988 {
2989 #ifdef PLAT_UNIX
2990         STUB_FUNCTION;
2991 #else
2992         _asm {
2993         
2994         push    eax
2995         push    ecx
2996         push    edx
2997         push    ebx
2998         push    ebp
2999         push    esi
3000         push    edi
3001
3002         // Put the FPU in low precision mode
3003         fstcw           Tmap.OldFPUCW                                   // store copy of CW
3004         mov             ax,Tmap.OldFPUCW                                // get it in ax
3005         and             eax, ~0x300L
3006         mov             Tmap.FPUCW,ax                                   // store it
3007         fldcw           Tmap.FPUCW                                              // load the FPU
3008
3009
3010         mov             ecx, Tmap.loop_count            // ecx = width
3011         mov             edi, Tmap.dest_row_data // edi = dest pointer
3012
3013         // edi = pointer to start pixel in dest dib
3014         // ecx = spanwidth
3015
3016         mov             eax,ecx                                                 // eax and ecx = width
3017         shr             ecx,5                                                           // ecx = width / subdivision length
3018         and             eax,31                                                          // eax = width mod subdivision length
3019         jnz             some_left_over                                  // any leftover?
3020         dec             ecx                                                             // no, so special case last span
3021         mov             eax,32                                                          // it's 8 pixels long
3022 some_left_over:
3023         mov             Tmap.Subdivisions,ecx           // store widths
3024         mov             Tmap.WidthModLength,eax
3025
3026         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
3027                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
3028         fld             Tmap.l.v                                        // V/ZL 
3029         fld             Tmap.l.u                                        // U/ZL V/ZL 
3030         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
3031         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
3032         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
3033         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
3034         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
3035         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
3036         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
3037
3038         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
3039         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
3040
3041         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
3042
3043         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
3044         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
3045         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
3046         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
3047         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
3048
3049         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
3050
3051         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
3052         // @todo overlap this guy
3053         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
3054         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
3055         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
3056         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
3057         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3058
3059         cmp             ecx,0                                                   // check for any full spans
3060         jle      HandleLeftoverPixels
3061     
3062 SpanLoop:
3063
3064         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
3065                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3066
3067         // convert left side coords
3068
3069         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
3070         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
3071         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
3072
3073         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
3074         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
3075         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
3076
3077         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
3078
3079         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
3080         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
3081         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
3082         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
3083
3084         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
3085         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
3086
3087         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
3088         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
3089         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
3090
3091         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
3092         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
3093
3094         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
3095         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
3096         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
3097         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
3098         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
3099         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
3100         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
3101
3102
3103         // setup delta values
3104     
3105         mov     eax,Tmap.DeltaV                         // get v 16.16 step
3106         mov     ebx,eax                                                 // copy it
3107         sar     eax,16                                                          // get v int step
3108         shl     ebx,16                                                          // get v frac step
3109         mov     Tmap.DeltaVFrac,ebx                     // store it
3110         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
3111
3112         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
3113         mov     ecx,ebx                                                 // copy it
3114         sar     ebx,16                                                          // get u int step
3115         shl     ecx,16                                                          // get u frac step
3116         mov     Tmap.DeltaUFrac,ecx                     // store it
3117         add     eax,ebx                                                 // calculate uint + vint step
3118         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
3119         add     eax,Tmap.src_offset                     // calculate whole step + v carry
3120         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
3121
3122         // setup initial coordinates
3123         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
3124
3125         mov     ebx,esi                                                 // copy it
3126         sar     esi,16                                                          // get integer part
3127         shl     ebx,16                                                          // get fractional part
3128
3129         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
3130    
3131         mov     edx,ecx                                                 // copy it
3132         sar     edx,16                                                          // get integer part
3133         shl     ecx,16                                                          // get fractional part
3134         imul    edx,Tmap.src_offset                     // calc texture scanline address
3135         add     esi,edx                                                 // calc texture offset
3136         add     esi,Tmap.pixptr                         // calc address
3137
3138         // set up affine registers
3139
3140         mov     eax, Tmap.fx_l
3141         shr     eax, 8
3142         mov     bx, ax
3143
3144         mov     ebp, Tmap.fx_dl_dx
3145         shl     ebp, 5  //*32
3146         add     Tmap.fx_l, ebp
3147
3148         mov     ebp, Tmap.fx_l
3149         shr     ebp, 8
3150         sub     bp, ax
3151         shr     bp, 5
3152
3153         mov     edx, Tmap.DeltaUFrac
3154         mov     dx, bp
3155         mov     Tmap.DeltaUFrac, edx
3156
3157
3158         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
3159         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
3160         // This divide should happen while the pixel span is drawn.
3161         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
3162
3163
3164         // 8 pixel span code
3165         // edi = dest dib bits at current pixel
3166         // esi = texture pointer at current u,v
3167         // eax = scratch
3168         // ebx = u fraction 0.32
3169         // ecx = v fraction 0.32
3170         // edx = u frac step
3171         // ebp = v carry scratch
3172
3173         mov     al,[edi]                                                                // preread the destination cache line
3174         mov     al,[esi]                                                                // get texture pixel 0
3175
3176         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
3177
3178         mov     ebp, Tmap.fx_w
3179
3180
3181         mov     eax, edi
3182         sub     eax, Tmap.pScreenBits
3183         mov     edx, gr_zbuffer
3184         shl     eax, 2
3185         add     edx, eax
3186
3187 InnerInnerLoop:
3188
3189                         // Pixel 0
3190                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
3191                         jle     Skip0                                                                   // If pixel is covered, skip drawing
3192                         mov     [edx+0], ebp                                                    // Write new Z value
3193         
3194                         // Get pixel and light it
3195                         push    ebx
3196                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3197                         mov     al, [esi]                                                               // Get texel into AL
3198                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3199                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3200                         pop     ebx
3201
3202                         mov     [edi+0],al                                                              // Write new pixel
3203
3204 Skip0:  add     ecx,Tmap.DeltaVFrac
3205                         sbb     eax,eax
3206                         add     ebp,Tmap.fx_dwdx
3207                         add     ebx,Tmap.DeltaUFrac
3208                         adc     esi,Tmap.uv_delta[4*eax+4]
3209
3210
3211                         // Pixel 1
3212                         cmp     ebp, [edx+4]                                                    // Compare the Z depth of this pixel with zbuffer
3213                         jle     Skip1                                                           // If pixel is covered, skip drawing
3214                         mov     [edx+4], ebp                                                    // Write new Z value
3215         
3216                         // Get pixel and light it
3217                         push    ebx
3218                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3219                         mov     al, [esi]                                                               // Get texel into AL
3220                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3221                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3222                         pop     ebx
3223
3224                         mov     [edi+1],al                                                              // Write new pixel
3225
3226 Skip1:  add     ecx,Tmap.DeltaVFrac
3227                         sbb     eax,eax
3228                         add     ebp,Tmap.fx_dwdx
3229                         add     ebx,Tmap.DeltaUFrac
3230                         adc     esi,Tmap.uv_delta[4*eax+4]
3231
3232
3233                         // Pixel 2
3234                         cmp     ebp, [edx+8]                                                    // Compare the Z depth of this pixel with zbuffer
3235                         jle     Skip2                                                                           // If pixel is covered, skip drawing
3236                         mov     [edx+8], ebp                                                    // Write new Z value
3237         
3238                         // Get pixel and light it
3239                         push    ebx
3240                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3241                         mov     al, [esi]                                                               // Get texel into AL
3242                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3243                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3244                         pop     ebx
3245
3246                         mov     [edi+2],al                                                              // Write new pixel
3247
3248 Skip2:  add     ecx,Tmap.DeltaVFrac
3249                         sbb     eax,eax
3250                         add     ebp,Tmap.fx_dwdx
3251                         add     ebx,Tmap.DeltaUFrac
3252                         adc     esi,Tmap.uv_delta[4*eax+4]
3253
3254
3255                         // Pixel 3
3256                         cmp     ebp, [edx+12]                                                   // Compare the Z depth of this pixel with zbuffer
3257                         jle     Skip3                                                                   // If pixel is covered, skip drawing
3258                         mov     [edx+12], ebp                                                   // Write new Z value
3259         
3260                         // Get pixel and light it
3261                         push    ebx
3262                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3263                         mov     al, [esi]                                                               // Get texel into AL
3264                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3265                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3266                         pop     ebx
3267
3268                         mov     [edi+3],al                                                              // Write new pixel
3269
3270 Skip3:  add     ecx,Tmap.DeltaVFrac
3271                         sbb     eax,eax
3272                         add     ebp,Tmap.fx_dwdx
3273                         add     ebx,Tmap.DeltaUFrac
3274                         adc     esi,Tmap.uv_delta[4*eax+4]
3275
3276
3277
3278         add     edi, 4
3279         add     edx, 16
3280         dec     Tmap.InnerLooper
3281         jnz     InnerInnerLoop
3282
3283         mov     Tmap.fx_w, ebp
3284
3285         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
3286                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
3287
3288     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
3289     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
3290     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
3291     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3292
3293     dec     Tmap.Subdivisions                   // decrement span count
3294     jnz     SpanLoop                                                    // loop back
3295
3296
3297 HandleLeftoverPixels:
3298
3299     mov     esi,Tmap.pixptr                             // load texture pointer
3300
3301     // edi = dest dib bits
3302     // esi = current texture dib bits
3303     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
3304     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
3305
3306     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
3307     jz      FPUReturn                   ; nope, pop the FPU and bail
3308
3309     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
3310
3311     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
3312     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
3313     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
3314
3315     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
3316     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
3317     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
3318
3319     dec     Tmap.WidthModLength            ; calc how many steps to take
3320     jz      OnePixelSpan                ; just one, do not do deltas
3321
3322     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
3323     // r -> R+1
3324
3325     // @todo rearrange things so we don't need these two instructions
3326     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
3327     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
3328
3329     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
3330     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
3331     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
3332     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
3333     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
3334     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
3335
3336     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
3337
3338     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
3339     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
3340
3341     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
3342
3343     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
3344     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
3345     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
3346     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
3347
3348     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
3349     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
3350     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
3351
3352     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
3353     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
3354     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
3355     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
3356
3357     // @todo gross!  these are to line up with the other loop
3358     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
3359     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
3360
3361
3362         // setup delta values
3363         mov     eax, Tmap.DeltaV        // get v 16.16 step
3364         mov     ebx, eax                                                // copy it
3365         sar     eax, 16                                         // get v int step
3366         shl     ebx, 16                                         // get v frac step
3367         mov     Tmap.DeltaVFrac, ebx    // store it
3368         imul    eax, Tmap.src_offset    // calc texture step for v int step
3369         
3370         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
3371         mov     ecx, ebx                                                // copy it
3372         sar     ebx, 16                                         // get the u int step
3373         shl     ecx, 16                                         // get the u frac step
3374         mov     Tmap.DeltaUFrac, ecx                    // store it
3375         add     eax, ebx                                                // calc uint + vint step
3376         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
3377         add     eax, Tmap.src_offset                            // calc whole step + v carry
3378         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
3379
3380
3381 OnePixelSpan:
3382
3383         ; setup initial coordinates
3384         mov     esi, Tmap.UFixed                        // get u 16.16
3385         mov     ebx, esi                                                // copy it
3386         sar     esi, 16                                         // get integer part
3387         shl     ebx, 16                                         // get fractional part
3388
3389         mov     ecx, Tmap.VFixed                        // get v 16.16 
3390         mov     edx, ecx                                                // copy it
3391         sar     edx, 16                                         // get integer part
3392         shl     ecx, 16                                         // get fractional part
3393         imul    edx, Tmap.src_offset            // calc texture scanline address
3394         add     esi, edx                                                        // calc texture offset
3395         add     esi, Tmap.pixptr                        // calc address
3396
3397
3398         mov     eax, Tmap.fx_l
3399         shr     eax, 8
3400         mov     bx, ax
3401
3402 //      mov     edx, Tmap.DeltaUFrac
3403
3404         cmp     Tmap.WidthModLength, 1
3405         jle     NoDeltaLight
3406
3407         push    ebx
3408         
3409         mov     ebx, Tmap.fx_l_right
3410         shr     ebx, 8
3411         
3412         sub     ebx, eax
3413         mov     eax, ebx
3414         
3415         mov     eax, Tmap.fx_dl_dx
3416         shr     eax, 8
3417
3418         mov     edx, Tmap.DeltaUFrac
3419         mov     dx, ax
3420         mov     Tmap.DeltaUFrac, edx
3421
3422         pop     ebx
3423
3424 NoDeltaLight:
3425
3426         mov     ebp, Tmap.fx_w
3427
3428         mov     eax, edi
3429         sub     eax, Tmap.pScreenBits
3430         shl     eax, 2
3431         mov     edx, gr_zbuffer
3432         add     edx, eax
3433
3434         inc     Tmap.WidthModLength
3435         mov     eax,Tmap.WidthModLength
3436         shr     eax, 1
3437         jz              one_more_pix
3438         pushf
3439         mov     Tmap.WidthModLength, eax
3440
3441         xor     eax, eax
3442
3443         mov     al,[edi]                    // preread the destination cache line
3444         mov     al,[esi]
3445
3446
3447
3448 NextPixel:
3449                         // Pixel 0
3450                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
3451                         jle     Skip0a                                                                  // If pixel is covered, skip drawing
3452                         mov     [edx+0], ebp                                                    // Write new Z value
3453
3454                         // Get pixel and light it
3455                         push    ebx
3456                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3457                         mov     al, [esi]                                                               // Get texel into AL
3458                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3459                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3460                         pop     ebx
3461
3462                         mov     [edi+0],al                                                              // Write new pixel
3463
3464 Skip0a: add     ecx,Tmap.DeltaVFrac
3465                         sbb     eax,eax
3466
3467                         //add   edx, 4                                                          // Go to next
3468                         add     ebp,Tmap.fx_dwdx
3469
3470                         add     ebx,Tmap.DeltaUFrac
3471
3472                         adc     esi,Tmap.uv_delta[4*eax+4]
3473
3474
3475                         // Pixel 1
3476                         cmp     ebp, [edx+4]                                                    // Compare the Z depth of this pixel with zbuffer
3477                         jle     Skip1a                                                                  // If pixel is covered, skip drawing
3478                         mov     [edx+4], ebp                                                    // Write new Z value
3479
3480                         // Get pixel and light it
3481                         push    ebx
3482                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3483                         mov     al, [esi]                                                               // Get texel into AL
3484                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3485                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3486                         pop     ebx
3487
3488                         mov     [edi+1],al                                                              // Write new pixel
3489
3490 Skip1a: add     ecx,Tmap.DeltaVFrac
3491                         sbb     eax,eax
3492
3493                         //add   edx, 4                                                          // Go to next
3494                         add     ebp,Tmap.fx_dwdx
3495
3496                         add     ebx,Tmap.DeltaUFrac
3497
3498                         adc     esi,Tmap.uv_delta[4*eax+4]
3499
3500
3501         add     edi, 2
3502         add     edx, 8
3503         dec     Tmap.WidthModLength
3504         jg              NextPixel
3505
3506         popf
3507         jnc     FPUReturn
3508
3509 one_more_pix:   
3510
3511                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
3512                         jle     Skip0c                                                                  // If pixel is covered, skip drawing
3513                         mov     [edx+0], ebp                                                    // Write new Z value
3514
3515                         // Get pixel and light it
3516                         push    ebx
3517                         xor     eax, eax                                                                        // Clear all bits of EAX.  This avoids a partial register stall on Pentium Pros
3518                         mov     al, [esi]                                                               // Get texel into AL
3519                         and     ebx, 0ff00h                                                             // Clear out fractional part of EBX
3520                         mov     eax, DWORD PTR gr_fade_table[eax+ebx]           // Lookup pixel in lighting table
3521                         pop     ebx
3522
3523                         mov     [edi+0],al                                                              // Write new pixel
3524
3525 Skip0c: 
3526
3527 FPUReturn:
3528
3529         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
3530                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
3531         ffree   st(0)
3532         ffree   st(1)
3533         ffree   st(2)
3534         ffree   st(3)
3535         ffree   st(4)
3536         ffree   st(5)
3537         ffree   st(6)
3538
3539         fldcw   Tmap.OldFPUCW                  // restore the FPU
3540
3541         pop     edi
3542         pop     esi
3543         pop     ebp
3544         pop     ebx
3545         pop     edx
3546         pop     ecx
3547         pop     eax
3548         }
3549 #endif
3550 }
3551
3552 void tmapscan_pln8_zbuffered_pentium()
3553 {
3554 #ifdef PLAT_UNIX
3555         STUB_FUNCTION;
3556 #else
3557         _asm {
3558         
3559         push    eax
3560         push    ecx
3561         push    edx
3562         push    ebx
3563         push    ebp
3564         push    esi
3565         push    edi
3566
3567         // Put the FPU in low precision mode
3568         fstcw           Tmap.OldFPUCW                                   // store copy of CW
3569         mov             ax,Tmap.OldFPUCW                                // get it in ax
3570         and             eax, ~0x300L
3571         mov             Tmap.FPUCW,ax                                   // store it
3572         fldcw           Tmap.FPUCW                                              // load the FPU
3573
3574
3575         mov             ecx, Tmap.loop_count            // ecx = width
3576         mov             edi, Tmap.dest_row_data // edi = dest pointer
3577
3578         // edi = pointer to start pixel in dest dib
3579         // ecx = spanwidth
3580
3581         mov             eax,ecx                                                 // eax and ecx = width
3582         shr             ecx,5                                                           // ecx = width / subdivision length
3583         and             eax,31                                                          // eax = width mod subdivision length
3584         jnz             some_left_over                                  // any leftover?
3585         dec             ecx                                                             // no, so special case last span
3586         mov             eax,32                                                          // it's 8 pixels long
3587 some_left_over:
3588         mov             Tmap.Subdivisions,ecx           // store widths
3589         mov             Tmap.WidthModLength,eax
3590
3591         // calculate ULeft and VLeft                    // FPU Stack (ZL = ZLeft)
3592                                                                                                         // st0  st1  st2  st3  st4  st5  st6  st7
3593         fld             Tmap.l.v                                        // V/ZL 
3594         fld             Tmap.l.u                                        // U/ZL V/ZL 
3595         fld             Tmap.l.sw                                       // 1/ZL U/ZL V/ZL 
3596         fld1                                                                                    // 1    1/ZL U/ZL V/ZL 
3597         fdiv            st,st(1)                                                        // ZL   1/ZL U/ZL V/ZL 
3598         fld             st                                                                      // ZL   ZL   1/ZL U/ZL V/ZL 
3599         fmul            st,st(4)                                                        // VL   ZL   1/ZL U/ZL V/ZL 
3600         fxch            st(1)                                                           // ZL   VL   1/ZL U/ZL V/ZL 
3601         fmul            st,st(3)                                                        // UL   VL   1/ZL U/ZL V/ZL 
3602
3603         fstp            st(5)                                                           // VL   1/ZL U/ZL V/ZL UL
3604         fstp            st(5)                                                           // 1/ZL U/ZL V/ZL UL   VL
3605
3606         // calculate right side OverZ terms  ; st0  st1  st2  st3  st4  st5  st6  st7
3607
3608         fadd            Tmap.fl_dwdx_wide                       // 1/ZR U/ZL V/ZL UL   VL
3609         fxch            st(1)                                                           // U/ZL 1/ZR V/ZL UL   VL
3610         fadd            Tmap.fl_dudx_wide                               // U/ZR 1/ZR V/ZL UL   VL
3611         fxch            st(2)                                                           // V/ZL 1/ZR U/ZR UL   VL
3612         fadd            Tmap.fl_dvdx_wide                               // V/ZR 1/ZR U/ZR UL   VL
3613
3614         // calculate right side coords          // st0  st1  st2  st3  st4  st5  st6  st7
3615
3616         fld1                                                                                    // 1    V/ZR 1/ZR U/ZR UL   VL
3617         // @todo overlap this guy
3618         fdiv            st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
3619         fld             st                                                                      // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
3620         fmul            st,st(2)                                                        // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
3621         fxch            st(1)                                                           // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
3622         fmul            st,st(4)                                                        // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3623
3624         cmp             ecx,0                                                   // check for any full spans
3625         jle      HandleLeftoverPixels
3626     
3627 SpanLoop:
3628
3629         // at this point the FPU contains       // st0  st1  st2  st3  st4  st5  st6  st7
3630                                                                                                         // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3631
3632         // convert left side coords
3633
3634         fld     st(5)                       ; UL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
3635         fmul    Tmap.FixedScale            ; UL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
3636         fistp   Tmap.UFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
3637
3638         fld     st(6)                       ; VL   UR   VR   V/ZR 1/ZR U/ZR UL   VL
3639         fmul    Tmap.FixedScale            ; VL16 UR   VR   V/ZR 1/ZR U/ZR UL   VL
3640         fistp   Tmap.VFixed                ; UR   VR   V/ZR 1/ZR U/ZR UL   VL
3641
3642         // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
3643
3644         fsubr   st(5),st                    ; UR   VR   V/ZR 1/ZR U/ZR dU   VL
3645         fxch    st(1)                       ; VR   UR   V/ZR 1/ZR U/ZR dU   VL
3646         fsubr   st(6),st                    ; VR   UR   V/ZR 1/ZR U/ZR dU   dV
3647         fxch    st(6)                       ; dV   UR   V/ZR 1/ZR U/ZR dU   VR
3648
3649         fmul    Tmap.FixedScale8           ; dV8  UR   V/ZR 1/ZR U/ZR dU   VR
3650         fistp   Tmap.DeltaV                ; UR   V/ZR 1/ZR U/ZR dU   VR
3651
3652         fxch    st(4)                       ; dU   V/ZR 1/ZR U/ZR UR   VR
3653         fmul    Tmap.FixedScale8           ; dU8  V/ZR 1/ZR U/ZR UR   VR
3654         fistp   Tmap.DeltaU                ; V/ZR 1/ZR U/ZR UR   VR
3655
3656         // increment terms for next span    // st0  st1  st2  st3  st4  st5  st6  st7
3657         // Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL   VL
3658
3659         fadd    Tmap.fl_dvdx_wide                               // V/ZR 1/ZL U/ZL UL   VL
3660         fxch    st(1)                                                           // 1/ZL V/ZR U/ZL UL   VL
3661         fadd    Tmap.fl_dwdx_wide                               // 1/ZR V/ZR U/ZL UL   VL
3662         fxch    st(2)                                                           // U/ZL V/ZR 1/ZR UL   VL
3663         fadd    Tmap.fl_dudx_wide                               // U/ZR V/ZR 1/ZR UL   VL
3664         fxch    st(2)                                                           // 1/ZR V/ZR U/ZR UL   VL
3665         fxch    st(1)                                                           // V/ZR 1/ZR U/ZR UL   VL
3666
3667
3668         // setup delta values
3669     
3670         mov     eax,Tmap.DeltaV                         // get v 16.16 step
3671         mov     ebx,eax                                                 // copy it
3672         sar     eax,16                                                          // get v int step
3673         shl     ebx,16                                                          // get v frac step
3674         mov     Tmap.DeltaVFrac,ebx                     // store it
3675         imul    eax,Tmap.src_offset                     // calculate texture step for v int step
3676
3677         mov     ebx,Tmap.DeltaU                         // get u 16.16 step
3678         mov     ecx,ebx                                                 // copy it
3679         sar     ebx,16                                                          // get u int step
3680         shl     ecx,16                                                          // get u frac step
3681         mov     Tmap.DeltaUFrac,ecx                     // store it
3682         add     eax,ebx                                                 // calculate uint + vint step
3683         mov     Tmap.uv_delta[4],eax                    // save whole step in non-v-carry slot
3684         add     eax,Tmap.src_offset                     // calculate whole step + v carry
3685         mov     Tmap.uv_delta[0],eax                    // save in v-carry slot
3686
3687         // setup initial coordinates
3688         mov     esi,Tmap.UFixed                         // get u 16.16 fixedpoint coordinate
3689
3690         mov     ebx,esi                                                 // copy it
3691         sar     esi,16                                                          // get integer part
3692         shl     ebx,16                                                          // get fractional part
3693
3694         mov     ecx,Tmap.VFixed                         // get v 16.16 fixedpoint coordinate
3695    
3696         mov     edx,ecx                                                 // copy it
3697         sar     edx,16                                                          // get integer part
3698         shl     ecx,16                                                          // get fractional part
3699         imul    edx,Tmap.src_offset                     // calc texture scanline address
3700         add     esi,edx                                                 // calc texture offset
3701         add     esi,Tmap.pixptr                         // calc address
3702
3703         // set up affine registers
3704
3705         mov     eax, Tmap.fx_l
3706         shr     eax, 8
3707         mov     bx, ax
3708
3709         mov     ebp, Tmap.fx_dl_dx
3710         shl     ebp, 5  //*32
3711         add     Tmap.fx_l, ebp
3712
3713         mov     ebp, Tmap.fx_l
3714         shr     ebp, 8
3715         sub     bp, ax
3716         shr     bp, 5
3717
3718         mov     edx, Tmap.DeltaUFrac
3719         mov     dx, bp
3720         mov     Tmap.DeltaUFrac, edx
3721
3722
3723         // calculate right side coords          st0  st1  st2  st3  st4  st5  st6  st7
3724         fld1                                                                            // 1    V/ZR 1/ZR U/ZR UL   VL
3725         // This divide should happen while the pixel span is drawn.
3726         fdiv    st,st(2)                                                        // ZR   V/ZR 1/ZR U/ZR UL   VL
3727
3728
3729         // 8 pixel span code
3730         // edi = dest dib bits at current pixel
3731         // esi = texture pointer at current u,v
3732         // eax = scratch
3733         // ebx = u fraction 0.32
3734         // ecx = v fraction 0.32
3735         // edx = u frac step
3736         // ebp = v carry scratch
3737
3738         mov     al,[edi]                                                                // preread the destination cache line
3739         mov     al,[esi]                                                                // get texture pixel 0
3740
3741         mov     Tmap.InnerLooper, 32/4                  // Set up loop counter
3742
3743         mov     ebp, Tmap.fx_w
3744
3745         mov     edx, gr_zbuffer
3746
3747         mov     eax, edi
3748         sub     eax, Tmap.pScreenBits
3749         shl     eax, 2
3750         add     edx, eax
3751
3752 InnerInnerLoop:
3753
3754                         // Pixel 0
3755                         mov     eax, ebx                                                                // Get lighting value from BH into AH
3756                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
3757
3758                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
3759                         mov     al, [esi]                                                       // Get texel into AL
3760                         jle     Skip0                                                                   // If pixel is covered, skip drawing
3761
3762                         mov     [edx+0], ebp                                                    // Write new Z value
3763
3764                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
3765                         mov     [edi+0],al                                                              // Write new pixel
3766
3767 Skip0:  add     ecx,Tmap.DeltaVFrac
3768                         sbb     eax,eax
3769
3770                         //add   edx, 4                                                          // Go to next
3771                         add     ebp,Tmap.fx_dwdx
3772
3773                         add     ebx,Tmap.DeltaUFrac
3774
3775                         adc     esi,Tmap.uv_delta[4*eax+4]
3776
3777
3778                         // Pixel 1
3779                         mov     eax, ebx                                                                // Get lighting value from BH into AH
3780                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
3781
3782                         cmp     ebp, [edx+4]                                                    // Compare the Z depth of this pixel with zbuffer
3783                         mov     al, [esi]                                                       // Get texel into AL
3784                         jle     Skip1                                                                   // If pixel is covered, skip drawing
3785
3786
3787                         mov     [edx+4], ebp                                                    // Write new Z value
3788
3789                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
3790                         mov     [edi+1],al                                                              // Write new pixel
3791
3792 Skip1:  add     ecx,Tmap.DeltaVFrac
3793                         sbb     eax,eax
3794
3795                         //add   edx, 4                                                          // Go to next
3796                         add     ebp,Tmap.fx_dwdx
3797
3798                         add     ebx,Tmap.DeltaUFrac
3799
3800                         adc     esi,Tmap.uv_delta[4*eax+4]
3801
3802                         // Pixel 2
3803
3804                         mov     eax, ebx                                                                // Get lighting value from BH into AH
3805                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
3806
3807
3808                         cmp     ebp, [edx+8]                                                    // Compare the Z depth of this pixel with zbuffer
3809                         mov     al, [esi]                                                       // Get texel into AL
3810                         jle     Skip2                                                                   // If pixel is covered, skip drawing
3811
3812
3813                         mov     [edx+8], ebp                                                    // Write new Z value
3814
3815                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
3816                         mov     [edi+2],al                                                              // Write new pixel
3817
3818 Skip2:  add     ecx,Tmap.DeltaVFrac
3819                         sbb     eax,eax
3820
3821                         //add   edx, 4                                                          // Go to next
3822                         add     ebp,Tmap.fx_dwdx
3823
3824                         add     ebx,Tmap.DeltaUFrac
3825
3826                         adc     esi,Tmap.uv_delta[4*eax+4]
3827
3828                         // Pixel 3
3829                         mov     eax, ebx                                                                // Get lighting value from BH into AH
3830                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
3831
3832
3833                         cmp     ebp, [edx+12]                                                   // Compare the Z depth of this pixel with zbuffer
3834                         mov     al, [esi]                                                       // Get texel into AL
3835                         jle     Skip3                                                                   // If pixel is covered, skip drawing
3836
3837
3838                         mov     [edx+12], ebp                                                   // Write new Z value
3839
3840                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
3841                         mov     [edi+3],al                                                              // Write new pixel
3842
3843 Skip3:  add     ecx,Tmap.DeltaVFrac
3844                         sbb     eax,eax
3845
3846                         //add   edx, 4                                                          // Go to next
3847                         add     ebp,Tmap.fx_dwdx
3848
3849                         add     ebx,Tmap.DeltaUFrac
3850
3851                         adc     esi,Tmap.uv_delta[4*eax+4]
3852
3853
3854         add     edi, 4
3855         add     edx, 16
3856         dec     Tmap.InnerLooper
3857         jnz     InnerInnerLoop
3858
3859         mov     Tmap.fx_w, ebp
3860
3861         // the fdiv is done, finish right       // st0  st1  st2  st3  st4  st5  st6  st7
3862                                             // ZR   V/ZR 1/ZR U/ZR UL   VL
3863
3864     fld     st                                                                  // ZR   ZR   V/ZR 1/ZR U/ZR UL   VL
3865     fmul    st,st(2)                                                    // VR   ZR   V/ZR 1/ZR U/ZR UL   VL
3866     fxch    st(1)                                                               // ZR   VR   V/ZR 1/ZR U/ZR UL   VL
3867     fmul    st,st(4)                                                    // UR   VR   V/ZR 1/ZR U/ZR UL   VL
3868
3869     dec     Tmap.Subdivisions                   // decrement span count
3870     jnz     SpanLoop                                                    // loop back
3871
3872
3873 HandleLeftoverPixels:
3874
3875     mov     esi,Tmap.pixptr                             // load texture pointer
3876
3877     // edi = dest dib bits
3878     // esi = current texture dib bits
3879     // at this point the FPU contains    ; st0  st1  st2  st3  st4  st5  st6  st7
3880     // inv. means invalid numbers        ; inv. inv. inv. inv. inv. UL   VL
3881
3882     cmp     Tmap.WidthModLength,0          ; are there remaining pixels to draw?
3883     jz      FPUReturn                   ; nope, pop the FPU and bail
3884
3885     // convert left side coords          ; st0  st1  st2  st3  st4  st5  st6  st7
3886
3887     fld     st(5)                       ; UL   inv. inv. inv. inv. inv. UL   VL
3888     fmul    Tmap.FixedScale                ; UL16 inv. inv. inv. inv. inv. UL   VL
3889     fistp   Tmap.UFixed                    ; inv. inv. inv. inv. inv. UL   VL
3890
3891     fld     st(6)                       ; VL   inv. inv. inv. inv. inv. UL   VL
3892     fmul    Tmap.FixedScale                // VL16 inv. inv. inv. inv. inv. UL   VL
3893     fistp   Tmap.VFixed                    ; inv. inv. inv. inv. inv. UL   VL
3894
3895     dec     Tmap.WidthModLength            ; calc how many steps to take
3896     jz      OnePixelSpan                ; just one, do not do deltas
3897
3898     // calculate right edge coordinates  ; st0  st1  st2  st3  st4  st5  st6  st7
3899     // r -> R+1
3900
3901     // @todo rearrange things so we don't need these two instructions
3902     fstp    Tmap.FloatTemp                 ; inv. inv. inv. inv. UL   VL
3903     fstp    Tmap.FloatTemp                 ; inv. inv. inv. UL   VL
3904
3905     fld     Tmap.r.v           ; V/Zr inv. inv. inv. UL   VL
3906     fsub    Tmap.deltas.v             ; V/ZR inv. inv. inv. UL   VL
3907     fld     Tmap.r.u           ; U/Zr V/ZR inv. inv. inv. UL   VL
3908     fsub    Tmap.deltas.u             ; U/ZR V/ZR inv. inv. inv. UL   VL
3909     fld     Tmap.r.sw              ; 1/Zr U/ZR V/ZR inv. inv. inv. UL   VL
3910     fsub    Tmap.deltas.sw           ; 1/ZR U/ZR V/ZR inv. inv. inv. UL   VL
3911
3912     fdivr   Tmap.One                       ; ZR   U/ZR V/ZR inv. inv. inv. UL   VL
3913
3914     fmul    st(1),st                    ; ZR   UR   V/ZR inv. inv. inv. UL   VL
3915     fmulp   st(2),st                    ; UR   VR   inv. inv. inv. UL   VL
3916
3917     // calculate deltas                  ; st0  st1  st2  st3  st4  st5  st6  st7
3918
3919     fsubr   st(5),st                    ; UR   VR   inv. inv. inv. dU   VL
3920     fxch    st(1)                       ; VR   UR   inv. inv. inv. dU   VL
3921     fsubr   st(6),st                    ; VR   UR   inv. inv. inv. dU   dV
3922     fxch    st(6)                       ; dV   UR   inv. inv. inv. dU   VR
3923
3924     fidiv   Tmap.WidthModLength            ; dv   UR   inv. inv. inv. dU   VR
3925     fmul    Tmap.FixedScale                ; dv16 UR   inv. inv. inv. dU   VR
3926     fistp   Tmap.DeltaV                    ; UR   inv. inv. inv. dU   VR
3927
3928     fxch    st(4)                       ; dU   inv. inv. inv. UR   VR
3929     fidiv   Tmap.WidthModLength            ; du   inv. inv. inv. UR   VR
3930     fmul    Tmap.FixedScale                ; du16 inv. inv. inv. UR   VR
3931     fistp   Tmap.DeltaU                    ; inv. inv. inv. UR   VR
3932
3933     // @todo gross!  these are to line up with the other loop
3934     fld     st(1)                       ; inv. inv. inv. inv. UR   VR
3935     fld     st(2)                       ; inv. inv. inv. inv. inv. UR   VR
3936
3937
3938         // setup delta values
3939         mov     eax, Tmap.DeltaV        // get v 16.16 step
3940         mov     ebx, eax                                                // copy it
3941         sar     eax, 16                                         // get v int step
3942         shl     ebx, 16                                         // get v frac step
3943         mov     Tmap.DeltaVFrac, ebx    // store it
3944         imul    eax, Tmap.src_offset    // calc texture step for v int step
3945         
3946         mov     ebx, Tmap.DeltaU                        // get u 16.16 step
3947         mov     ecx, ebx                                                // copy it
3948         sar     ebx, 16                                         // get the u int step
3949         shl     ecx, 16                                         // get the u frac step
3950         mov     Tmap.DeltaUFrac, ecx                    // store it
3951         add     eax, ebx                                                // calc uint + vint step
3952         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
3953         add     eax, Tmap.src_offset                            // calc whole step + v carry
3954         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
3955
3956
3957 OnePixelSpan:
3958
3959         ; setup initial coordinates
3960         mov     esi, Tmap.UFixed                        // get u 16.16
3961         mov     ebx, esi                                                // copy it
3962         sar     esi, 16                                         // get integer part
3963         shl     ebx, 16                                         // get fractional part
3964
3965         mov     ecx, Tmap.VFixed                        // get v 16.16 
3966         mov     edx, ecx                                                // copy it
3967         sar     edx, 16                                         // get integer part
3968         shl     ecx, 16                                         // get fractional part
3969         imul    edx, Tmap.src_offset            // calc texture scanline address
3970         add     esi, edx                                                        // calc texture offset
3971         add     esi, Tmap.pixptr                        // calc address
3972
3973
3974         mov     eax, Tmap.fx_l
3975         shr     eax, 8
3976         mov     bx, ax
3977
3978 //      mov     edx, Tmap.DeltaUFrac
3979
3980         cmp     Tmap.WidthModLength, 1
3981         jle     NoDeltaLight
3982
3983         push    ebx
3984         
3985         mov     ebx, Tmap.fx_l_right
3986         shr     ebx, 8
3987         
3988         sub     ebx, eax
3989         mov     eax, ebx
3990         
3991         mov     eax, Tmap.fx_dl_dx
3992         shr     eax, 8
3993
3994         mov     edx, Tmap.DeltaUFrac
3995         mov     dx, ax
3996         mov     Tmap.DeltaUFrac, edx
3997
3998         pop     ebx
3999
4000 NoDeltaLight:
4001
4002         mov     ebp, Tmap.fx_w
4003
4004         mov     eax, edi
4005         sub     eax, Tmap.pScreenBits
4006         mov     edx, gr_zbuffer
4007         shl     eax, 2
4008         add     edx, eax
4009
4010         inc     Tmap.WidthModLength
4011         mov     eax,Tmap.WidthModLength
4012         shr     eax, 1
4013         jz              one_more_pix
4014         pushf
4015         mov     Tmap.WidthModLength, eax
4016
4017         xor     eax, eax
4018
4019         mov     al,[edi]                    // preread the destination cache line
4020         mov     al,[esi]
4021
4022
4023
4024 NextPixel:
4025                         // Pixel 0
4026                         mov     eax, ebx                                                                // Get lighting value from BH into AH
4027                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
4028
4029                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
4030                         mov     al, [esi]                                                       // Get texel into AL
4031                         jle     Skip0a                                                                  // If pixel is covered, skip drawing
4032
4033
4034                         mov     [edx+0], ebp                                                    // Write new Z value
4035
4036                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
4037                         mov     [edi+0],al                                                              // Write new pixel
4038
4039 Skip0a: add     ecx,Tmap.DeltaVFrac
4040                         sbb     eax,eax
4041
4042                         //add   edx, 4                                                          // Go to next
4043                         add     ebp,Tmap.fx_dwdx
4044
4045                         add     ebx,Tmap.DeltaUFrac
4046
4047                         adc     esi,Tmap.uv_delta[4*eax+4]
4048
4049
4050                         // Pixel 1
4051                         mov     eax, ebx                                                                // Get lighting value from BH into AH
4052                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
4053
4054
4055                         cmp     ebp, [edx+4]                                                    // Compare the Z depth of this pixel with zbuffer
4056                         mov     al, [esi]                                                       // Get texel into AL
4057                         jle     Skip1a                                                                  // If pixel is covered, skip drawing
4058
4059                         mov     [edx+4], ebp                                                    // Write new Z value
4060
4061                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
4062                         mov     [edi+1],al                                                              // Write new pixel
4063
4064 Skip1a: add     ecx,Tmap.DeltaVFrac
4065                         sbb     eax,eax
4066
4067                         //add   edx, 4                                                          // Go to next
4068                         add     ebp,Tmap.fx_dwdx
4069
4070                         add     ebx,Tmap.DeltaUFrac
4071
4072                         adc     esi,Tmap.uv_delta[4*eax+4]
4073
4074
4075         add     edi, 2
4076         add     edx, 8
4077         dec     Tmap.WidthModLength
4078         jg              NextPixel
4079
4080         popf
4081         jnc     FPUReturn
4082
4083 one_more_pix:   
4084
4085                         mov     eax, ebx                                                                // Get lighting value from BH into AH
4086                         and     eax, 0ffffh;                                            // Clear upper bits of EAX
4087
4088                         cmp     ebp, [edx+0]                                                    // Compare the Z depth of this pixel with zbuffer
4089                         mov     al, [esi]                                                       // Get texel into AL
4090                         jle     Skip0c                                                                  // If pixel is covered, skip drawing
4091
4092                         mov     al, gr_fade_table[eax]                  // Lookup pixel in lighting table
4093
4094                         mov     [edx+0], ebp                                                    // Write new Z value
4095
4096                         mov     [edi+0],al                                                              // Write new pixel
4097
4098 Skip0c: 
4099
4100 FPUReturn:
4101
4102         // busy FPU registers:  // st0  st1  st2  st3  st4  st5  st6  st7
4103                                                                         // xxx  xxx  xxx  xxx  xxx  xxx  xxx
4104         ffree   st(0)
4105         ffree   st(1)
4106         ffree   st(2)
4107         ffree   st(3)
4108         ffree   st(4)
4109         ffree   st(5)
4110         ffree   st(6)
4111
4112         fldcw   Tmap.OldFPUCW                  // restore the FPU
4113
4114         pop     edi
4115         pop     esi
4116         pop     ebp
4117         pop     ebx
4118         pop     edx
4119         pop     ecx
4120         pop     eax
4121         }
4122 #endif
4123 }
4124
4125 void tmapscan_pln8_zbuffered()
4126 {
4127         if ( Gr_cpu     > 5 )   {
4128                 // Pentium Pro optimized code.
4129                 tmapscan_pln8_zbuffered_ppro();
4130         } else {
4131                 tmapscan_pln8_zbuffered_pentium();
4132         }
4133 }
4134
4135 void tmapscan_lnaa8_zbuffered()
4136 {
4137 #ifndef HARDWARE_ONLY
4138         Tmap.lookup = (uint)&Current_alphacolor->table.lookup[0][0];
4139
4140 #ifdef PLAT_UNIX
4141         STUB_FUNCTION;
4142 #else
4143         _asm {
4144         push    eax
4145         push    ecx
4146         push    edx
4147         push    ebx
4148         push    ebp
4149         push    esi
4150         push    edi
4151
4152         ; setup delta values
4153         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
4154         mov     ebx, eax                                                // copy it
4155         sar     eax, 16                                         // get v int step
4156         shl     ebx, 16                                         // get v frac step
4157         mov     Tmap.DeltaVFrac, ebx    // store it
4158         imul    eax, Tmap.src_offset    // calc texture step for v int step
4159         
4160         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
4161         mov     ecx, ebx                                                // copy it
4162         sar     ebx, 16                                         // get the u int step
4163         shl     ecx, 16                                         // get the u frac step
4164         mov     Tmap.DeltaUFrac, ecx                    // store it
4165         add     eax, ebx                                                // calc uint + vint step
4166
4167         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
4168         add     eax, Tmap.src_offset                            // calc whole step + v carry
4169         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
4170
4171         ; setup initial coordinates
4172         mov     esi, Tmap.fx_u                  // get u 16.16
4173         mov     ebx, esi                                                // copy it
4174         sar     esi, 16                                         // get integer part
4175         shl     ebx, 16                                         // get fractional part
4176
4177         mov     ecx, Tmap.fx_v                  // get v 16.16 
4178         mov     edx, ecx                                                // copy it
4179         sar     edx, 16                                         // get integer part
4180         shl     ecx, 16                                         // get fractional part
4181         imul    edx, Tmap.src_offset            // calc texture scanline address
4182         add     esi, edx                                                        // calc texture offset
4183         add     esi, Tmap.pixptr                        // calc address
4184         
4185         ; set edi = address of first pixel to modify
4186         mov     edi, Tmap.dest_row_data
4187         
4188         xor     eax, eax
4189         mov     al,[edi]                                                        // get the destination pixel
4190
4191         mov     ebp, Tmap.fx_w
4192         mov     edx, gr_zbuffer
4193         mov     eax, edi
4194         sub     eax, Tmap.pScreenBits
4195         shl     eax, 2
4196         add     edx, eax
4197
4198         mov     eax, Tmap.loop_count
4199
4200         shr     eax, 2
4201         je              DoLeftOverPixels
4202
4203         mov     Tmap.num_big_steps, eax
4204         and     Tmap.loop_count, 3
4205
4206 NextPixelBlock:
4207
4208     // 8 pixel span code
4209     // edi = dest dib bits at current pixel
4210     // esi = texture pointer at current u,v
4211     // eax = scratch
4212     // ebx = u fraction 0.32
4213     // ecx = v fraction 0.32
4214     // edx = u frac step
4215     // ebp = v carry scratch
4216
4217         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
4218         jle     Skip0a                                                          // If pixel is covered, skip drawing
4219 //      mov     [edx+4*0], ebp                                          // Write new Z value
4220         mov     al,[edi+0]                                                      // get the destination pixel
4221         mov     ah,[esi]                                                                // get texture pixel 0
4222         and     eax, 0ffffh
4223         add     eax, Tmap.lookup
4224         mov     al, [eax]                       // blend them
4225         mov     [edi+0],al                                                      // store pixel
4226 Skip0a:
4227         add     ebp, Tmap.fx_dwdx
4228         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4229         sbb     eax,eax                                                         // get -1 if carry
4230         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4231         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4232
4233
4234         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
4235         jle     Skip1a                                                          // If pixel is covered, skip drawing
4236 //      mov     [edx+4*1], ebp                                          // Write new Z value
4237         mov     al,[edi+1]                                                      // get the destination pixel
4238         mov     ah,[esi]                                                                // get texture pixel 0
4239         and     eax, 0ffffh
4240         add     eax, Tmap.lookup
4241         mov     al, [eax]                       // blend them
4242         mov     [edi+1],al                                                      // store pixel
4243 Skip1a:
4244         add     ebp, Tmap.fx_dwdx
4245         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4246         sbb     eax,eax                                                         // get -1 if carry
4247         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4248         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4249
4250         cmp     ebp, [edx+4*2]                                          // Compare the Z depth of this pixel with zbuffer
4251         jle     Skip2a                                                          // If pixel is covered, skip drawing
4252 //      mov     [edx+4*2], ebp                                          // Write new Z value
4253         mov     al,[edi+2]                                                      // get the destination pixel
4254         mov     ah,[esi]                                                                // get texture pixel 0
4255         and     eax, 0ffffh
4256         add     eax, Tmap.lookup
4257         mov     al, [eax]                       // blend them
4258         mov     [edi+2],al                                                      // store pixel
4259 Skip2a:
4260         add     ebp, Tmap.fx_dwdx
4261         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4262         sbb     eax,eax                                                         // get -1 if carry
4263         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4264         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4265
4266         cmp     ebp, [edx+4*3]                                          // Compare the Z depth of this pixel with zbuffer
4267         jle     Skip3a                                                          // If pixel is covered, skip drawing
4268 //      mov     [edx+4*3], ebp                                          // Write new Z value
4269         mov     al,[edi+3]                                                      // get the destination pixel
4270         mov     ah,[esi]                                                                // get texture pixel 0
4271         and     eax, 0ffffh
4272         add     eax, Tmap.lookup
4273         mov     al, [eax]                       // blend them
4274         mov     [edi+3],al                                                      // store pixel
4275 Skip3a:
4276         add     ebp, Tmap.fx_dwdx
4277         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4278         sbb     eax,eax                                                         // get -1 if carry
4279         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4280         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4281
4282         add     edx, 16
4283         add     edi, 4
4284         dec     Tmap.num_big_steps
4285         jne     NextPixelBlock
4286         
4287
4288 DoLeftOverPixels:
4289
4290         mov     eax,Tmap.loop_count
4291         test    eax, -1
4292         jz      _none_to_do
4293         shr     eax, 1
4294         je      one_more_pix
4295         mov     Tmap.loop_count, eax
4296         pushf
4297
4298         xor     eax, eax
4299         mov     al,[edi]                                                        // get the destination pixel
4300
4301 NextPixel:
4302
4303         cmp     ebp, [edx+4*0]                                          // Compare the Z depth of this pixel with zbuffer
4304         jle     Skip0b                                                          // If pixel is covered, skip drawing
4305 //      mov     [edx+4*0], ebp                                          // Write new Z value
4306         mov     al,[edi+0]                                                      // get the destination pixel
4307         mov     ah,[esi]                                                                // get texture pixel 0
4308         and     eax, 0ffffh
4309         add     eax, Tmap.lookup
4310         mov     al, [eax]                       // blend them
4311         mov     [edi+0],al                                                      // store pixel
4312 Skip0b:
4313         add     ebp, Tmap.fx_dwdx
4314         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4315         sbb     eax,eax                                                         // get -1 if carry
4316         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4317         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4318
4319         cmp     ebp, [edx+4*1]                                          // Compare the Z depth of this pixel with zbuffer
4320         jle     Skip1b                                                          // If pixel is covered, skip drawing
4321 //      mov     [edx+4*1], ebp                                          // Write new Z value
4322         mov     al,[edi+1]                                                      // get the destination pixel
4323         mov     ah,[esi]                                                                // get texture pixel 0
4324         and     eax, 0ffffh
4325         add     eax, Tmap.lookup
4326         mov     al, [eax]                       // blend them
4327         mov     [edi+1],al                                                      // store pixel
4328 Skip1b:
4329         add     ebp, Tmap.fx_dwdx
4330         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4331         sbb     eax,eax                                                         // get -1 if carry
4332         add     ebx,Tmap.DeltaUFrac                             // increment u fraction
4333         adc     esi,Tmap.uv_delta[4*eax+4]              // add in step ints & carries
4334
4335         add     edi, 2
4336         add     edx, 8
4337         dec     Tmap.loop_count
4338         jne     NextPixel
4339
4340         popf
4341         jnc     _none_to_do
4342
4343 one_more_pix:   
4344         cmp     ebp, [edx]                                              // Compare the Z depth of this pixel with zbuffer
4345         jle     Skip0c                                                          // If pixel is covered, skip drawing
4346 //      mov     [edx], ebp                                              // Write new Z value
4347         mov     al,[edi]                                                        // get the destination pixel
4348         mov     ah,[esi]                                                        // get texture pixel 0
4349         and     eax, 0ffffh
4350         add     eax, Tmap.lookup
4351         mov     al, [eax]                       // blend them
4352         mov     [edi],al                                                        // store pixel
4353 Skip0c:
4354
4355 _none_to_do:    
4356         pop     edi
4357         pop     esi
4358         pop     ebp
4359         pop     ebx
4360         pop     edx
4361         pop     ecx
4362         pop     eax
4363         }
4364 #endif
4365 #else
4366         Int3();
4367 #endif
4368 }
4369
4370 void tmapscan_lnaa8()
4371 {
4372 #ifndef HARDWARE_ONLY
4373         if (gr_zbuffering) {
4374                 switch(gr_zbuffering_mode)      {
4375                 case GR_ZBUFF_NONE:
4376                         break;
4377                 case GR_ZBUFF_FULL:             // both
4378                 case GR_ZBUFF_WRITE:            // write only
4379                 case GR_ZBUFF_READ:             // read only
4380                         tmapscan_lnaa8_zbuffered();
4381                         return;
4382                 }
4383
4384         }
4385
4386         Tmap.lookup = (uint)&Current_alphacolor->table.lookup[0][0];
4387
4388 #ifdef PLAT_UNIX
4389         STUB_FUNCTION;
4390 #else
4391         _asm {
4392         push    eax
4393         push    ecx
4394         push    edx
4395         push    ebx
4396         push    ebp
4397         push    esi
4398         push    edi
4399
4400         ; setup delta values
4401         mov     eax, Tmap.fx_dv_dx      // get v 16.16 step
4402         mov     ebx, eax                                                // copy it
4403         sar     eax, 16                                         // get v int step
4404         shl     ebx, 16                                         // get v frac step
4405         mov     Tmap.DeltaVFrac, ebx    // store it
4406         imul    eax, Tmap.src_offset    // calc texture step for v int step
4407         
4408         mov     ebx, Tmap.fx_du_dx              // get u 16.16 step
4409         mov     ecx, ebx                                                // copy it
4410         sar     ebx, 16                                         // get the u int step
4411         shl     ecx, 16                                         // get the u frac step
4412         mov     Tmap.DeltaUFrac, ecx                    // store it
4413         add     eax, ebx                                                // calc uint + vint step
4414
4415         mov     Tmap.uv_delta[4], eax   // save whole step in non-v-carry slot
4416         add     eax, Tmap.src_offset                            // calc whole step + v carry
4417         mov     Tmap.uv_delta[0], eax   // save in v-carry slot
4418
4419         ; setup initial coordinates
4420         mov     esi, Tmap.fx_u                  // get u 16.16
4421         mov     ebx, esi                                                // copy it
4422         sar     esi, 16                                         // get integer part
4423         shl     ebx, 16                                         // get fractional part
4424
4425         mov     ecx, Tmap.fx_v                  // get v 16.16 
4426         mov     edx, ecx                                                // copy it
4427         sar     edx, 16                                         // get integer part
4428         shl     ecx, 16                                         // get fractional part
4429         imul    edx, Tmap.src_offset            // calc texture scanline address
4430         add     esi, edx                                                        // calc texture offset
4431         add     esi, Tmap.pixptr                        // calc address
4432         
4433         ; set edi = address of first pixel to modify
4434         mov     edi, Tmap.dest_row_data
4435         
4436         mov     edx, Tmap.DeltaUFrac
4437
4438         xor     eax, eax
4439         mov     al,[edi]                                                        // get the destination pixel
4440
4441         mov     ebp, Tmap.loop_count
4442
4443         shr     ebp, 2
4444         je              DoLeftOverPixels
4445
4446         mov     Tmap.num_big_steps, ebp
4447         and     Tmap.loop_count, 3
4448
4449
4450 NextPixelBlock:
4451
4452     // 8 pixel span code
4453     // edi = dest dib bits at current pixel
4454     // esi = texture pointer at current u,v
4455     // eax = scratch
4456     // ebx = u fraction 0.32
4457     // ecx = v fraction 0.32
4458     // edx = u frac step
4459     // ebp = v carry scratch
4460
4461
4462         mov     al,[edi+0]                                                      // get the destination pixel
4463         mov     ah,[esi]                                                                // get texture pixel 0
4464         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4465         sbb     ebp,ebp                                                         // get -1 if carry
4466         add     ebx,edx                                                         // increment u fraction
4467         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4468         add     eax, Tmap.lookup
4469         mov     al, [eax]                       // blend them
4470         mov     [edi+0],al                                                      // store pixel
4471
4472         mov     al,[edi+1]                                                      // get the destination pixel
4473         mov     ah,[esi]                                                                // get texture pixel 0
4474         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4475         sbb     ebp,ebp                                                         // get -1 if carry
4476         add     ebx,edx                                                         // increment u fraction
4477         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4478         add     eax, Tmap.lookup
4479         mov     al, [eax]                       // blend them
4480         mov     [edi+1],al                                                      // store pixel
4481
4482         mov     al,[edi+2]                                                      // get the destination pixel
4483         mov     ah,[esi]                                                                // get texture pixel 0
4484         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4485         sbb     ebp,ebp                                                         // get -1 if carry
4486         add     ebx,edx                                                         // increment u fraction
4487         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4488         add     eax, Tmap.lookup
4489         mov     al, [eax]                       // blend them
4490         mov     [edi+2],al                                                      // store pixel
4491
4492         mov     al,[edi+3]                                                      // get the destination pixel
4493         mov     ah,[esi]                                                                // get texture pixel 0
4494         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4495         sbb     ebp,ebp                                                         // get -1 if carry
4496         add     ebx,edx                                                         // increment u fraction
4497         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4498         add     eax, Tmap.lookup
4499         mov     al, [eax]                       // blend them
4500         mov     [edi+3],al                                                      // store pixel
4501
4502         add     edi, 4
4503         dec     Tmap.num_big_steps
4504         jne     NextPixelBlock
4505         
4506
4507 DoLeftOverPixels:
4508
4509         mov     ebp,Tmap.loop_count
4510         test    ebp, -1
4511         jz      _none_to_do
4512         shr     ebp, 1
4513         je      one_more_pix
4514         mov     Tmap.loop_count, ebp
4515         pushf
4516
4517         xor     eax, eax
4518         mov     al,[edi]                                                        // get the destination pixel
4519
4520 NextPixel:
4521
4522         mov     al,[edi+0]                                                      // get the destination pixel
4523         mov     ah,[esi]                                                                // get texture pixel 0
4524         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4525         sbb     ebp,ebp                                                         // get -1 if carry
4526         add     ebx,edx                                                         // increment u fraction
4527         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4528         add     eax, Tmap.lookup
4529         mov     al, [eax]                       // blend them
4530         mov     [edi+0],al                                                      // store pixel
4531
4532         mov     al,[edi+1]                                                      // get the destination pixel
4533         mov     ah,[esi]                                                                // get texture pixel 0
4534         add     ecx,Tmap.DeltaVFrac                             // increment v fraction
4535         sbb     ebp,ebp                                                         // get -1 if carry
4536         add     ebx,edx                                                         // increment u fraction
4537         adc     esi,Tmap.uv_delta[4*ebp+4]              // add in step ints & carries
4538         add     eax, Tmap.lookup
4539         mov     al, [eax]                       // blend them
4540         mov     [edi+1],al                                                      // store pixel
4541
4542         add     edi, 2
4543         dec     Tmap.loop_count
4544         jne     NextPixel
4545
4546         popf
4547         jnc     _none_to_do
4548
4549 one_more_pix:   
4550         mov     al,[edi]                                                        // get the destination pixel
4551         mov     ah,[esi]                                                        // get texture pixel 0
4552         add     eax, Tmap.lookup
4553         mov     al, [eax]                       // blend them
4554         mov     [edi],al                                                        // store pixel
4555
4556 _none_to_do:    
4557         pop     edi
4558         pop     esi
4559         pop     ebp
4560         pop     ebx
4561         pop     edx
4562         pop     ecx
4563         pop     eax
4564         }
4565 #endif
4566 #else
4567         Int3();
4568 #endif
4569 }
4570
4571
4572
4573
4574