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