mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 04:31:35 -10:00
4527 lines
124 KiB
C++
4527 lines
124 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/Graphics/TmapScanline.cpp $
|
|
* $Revision: 2.1 $
|
|
* $Date: 2002-08-01 01:41:05 $
|
|
* $Author: penguin $
|
|
*
|
|
* Routines to draw one textured mapped scanline.
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 2.0 2002/06/03 04:02:23 penguin
|
|
* Warpcore CVS sync
|
|
*
|
|
* Revision 1.1 2002/05/02 18:03:07 mharris
|
|
* Initial checkin - converted filenames and includes to lower case
|
|
*
|
|
*
|
|
* 5 12/02/98 5:47p Dave
|
|
* Put in interface xstr code. Converted barracks screen to new format.
|
|
*
|
|
* 4 11/30/98 5:31p Dave
|
|
* Fixed up Fred support for software mode.
|
|
*
|
|
* 3 11/30/98 1:07p Dave
|
|
* 16 bit conversion, first run.
|
|
*
|
|
* 2 10/07/98 10:53a Dave
|
|
* Initial checkin.
|
|
*
|
|
* 1 10/07/98 10:49a Dave
|
|
*
|
|
* 21 4/20/98 4:44p John
|
|
* Fixed problems with black being xparent on model cache rneders. Made
|
|
* model cache key off of detail level setting and framerate.
|
|
*
|
|
* 20 4/09/98 7:58p John
|
|
* Cleaned up tmapper code a bit. Put NDEBUG around some ndebug stuff.
|
|
* Took out XPARENT flag settings in all the alpha-blended texture stuff.
|
|
*
|
|
* 19 3/22/98 2:33p John
|
|
* Took out fx_v/v_right. Made fx_u etc get calculated in tmapper.
|
|
*
|
|
* 18 3/10/98 4:19p John
|
|
* Cleaned up graphics lib. Took out most unused gr functions. Made D3D
|
|
* & Glide have popups and print screen. Took out all >8bpp software
|
|
* support. Made Fred zbuffer. Made zbuffer allocate dynamically to
|
|
* support Fred. Made zbuffering key off of functions rather than one
|
|
* global variable.
|
|
*
|
|
* 17 12/10/96 10:37a John
|
|
* Restructured texture mapper to remove some overhead from each scanline
|
|
* setup. This gave about a 30% improvement drawing trans01.pof, which is
|
|
* a really complex model. In the process, I cleaned up the scanline
|
|
* functions and separated them into different modules for each pixel
|
|
* depth.
|
|
*
|
|
* 16 12/02/96 4:03p John
|
|
* made texture divide pipeline better. 2.5% speedup.
|
|
*
|
|
* 15 11/26/96 6:50p John
|
|
* Added some more hicolor primitives. Made windowed mode run as current
|
|
* bpp, if bpp is 8,16,or 32.
|
|
*
|
|
* 14 11/18/96 9:58a John
|
|
* Fixed warnings
|
|
*
|
|
* 13 11/07/96 6:19p John
|
|
* Added a bunch of 16bpp primitives so the game sort of runs in 16bpp
|
|
* mode.
|
|
*
|
|
* 12 11/07/96 3:49p John
|
|
* Fixed some old 'c' inner loop code for testing.
|
|
*
|
|
* 11 11/07/96 2:17p John
|
|
* Took out the OldTmapper stuff.
|
|
*
|
|
* 10 11/05/96 4:05p John
|
|
* Added roller. Added code to draw a distant planet. Made bm_load
|
|
* return -1 if invalid bitmap.
|
|
*
|
|
* 9 10/31/96 7:20p John
|
|
* Added per,tiled tmapper. Made models tile if they use 64x64 textures.
|
|
*
|
|
* 8 10/26/96 1:40p John
|
|
* Added some now primitives to the 2d library and
|
|
* cleaned up some old ones.
|
|
*
|
|
* $NoKeywords: $
|
|
*/
|
|
|
|
#include "render/3d.h"
|
|
#include "graphics/2d.h"
|
|
#include "graphics/grinternal.h"
|
|
#include "graphics/tmapper.h"
|
|
#include "graphics/tmapscanline.h"
|
|
#include "math/floating.h"
|
|
#include "palman/palman.h"
|
|
#include "math/fix.h"
|
|
#include "io/key.h"
|
|
|
|
// Needed to keep warning 4725 to stay away. See PsTypes.h for details why.
|
|
void disable_warning_4725_stub_ts32()
|
|
{
|
|
}
|
|
|
|
|
|
extern void tmapscan_pln8_tiled_256x256();
|
|
extern void tmapscan_pln8_tiled_128x128();
|
|
extern void tmapscan_pln8_tiled_64x64();
|
|
extern void tmapscan_pln8_tiled_32x32();
|
|
extern void tmapscan_pln8_tiled_16x16();
|
|
|
|
|
|
void tmapscan_pln8_tiled()
|
|
{
|
|
if ( (Tmap.bp->w == 256) && (Tmap.bp->h == 256) ) {
|
|
tmapscan_pln8_tiled_256x256();
|
|
} else if ( (Tmap.bp->w == 128) && (Tmap.bp->h == 128) ) {
|
|
tmapscan_pln8_tiled_128x128();
|
|
} else if ( (Tmap.bp->w == 64) && (Tmap.bp->h == 64) ) {
|
|
tmapscan_pln8_tiled_64x64();
|
|
} else if ( (Tmap.bp->w == 32) && (Tmap.bp->h == 32) ) {
|
|
tmapscan_pln8_tiled_32x32();
|
|
} else if ( (Tmap.bp->w == 16) && (Tmap.bp->h == 16) ) {
|
|
tmapscan_pln8_tiled_16x16();
|
|
} else {
|
|
// argh! write another texure mapper!
|
|
tmapscan_pln8();
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_write_z()
|
|
{
|
|
int i;
|
|
ubyte * dptr;
|
|
uint w, dw;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
|
|
w = Tmap.fx_w;
|
|
dw = Tmap.fx_dwdx;
|
|
|
|
uint *zbuf = (uint *)&gr_zbuffer[(uint)dptr-(uint)Tmap.pScreenBits];
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
*zbuf = w;
|
|
zbuf++;
|
|
w += dw;
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_flat_gouraud_zbuffered()
|
|
{
|
|
int i;
|
|
ubyte * dptr,c;
|
|
fix l, dl;
|
|
uint w, dw;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
c = gr_screen.current_color.raw8;
|
|
|
|
w = Tmap.fx_w;
|
|
dw = Tmap.fx_dwdx;
|
|
|
|
l = Tmap.fx_l;
|
|
dl = Tmap.fx_dl_dx;
|
|
|
|
uint *zbuf = (uint *)&gr_zbuffer[(uint)dptr-(uint)Tmap.pScreenBits];
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
if ( w > *zbuf ) {
|
|
*zbuf = w;
|
|
*dptr = gr_fade_table[(f2i(l)<<8)+c];
|
|
}
|
|
zbuf++;
|
|
w += dw;
|
|
l+=dl;
|
|
dptr++;
|
|
}
|
|
}
|
|
|
|
// ADAM: Change Nebula colors here:
|
|
#define NEBULA_COLORS 20
|
|
|
|
void tmapscan_nebula8()
|
|
{
|
|
ubyte * dptr;
|
|
int l1,l2, dldx;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
|
|
float max_neb_color = i2fl(NEBULA_COLORS-1);
|
|
|
|
l1 = (int)(Tmap.l.b*max_neb_color*256.0f);
|
|
l2 = l1 + 256/2; // dithering
|
|
dldx = (int)(Tmap.deltas.b*max_neb_color*2.0f*256.0f);
|
|
|
|
#ifdef USE_INLINE_ASM
|
|
// memset( dptr, 31, Tmap.loop_count );
|
|
_asm push eax
|
|
_asm push ebx
|
|
_asm push ecx
|
|
_asm push edx
|
|
_asm push edi
|
|
|
|
// eax - l1
|
|
// ebx - l2
|
|
// ecx - count
|
|
// edx - dldx
|
|
// edi - dest
|
|
_asm mov eax, l1
|
|
_asm mov ebx, l2
|
|
_asm mov edx, dldx
|
|
_asm mov edi, dptr
|
|
|
|
_asm mov ecx, Tmap.loop_count
|
|
_asm shr ecx, 1
|
|
_asm jz DoFinal
|
|
_asm pushf
|
|
|
|
Next2Pixels:
|
|
_asm mov [edi], ah
|
|
_asm add eax, edx
|
|
|
|
_asm mov [edi+1], bh
|
|
_asm add ebx, edx
|
|
|
|
_asm add edi, 2
|
|
_asm dec ecx
|
|
_asm jnz Next2Pixels
|
|
|
|
_asm popf
|
|
DoFinal:
|
|
_asm jnc NotDoFinal
|
|
_asm mov [edi], ah
|
|
NotDoFinal:
|
|
|
|
_asm pop edi
|
|
_asm pop edx
|
|
_asm pop ecx
|
|
_asm pop ebx
|
|
_asm pop eax
|
|
|
|
#else
|
|
int i;
|
|
if ( Tmap.loop_count > 1 ) {
|
|
for (i=0; i<Tmap.loop_count/2; i++ ) {
|
|
dptr[0] = (ubyte)((l1&0xFF00)>>8);
|
|
l1+=dldx;
|
|
dptr[1] = (ubyte)((l2&0xFF00)>>8);
|
|
l2+=dldx;
|
|
dptr+=2;
|
|
}
|
|
}
|
|
if ( Tmap.loop_count & 1 ) {
|
|
dptr[0] = (ubyte)((l1&0xFF00)>>8);
|
|
dptr++;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void tmapscan_flat_gouraud()
|
|
{
|
|
if (gr_zbuffering) {
|
|
switch(gr_zbuffering_mode) {
|
|
case GR_ZBUFF_NONE:
|
|
break;
|
|
case GR_ZBUFF_FULL: // both
|
|
tmapscan_flat_gouraud_zbuffered();
|
|
return;
|
|
case GR_ZBUFF_WRITE: // write only
|
|
tmapscan_flat_gouraud_zbuffered();
|
|
break;
|
|
case GR_ZBUFF_READ: // read only
|
|
tmapscan_flat_gouraud_zbuffered();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* HARDWARE_ONLY
|
|
if ( Current_alphacolor ) {
|
|
ubyte *lookup = &Current_alphacolor->table.lookup[0][0];
|
|
|
|
int i;
|
|
ubyte * dptr;
|
|
fix l, dl;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
|
|
l = Tmap.fx_l;
|
|
dl = Tmap.fx_dl_dx;
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
*dptr = lookup[f2i(l*16)*256+*dptr];
|
|
l+=dl;
|
|
dptr++;
|
|
}
|
|
|
|
} else {
|
|
*/
|
|
int i;
|
|
ubyte * dptr,c;
|
|
fix l, dl;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
c = gr_screen.current_color.raw8;
|
|
|
|
l = Tmap.fx_l;
|
|
dl = Tmap.fx_dl_dx;
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
*dptr = gr_fade_table[f2i(l*32)*256+c];
|
|
l+=dl;
|
|
dptr++;
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_flat8_zbuffered()
|
|
{
|
|
int i;
|
|
ubyte * dptr,c;
|
|
|
|
dptr = (ubyte *)Tmap.dest_row_data;
|
|
c = gr_screen.current_color.raw8;
|
|
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
int tmp = (uint)dptr-Tmap.pScreenBits;
|
|
if ( Tmap.fx_w > (int)gr_zbuffer[tmp] ) {
|
|
gr_zbuffer[tmp] = Tmap.fx_w;
|
|
*dptr = c;
|
|
}
|
|
Tmap.fx_w += Tmap.fx_dwdx;
|
|
dptr++;
|
|
}
|
|
}
|
|
|
|
void tmapscan_flat8()
|
|
{
|
|
if (gr_zbuffering) {
|
|
switch(gr_zbuffering_mode) {
|
|
case GR_ZBUFF_NONE:
|
|
break;
|
|
case GR_ZBUFF_FULL: // both
|
|
tmapscan_flat8_zbuffered();
|
|
return;
|
|
case GR_ZBUFF_WRITE: // write only
|
|
tmapscan_write_z();
|
|
break;
|
|
case GR_ZBUFF_READ: // read only
|
|
tmapscan_flat8_zbuffered();
|
|
return;
|
|
}
|
|
}
|
|
|
|
memset( (ubyte *)Tmap.dest_row_data, gr_screen.current_color.raw8, Tmap.loop_count );
|
|
}
|
|
|
|
void tmapscan_pln8_zbuffered();
|
|
|
|
|
|
void tmapscan_pln8_ppro()
|
|
{
|
|
_asm {
|
|
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
// Put the FPU in low precision mode
|
|
fstcw Tmap.OldFPUCW // store copy of CW
|
|
mov ax,Tmap.OldFPUCW // get it in ax
|
|
and eax, ~0x300L
|
|
mov Tmap.FPUCW,ax // store it
|
|
fldcw Tmap.FPUCW // load the FPU
|
|
|
|
mov ecx, Tmap.loop_count // ecx = width
|
|
mov edi, Tmap.dest_row_data // edi = dest pointer
|
|
|
|
// edi = pointer to start pixel in dest dib
|
|
// ecx = spanwidth
|
|
|
|
mov eax,ecx // eax and ecx = width
|
|
shr ecx,5 // ecx = width / subdivision length
|
|
and eax,31 // eax = width mod subdivision length
|
|
jnz some_left_over // any leftover?
|
|
dec ecx // no, so special case last span
|
|
mov eax,32 // it's 8 pixels long
|
|
some_left_over:
|
|
mov Tmap.Subdivisions,ecx // store widths
|
|
mov Tmap.WidthModLength,eax
|
|
|
|
// calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
|
|
// st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld Tmap.l.v // V/ZL
|
|
fld Tmap.l.u // U/ZL V/ZL
|
|
fld Tmap.l.sw // 1/ZL U/ZL V/ZL
|
|
fld1 // 1 1/ZL U/ZL V/ZL
|
|
fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
|
|
fld st // ZL ZL 1/ZL U/ZL V/ZL
|
|
fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
|
|
fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
|
|
fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
|
|
|
|
fstp st(5) // VL 1/ZL U/ZL V/ZL UL
|
|
fstp st(5) // 1/ZL U/ZL V/ZL UL VL
|
|
|
|
// calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
|
|
fxch st(1) // U/ZL 1/ZR V/ZL UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
|
|
fxch st(2) // V/ZL 1/ZR U/ZR UL VL
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// @todo overlap this guy
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
cmp ecx,0 // check for any full spans
|
|
jle HandleLeftoverPixels
|
|
|
|
SpanLoop:
|
|
|
|
// at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// convert left side coords
|
|
|
|
fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
|
|
fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
|
|
fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
|
|
fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
|
|
fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
|
|
fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
|
|
fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
|
|
|
|
// increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
|
|
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
|
|
fxch st(1) // 1/ZL V/ZR U/ZL UL VL
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
|
|
fxch st(2) // U/ZL V/ZR 1/ZR UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
|
|
fxch st(2) // 1/ZR V/ZR U/ZR UL VL
|
|
fxch st(1) // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// setup delta values
|
|
|
|
mov eax,Tmap.DeltaV // get v 16.16 step
|
|
mov ebx,eax // copy it
|
|
sar eax,16 // get v int step
|
|
shl ebx,16 // get v frac step
|
|
mov Tmap.DeltaVFrac,ebx // store it
|
|
imul eax,Tmap.src_offset // calculate texture step for v int step
|
|
|
|
mov ebx,Tmap.DeltaU // get u 16.16 step
|
|
mov ecx,ebx // copy it
|
|
sar ebx,16 // get u int step
|
|
shl ecx,16 // get u frac step
|
|
mov Tmap.DeltaUFrac,ecx // store it
|
|
add eax,ebx // calculate uint + vint step
|
|
mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
|
|
add eax,Tmap.src_offset // calculate whole step + v carry
|
|
mov Tmap.uv_delta[0],eax // save in v-carry slot
|
|
|
|
// setup initial coordinates
|
|
mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
|
|
|
|
mov ebx,esi // copy it
|
|
sar esi,16 // get integer part
|
|
shl ebx,16 // get fractional part
|
|
|
|
mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
|
|
|
|
mov edx,ecx // copy it
|
|
sar edx,16 // get integer part
|
|
shl ecx,16 // get fractional part
|
|
imul edx,Tmap.src_offset // calc texture scanline address
|
|
add esi,edx // calc texture offset
|
|
add esi,Tmap.pixptr // calc address
|
|
|
|
// set up affine registers
|
|
mov edx,Tmap.DeltaUFrac // get register copy
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shl ebp, 5 //*32
|
|
add Tmap.fx_l, ebp
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
sub bp, ax
|
|
shr bp, 5
|
|
|
|
mov dx, bp
|
|
|
|
// calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// This divide should happen while the pixel span is drawn.
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // preread the destination cache line
|
|
xor eax, eax
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov Tmap.InnerLooper, 32/4 // Set up loop counter
|
|
|
|
InnerInnerLoop:
|
|
|
|
push ebx
|
|
and ebx, 0ff00h
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Get shaded pixel
|
|
pop ebx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
xor eax, eax
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
push ebx
|
|
and ebx, 0ff00h
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Get shaded pixel
|
|
pop ebx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
xor eax, eax
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
push ebx
|
|
and ebx, 0ff00h
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Get shaded pixel
|
|
pop ebx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+2],al // store pixel
|
|
xor eax, eax
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
push ebx
|
|
and ebx, 0ff00h
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Get shaded pixel
|
|
pop ebx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+3],al // store pixel
|
|
xor eax, eax
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.InnerLooper
|
|
jnz InnerInnerLoop
|
|
|
|
// the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
dec Tmap.Subdivisions // decrement span count
|
|
jnz SpanLoop // loop back
|
|
|
|
|
|
HandleLeftoverPixels:
|
|
|
|
mov esi,Tmap.pixptr // load texture pointer
|
|
|
|
// edi = dest dib bits
|
|
// esi = current texture dib bits
|
|
// at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
|
|
jz FPUReturn ; nope, pop the FPU and bail
|
|
|
|
// convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
dec Tmap.WidthModLength ; calc how many steps to take
|
|
jz OnePixelSpan ; just one, don't do deltas
|
|
|
|
// calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// r -> R+1
|
|
|
|
// @todo rearrange things so we don't need these two instructions
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
|
|
|
|
fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
|
|
fmulp st(2),st ; UR VR inv. inv. inv. UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR inv. inv. inv. dU VL
|
|
fxch st(1) ; VR UR inv. inv. inv. dU VL
|
|
fsubr st(6),st ; VR UR inv. inv. inv. dU dV
|
|
fxch st(6) ; dV UR inv. inv. inv. dU VR
|
|
|
|
fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
|
|
fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
|
|
fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
|
|
|
|
fxch st(4) ; dU inv. inv. inv. UR VR
|
|
fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
|
|
fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
|
|
fistp Tmap.DeltaU ; inv. inv. inv. UR VR
|
|
|
|
// @todo gross! these are to line up with the other loop
|
|
fld st(1) ; inv. inv. inv. inv. UR VR
|
|
fld st(2) ; inv. inv. inv. inv. inv. UR VR
|
|
|
|
|
|
// setup delta values
|
|
mov eax, Tmap.DeltaV // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.DeltaU // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
|
|
OnePixelSpan:
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.UFixed // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.VFixed // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
cmp Tmap.WidthModLength, 1
|
|
jle NoDeltaLight
|
|
|
|
push ebx
|
|
|
|
mov ebx, Tmap.fx_l_right
|
|
shr ebx, 8
|
|
|
|
sub ebx, eax
|
|
mov eax, ebx
|
|
|
|
mov eax, Tmap.fx_dl_dx
|
|
shr eax, 8
|
|
|
|
mov dx, ax
|
|
|
|
pop ebx
|
|
|
|
NoDeltaLight:
|
|
|
|
inc Tmap.WidthModLength
|
|
mov eax,Tmap.WidthModLength
|
|
shr eax, 1
|
|
jz one_more_pix
|
|
pushf
|
|
mov Tmap.WidthModLength, eax
|
|
|
|
xor eax, eax
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi]
|
|
|
|
NextPixel:
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.WidthModLength
|
|
jg NextPixel
|
|
|
|
popf
|
|
jnc FPUReturn
|
|
|
|
one_more_pix:
|
|
|
|
mov al,[esi] // get texture pixel 2
|
|
mov ah, bh
|
|
mov al, gr_fade_table[eax]
|
|
mov [edi],al // store pixel 2
|
|
|
|
|
|
FPUReturn:
|
|
|
|
// busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// xxx xxx xxx xxx xxx xxx xxx
|
|
ffree st(0)
|
|
ffree st(1)
|
|
ffree st(2)
|
|
ffree st(3)
|
|
ffree st(4)
|
|
ffree st(5)
|
|
ffree st(6)
|
|
|
|
fldcw Tmap.OldFPUCW // restore the FPU
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_pln8_pentium()
|
|
{
|
|
_asm {
|
|
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
// Put the FPU in low precision mode
|
|
fstcw Tmap.OldFPUCW // store copy of CW
|
|
mov ax,Tmap.OldFPUCW // get it in ax
|
|
and eax, ~0x300L
|
|
mov Tmap.FPUCW,ax // store it
|
|
fldcw Tmap.FPUCW // load the FPU
|
|
|
|
mov ecx, Tmap.loop_count // ecx = width
|
|
mov edi, Tmap.dest_row_data // edi = dest pointer
|
|
|
|
// edi = pointer to start pixel in dest dib
|
|
// ecx = spanwidth
|
|
|
|
mov eax,ecx // eax and ecx = width
|
|
shr ecx,5 // ecx = width / subdivision length
|
|
and eax,31 // eax = width mod subdivision length
|
|
jnz some_left_over // any leftover?
|
|
dec ecx // no, so special case last span
|
|
mov eax,32 // it's 8 pixels long
|
|
some_left_over:
|
|
mov Tmap.Subdivisions,ecx // store widths
|
|
mov Tmap.WidthModLength,eax
|
|
|
|
// calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
|
|
// st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld Tmap.l.v // V/ZL
|
|
fld Tmap.l.u // U/ZL V/ZL
|
|
fld Tmap.l.sw // 1/ZL U/ZL V/ZL
|
|
fld1 // 1 1/ZL U/ZL V/ZL
|
|
fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
|
|
fld st // ZL ZL 1/ZL U/ZL V/ZL
|
|
fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
|
|
fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
|
|
fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
|
|
|
|
fstp st(5) // VL 1/ZL U/ZL V/ZL UL
|
|
fstp st(5) // 1/ZL U/ZL V/ZL UL VL
|
|
|
|
// calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
|
|
fxch st(1) // U/ZL 1/ZR V/ZL UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
|
|
fxch st(2) // V/ZL 1/ZR U/ZR UL VL
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// @todo overlap this guy
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
cmp ecx,0 // check for any full spans
|
|
jle HandleLeftoverPixels
|
|
|
|
SpanLoop:
|
|
|
|
// at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// convert left side coords
|
|
|
|
fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
|
|
fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
|
|
fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
|
|
fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
|
|
fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
|
|
fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
|
|
fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
|
|
|
|
// increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
|
|
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
|
|
fxch st(1) // 1/ZL V/ZR U/ZL UL VL
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
|
|
fxch st(2) // U/ZL V/ZR 1/ZR UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
|
|
fxch st(2) // 1/ZR V/ZR U/ZR UL VL
|
|
fxch st(1) // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// setup delta values
|
|
|
|
mov eax,Tmap.DeltaV // get v 16.16 step
|
|
mov ebx,eax // copy it
|
|
sar eax,16 // get v int step
|
|
shl ebx,16 // get v frac step
|
|
mov Tmap.DeltaVFrac,ebx // store it
|
|
imul eax,Tmap.src_offset // calculate texture step for v int step
|
|
|
|
mov ebx,Tmap.DeltaU // get u 16.16 step
|
|
mov ecx,ebx // copy it
|
|
sar ebx,16 // get u int step
|
|
shl ecx,16 // get u frac step
|
|
mov Tmap.DeltaUFrac,ecx // store it
|
|
add eax,ebx // calculate uint + vint step
|
|
mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
|
|
add eax,Tmap.src_offset // calculate whole step + v carry
|
|
mov Tmap.uv_delta[0],eax // save in v-carry slot
|
|
|
|
// setup initial coordinates
|
|
mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
|
|
|
|
mov ebx,esi // copy it
|
|
sar esi,16 // get integer part
|
|
shl ebx,16 // get fractional part
|
|
|
|
mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
|
|
|
|
mov edx,ecx // copy it
|
|
sar edx,16 // get integer part
|
|
shl ecx,16 // get fractional part
|
|
imul edx,Tmap.src_offset // calc texture scanline address
|
|
add esi,edx // calc texture offset
|
|
add esi,Tmap.pixptr // calc address
|
|
|
|
// set up affine registers
|
|
mov edx,Tmap.DeltaUFrac // get register copy
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shl ebp, 5 //*32
|
|
add Tmap.fx_l, ebp
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
sub bp, ax
|
|
shr bp, 5
|
|
|
|
mov dx, bp
|
|
|
|
// calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// This divide should happen while the pixel span is drawn.
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov Tmap.InnerLooper, 32/4 // Set up loop counter
|
|
|
|
InnerInnerLoop:
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+2],al // store pixel
|
|
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+3],al // store pixel
|
|
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.InnerLooper
|
|
jnz InnerInnerLoop
|
|
|
|
// the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
dec Tmap.Subdivisions // decrement span count
|
|
jnz SpanLoop // loop back
|
|
|
|
|
|
HandleLeftoverPixels:
|
|
|
|
mov esi,Tmap.pixptr // load texture pointer
|
|
|
|
// edi = dest dib bits
|
|
// esi = current texture dib bits
|
|
// at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
|
|
jz FPUReturn ; nope, pop the FPU and bail
|
|
|
|
// convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
dec Tmap.WidthModLength ; calc how many steps to take
|
|
jz OnePixelSpan ; just one, don't do deltas
|
|
|
|
// calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// r -> R+1
|
|
|
|
// @todo rearrange things so we don't need these two instructions
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
|
|
|
|
fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
|
|
fmulp st(2),st ; UR VR inv. inv. inv. UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR inv. inv. inv. dU VL
|
|
fxch st(1) ; VR UR inv. inv. inv. dU VL
|
|
fsubr st(6),st ; VR UR inv. inv. inv. dU dV
|
|
fxch st(6) ; dV UR inv. inv. inv. dU VR
|
|
|
|
fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
|
|
fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
|
|
fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
|
|
|
|
fxch st(4) ; dU inv. inv. inv. UR VR
|
|
fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
|
|
fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
|
|
fistp Tmap.DeltaU ; inv. inv. inv. UR VR
|
|
|
|
// @todo gross! these are to line up with the other loop
|
|
fld st(1) ; inv. inv. inv. inv. UR VR
|
|
fld st(2) ; inv. inv. inv. inv. inv. UR VR
|
|
|
|
|
|
// setup delta values
|
|
mov eax, Tmap.DeltaV // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.DeltaU // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
|
|
OnePixelSpan:
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.UFixed // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.VFixed // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
cmp Tmap.WidthModLength, 1
|
|
jle NoDeltaLight
|
|
|
|
push ebx
|
|
|
|
mov ebx, Tmap.fx_l_right
|
|
shr ebx, 8
|
|
|
|
sub ebx, eax
|
|
mov eax, ebx
|
|
|
|
mov eax, Tmap.fx_dl_dx
|
|
shr eax, 8
|
|
|
|
mov dx, ax
|
|
|
|
pop ebx
|
|
|
|
NoDeltaLight:
|
|
|
|
inc Tmap.WidthModLength
|
|
mov eax,Tmap.WidthModLength
|
|
shr eax, 1
|
|
jz one_more_pix
|
|
pushf
|
|
mov Tmap.WidthModLength, eax
|
|
|
|
xor eax, eax
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi]
|
|
|
|
NextPixel:
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.WidthModLength
|
|
jg NextPixel
|
|
|
|
popf
|
|
jnc FPUReturn
|
|
|
|
one_more_pix:
|
|
|
|
mov al,[esi] // get texture pixel 2
|
|
mov ah, bh
|
|
mov al, gr_fade_table[eax]
|
|
mov [edi],al // store pixel 2
|
|
|
|
|
|
FPUReturn:
|
|
|
|
// busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// xxx xxx xxx xxx xxx xxx xxx
|
|
ffree st(0)
|
|
ffree st(1)
|
|
ffree st(2)
|
|
ffree st(3)
|
|
ffree st(4)
|
|
ffree st(5)
|
|
ffree st(6)
|
|
|
|
fldcw Tmap.OldFPUCW // restore the FPU
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void tmapscan_pln8()
|
|
{
|
|
if (gr_zbuffering) {
|
|
switch(gr_zbuffering_mode) {
|
|
case GR_ZBUFF_NONE:
|
|
break;
|
|
case GR_ZBUFF_FULL: // both
|
|
tmapscan_pln8_zbuffered();
|
|
return;
|
|
case GR_ZBUFF_WRITE: // write only
|
|
tmapscan_write_z();
|
|
break;
|
|
case GR_ZBUFF_READ: // read only
|
|
tmapscan_pln8_zbuffered();
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
if ( Gr_cpu > 5 ) {
|
|
tmapscan_pln8_ppro();
|
|
} else {
|
|
tmapscan_pln8_pentium();
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_lln8()
|
|
{
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
mov eax, Tmap.loop_count
|
|
shr eax, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, eax
|
|
and Tmap.loop_count, 3
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
NextPixelBlock:
|
|
|
|
push eax
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shl ebp, 2 //*4
|
|
add Tmap.fx_l, ebp
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
sub bp, ax
|
|
shr bp, 2
|
|
|
|
mov dx, bp
|
|
pop eax
|
|
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+2],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+3],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
mov bx, bp
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shr ebp, 8
|
|
mov dx, bp
|
|
|
|
mov eax,Tmap.loop_count
|
|
test eax, -1
|
|
jz _none_to_do
|
|
shr eax, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, eax
|
|
pushf
|
|
|
|
xor eax, eax
|
|
|
|
mov al, [edi] // preread the destination cache line
|
|
mov al, [esi] // Get first texel
|
|
|
|
NextPixel:
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
mov ah, bh // move lighting value into place
|
|
mov al, gr_fade_table[eax] // Get shaded pixel
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
xor eax, eax
|
|
mov al, [esi] // Get first texel
|
|
mov ah, bh
|
|
mov al, gr_fade_table[eax]
|
|
mov [edi],al // store pixel 2
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
|
|
void tmapscan_lna8_zbuffered_ppro()
|
|
{
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
mov ebp, Tmap.fx_w
|
|
mov edx, gr_zbuffer
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
mov eax, Tmap.loop_count
|
|
|
|
shr eax, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, eax
|
|
and Tmap.loop_count, 3
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = zbuffer pointer
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// ebp = zvalue
|
|
// esp = stack
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0a // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
|
|
// Get pixel and blend it
|
|
push ebx
|
|
xor ebx, ebx
|
|
mov bl, [edi+0]
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov ah, [esi] // Get texel into AL
|
|
add eax, Tmap.BlendLookup
|
|
mov eax, [eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+0],al // store pixel
|
|
Skip0a:
|
|
add ebp,Tmap.fx_dwdx // increment z value
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1a // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
|
|
// Get pixel and blend it
|
|
push ebx
|
|
xor ebx, ebx
|
|
mov bl, [edi+1]
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov ah, [esi] // Get texel into AL
|
|
add eax, Tmap.BlendLookup
|
|
mov eax, [eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+1],al // store pixel
|
|
Skip1a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*2] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip2a // If pixel is covered, skip drawing
|
|
// mov [edx+4*2], ebp // Write new Z value
|
|
|
|
push ebx
|
|
xor ebx, ebx
|
|
mov bl, [edi+2]
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov ah, [esi] // Get texel into AL
|
|
add eax, Tmap.BlendLookup
|
|
mov eax, [eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+2],al // store pixel
|
|
Skip2a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*3] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip3a // If pixel is covered, skip drawing
|
|
// mov [edx+4*3], ebp // Write new Z value
|
|
|
|
push ebx
|
|
xor ebx, ebx
|
|
mov bl, [edi+3]
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov ah, [esi] // Get texel into AL
|
|
add eax, Tmap.BlendLookup
|
|
mov eax, [eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+3],al // store pixel
|
|
Skip3a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edx, 16
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov eax,Tmap.loop_count
|
|
test eax, -1
|
|
jz _none_to_do
|
|
shr eax, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, eax
|
|
pushf
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
NextPixel:
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0b // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
Skip0b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1b // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
Skip1b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
add edx, 8
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
cmp ebp, [edx] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0c // If pixel is covered, skip drawing
|
|
// mov [edx], ebp // Write new Z value
|
|
mov al,[edi] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi],al // store pixel
|
|
Skip0c:
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_lna8_zbuffered_pentium()
|
|
{
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
mov ebp, Tmap.fx_w
|
|
mov edx, gr_zbuffer
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
mov eax, Tmap.loop_count
|
|
|
|
shr eax, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, eax
|
|
and Tmap.loop_count, 3
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = zbuffer pointer
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// ebp = zvalue
|
|
// esp = stack
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0a // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
|
|
|
|
|
|
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
|
|
|
|
mov [edi+0],al // store pixel
|
|
Skip0a:
|
|
add ebp,Tmap.fx_dwdx // increment z value
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1a // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
|
|
|
|
|
|
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
|
|
|
|
mov [edi+1],al // store pixel
|
|
Skip1a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*2] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip2a // If pixel is covered, skip drawing
|
|
// mov [edx+4*2], ebp // Write new Z value
|
|
mov al,[edi+2] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
|
|
|
|
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
|
|
|
|
mov [edi+2],al // store pixel
|
|
Skip2a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*3] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip3a // If pixel is covered, skip drawing
|
|
// mov [edx+4*3], ebp // Write new Z value
|
|
mov al,[edi+3] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
|
|
|
|
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
|
|
|
|
mov [edi+3],al // store pixel
|
|
Skip3a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edx, 16
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov eax,Tmap.loop_count
|
|
test eax, -1
|
|
jz _none_to_do
|
|
shr eax, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, eax
|
|
pushf
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
NextPixel:
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0b // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
Skip0b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1b // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
Skip1b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
add edx, 8
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
cmp ebp, [edx] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0c // If pixel is covered, skip drawing
|
|
// mov [edx], ebp // Write new Z value
|
|
mov al,[edi] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi],al // store pixel
|
|
Skip0c:
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_lna8_zbuffered()
|
|
{
|
|
if ( Gr_cpu > 5 ) {
|
|
tmapscan_lna8_zbuffered_ppro();
|
|
} else {
|
|
tmapscan_lna8_zbuffered_pentium();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
extern float Tmap_clipped_left;
|
|
|
|
void tmapscan_lna8()
|
|
{
|
|
if (gr_zbuffering) {
|
|
switch(gr_zbuffering_mode) {
|
|
case GR_ZBUFF_NONE:
|
|
break;
|
|
case GR_ZBUFF_FULL: // both
|
|
case GR_ZBUFF_WRITE: // write only
|
|
case GR_ZBUFF_READ: // read only
|
|
tmapscan_lna8_zbuffered();
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
mov eax, 0
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
|
|
xor eax, eax
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
|
|
xor eax, eax
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
|
|
xor eax, eax
|
|
mov al,[edi+2] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+2],al // store pixel
|
|
|
|
xor eax, eax
|
|
mov al,[edi+3] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+3],al // store pixel
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
NextPixel:
|
|
|
|
xor eax, eax
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
|
|
xor eax, eax
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
mov eax, 0
|
|
mov al,[edi] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add eax, Tmap.BlendLookup
|
|
mov al, [eax] // blend them
|
|
mov [edi],al // store pixel
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
// HACKED IN SYSTEM FOR DOING MODEL CACHING
|
|
int Tmap_scan_read = 0; // 0 = normal mapper, 1=read, 2=write
|
|
|
|
// HACKED IN SYSTEM FOR DOING MODEL CACHING
|
|
void tmapscan_lnn8_read()
|
|
{
|
|
Tmap.fx_u = fl2f(Tmap.l.u);
|
|
Tmap.fx_v = fl2f(Tmap.l.v);
|
|
Tmap.fx_du_dx = fl2f(Tmap.deltas.u);
|
|
Tmap.fx_dv_dx = fl2f(Tmap.deltas.v);
|
|
|
|
/*
|
|
int i;
|
|
|
|
ubyte * src = (ubyte *)Tmap.pixptr;
|
|
ubyte * dst = (ubyte *)Tmap.dest_row_data;
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
int u,v;
|
|
u = f2i(Tmap.fx_u);
|
|
v = f2i(Tmap.fx_v);
|
|
|
|
src[u+v*Tmap.src_offset] = *dst++;
|
|
|
|
Tmap.fx_u += Tmap.fx_du_dx;
|
|
Tmap.fx_v += Tmap.fx_dv_dx;
|
|
}
|
|
*/
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+0] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+1] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+2] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+3] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
xor eax, eax
|
|
|
|
mov al, [edi] // preread the destination cache line
|
|
|
|
NextPixel:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+0] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[edi+1] // get texture pixel
|
|
mov [esi],al // store pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
mov al,[edi] // get texture pixel
|
|
mov [esi],al // store pixel 2
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
|
|
// HACKED IN SYSTEM FOR DOING MODEL CACHING
|
|
void tmapscan_lnn8_write()
|
|
{
|
|
Tmap.fx_u = fl2f(Tmap.l.u);
|
|
Tmap.fx_v = fl2f(Tmap.l.v);
|
|
Tmap.fx_du_dx = fl2f(Tmap.deltas.u);
|
|
Tmap.fx_dv_dx = fl2f(Tmap.deltas.v);
|
|
|
|
/*
|
|
int i;
|
|
|
|
ubyte * src = (ubyte *)Tmap.pixptr;
|
|
ubyte * dst = (ubyte *)Tmap.dest_row_data;
|
|
|
|
for (i=0; i<Tmap.loop_count; i++ ) {
|
|
int u,v;
|
|
u = f2i(Tmap.fx_u);
|
|
v = f2i(Tmap.fx_v);
|
|
|
|
ubyte c = src[u+v*Tmap.src_offset];
|
|
if ( c != 0 ) {
|
|
*dst = c;
|
|
}
|
|
dst++;
|
|
|
|
Tmap.fx_u += Tmap.fx_du_dx;
|
|
Tmap.fx_v += Tmap.fx_dv_dx;
|
|
}
|
|
*/
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip0
|
|
mov [edi+0],al // store pixel
|
|
Skip0:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip1
|
|
mov [edi+1],al // store pixel
|
|
Skip1:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip2
|
|
mov [edi+2],al // store pixel
|
|
Skip2:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip3
|
|
mov [edi+3],al // store pixel
|
|
Skip3:
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
xor eax, eax
|
|
|
|
mov al, [edi] // preread the destination cache line
|
|
|
|
NextPixel:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip0a
|
|
mov [edi+0],al // store pixel
|
|
Skip0a:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
cmp al, 255
|
|
je Skip1a
|
|
mov [edi+1],al // store pixel
|
|
Skip1a:
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
mov al,[esi] // get texture pixel
|
|
cmp al, 255
|
|
je Skip0b
|
|
mov [edi],al // store pixel
|
|
Skip0b:
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_lnn8()
|
|
{
|
|
// HACKED IN SYSTEM FOR DOING MODEL CACHING
|
|
if ( Tmap_scan_read==1 ) {
|
|
tmapscan_lnn8_read();
|
|
return;
|
|
} else if ( Tmap_scan_read==2 ) {
|
|
tmapscan_lnn8_write();
|
|
//tmapscan_lnt8();
|
|
return;
|
|
}
|
|
|
|
if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER ) {
|
|
tmapscan_lna8();
|
|
return;
|
|
}
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+2],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+3],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
xor eax, eax
|
|
|
|
mov al, [edi] // preread the destination cache line
|
|
mov al, [esi] // Get first texel
|
|
|
|
NextPixel:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+0],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
mov [edi+1],al // store pixel
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
mov [edi],al // store pixel 2
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_lnt8()
|
|
{
|
|
if ( gr_screen.current_alphablend_mode == GR_ALPHABLEND_FILTER ) {
|
|
tmapscan_lna8();
|
|
return;
|
|
}
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skip0
|
|
mov [edi+0],al // store pixel
|
|
skip0:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skip1
|
|
mov [edi+1],al // store pixel
|
|
skip1:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skip2
|
|
mov [edi+2],al // store pixel
|
|
skip2:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skip3
|
|
mov [edi+3],al // store pixel
|
|
skip3:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
xor eax, eax
|
|
|
|
mov al, [edi] // preread the destination cache line
|
|
mov al, [esi] // Get first texel
|
|
|
|
NextPixel:
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skipa0
|
|
mov [edi+0],al // store pixel
|
|
skipa0:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
cmp al, 255
|
|
je skipa1
|
|
mov [edi+1],al // store pixel
|
|
skipa1:
|
|
mov al,[esi] // get texture pixel
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
cmp al, 255
|
|
je skipb0
|
|
mov [edi],al // store pixel
|
|
skipb0:
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void tmapscan_pln8_zbuffered_ppro()
|
|
{
|
|
_asm {
|
|
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
// Put the FPU in low precision mode
|
|
fstcw Tmap.OldFPUCW // store copy of CW
|
|
mov ax,Tmap.OldFPUCW // get it in ax
|
|
and eax, ~0x300L
|
|
mov Tmap.FPUCW,ax // store it
|
|
fldcw Tmap.FPUCW // load the FPU
|
|
|
|
|
|
mov ecx, Tmap.loop_count // ecx = width
|
|
mov edi, Tmap.dest_row_data // edi = dest pointer
|
|
|
|
// edi = pointer to start pixel in dest dib
|
|
// ecx = spanwidth
|
|
|
|
mov eax,ecx // eax and ecx = width
|
|
shr ecx,5 // ecx = width / subdivision length
|
|
and eax,31 // eax = width mod subdivision length
|
|
jnz some_left_over // any leftover?
|
|
dec ecx // no, so special case last span
|
|
mov eax,32 // it's 8 pixels long
|
|
some_left_over:
|
|
mov Tmap.Subdivisions,ecx // store widths
|
|
mov Tmap.WidthModLength,eax
|
|
|
|
// calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
|
|
// st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld Tmap.l.v // V/ZL
|
|
fld Tmap.l.u // U/ZL V/ZL
|
|
fld Tmap.l.sw // 1/ZL U/ZL V/ZL
|
|
fld1 // 1 1/ZL U/ZL V/ZL
|
|
fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
|
|
fld st // ZL ZL 1/ZL U/ZL V/ZL
|
|
fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
|
|
fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
|
|
fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
|
|
|
|
fstp st(5) // VL 1/ZL U/ZL V/ZL UL
|
|
fstp st(5) // 1/ZL U/ZL V/ZL UL VL
|
|
|
|
// calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
|
|
fxch st(1) // U/ZL 1/ZR V/ZL UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
|
|
fxch st(2) // V/ZL 1/ZR U/ZR UL VL
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// @todo overlap this guy
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
cmp ecx,0 // check for any full spans
|
|
jle HandleLeftoverPixels
|
|
|
|
SpanLoop:
|
|
|
|
// at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// convert left side coords
|
|
|
|
fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
|
|
fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
|
|
fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
|
|
fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
|
|
fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
|
|
fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
|
|
fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
|
|
|
|
// increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
|
|
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
|
|
fxch st(1) // 1/ZL V/ZR U/ZL UL VL
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
|
|
fxch st(2) // U/ZL V/ZR 1/ZR UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
|
|
fxch st(2) // 1/ZR V/ZR U/ZR UL VL
|
|
fxch st(1) // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// setup delta values
|
|
|
|
mov eax,Tmap.DeltaV // get v 16.16 step
|
|
mov ebx,eax // copy it
|
|
sar eax,16 // get v int step
|
|
shl ebx,16 // get v frac step
|
|
mov Tmap.DeltaVFrac,ebx // store it
|
|
imul eax,Tmap.src_offset // calculate texture step for v int step
|
|
|
|
mov ebx,Tmap.DeltaU // get u 16.16 step
|
|
mov ecx,ebx // copy it
|
|
sar ebx,16 // get u int step
|
|
shl ecx,16 // get u frac step
|
|
mov Tmap.DeltaUFrac,ecx // store it
|
|
add eax,ebx // calculate uint + vint step
|
|
mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
|
|
add eax,Tmap.src_offset // calculate whole step + v carry
|
|
mov Tmap.uv_delta[0],eax // save in v-carry slot
|
|
|
|
// setup initial coordinates
|
|
mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
|
|
|
|
mov ebx,esi // copy it
|
|
sar esi,16 // get integer part
|
|
shl ebx,16 // get fractional part
|
|
|
|
mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
|
|
|
|
mov edx,ecx // copy it
|
|
sar edx,16 // get integer part
|
|
shl ecx,16 // get fractional part
|
|
imul edx,Tmap.src_offset // calc texture scanline address
|
|
add esi,edx // calc texture offset
|
|
add esi,Tmap.pixptr // calc address
|
|
|
|
// set up affine registers
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shl ebp, 5 //*32
|
|
add Tmap.fx_l, ebp
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
sub bp, ax
|
|
shr bp, 5
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
mov dx, bp
|
|
mov Tmap.DeltaUFrac, edx
|
|
|
|
|
|
// calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// This divide should happen while the pixel span is drawn.
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov Tmap.InnerLooper, 32/4 // Set up loop counter
|
|
|
|
mov ebp, Tmap.fx_w
|
|
|
|
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
mov edx, gr_zbuffer
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
InnerInnerLoop:
|
|
|
|
// Pixel 0
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0 // If pixel is covered, skip drawing
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
add ebp,Tmap.fx_dwdx
|
|
add ebx,Tmap.DeltaUFrac
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 1
|
|
cmp ebp, [edx+4] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1 // If pixel is covered, skip drawing
|
|
mov [edx+4], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+1],al // Write new pixel
|
|
|
|
Skip1: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
add ebp,Tmap.fx_dwdx
|
|
add ebx,Tmap.DeltaUFrac
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 2
|
|
cmp ebp, [edx+8] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip2 // If pixel is covered, skip drawing
|
|
mov [edx+8], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+2],al // Write new pixel
|
|
|
|
Skip2: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
add ebp,Tmap.fx_dwdx
|
|
add ebx,Tmap.DeltaUFrac
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 3
|
|
cmp ebp, [edx+12] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip3 // If pixel is covered, skip drawing
|
|
mov [edx+12], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+3],al // Write new pixel
|
|
|
|
Skip3: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
add ebp,Tmap.fx_dwdx
|
|
add ebx,Tmap.DeltaUFrac
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
|
|
add edi, 4
|
|
add edx, 16
|
|
dec Tmap.InnerLooper
|
|
jnz InnerInnerLoop
|
|
|
|
mov Tmap.fx_w, ebp
|
|
|
|
// the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
dec Tmap.Subdivisions // decrement span count
|
|
jnz SpanLoop // loop back
|
|
|
|
|
|
HandleLeftoverPixels:
|
|
|
|
mov esi,Tmap.pixptr // load texture pointer
|
|
|
|
// edi = dest dib bits
|
|
// esi = current texture dib bits
|
|
// at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
|
|
jz FPUReturn ; nope, pop the FPU and bail
|
|
|
|
// convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
dec Tmap.WidthModLength ; calc how many steps to take
|
|
jz OnePixelSpan ; just one, don't do deltas
|
|
|
|
// calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// r -> R+1
|
|
|
|
// @todo rearrange things so we don't need these two instructions
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
|
|
|
|
fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
|
|
fmulp st(2),st ; UR VR inv. inv. inv. UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR inv. inv. inv. dU VL
|
|
fxch st(1) ; VR UR inv. inv. inv. dU VL
|
|
fsubr st(6),st ; VR UR inv. inv. inv. dU dV
|
|
fxch st(6) ; dV UR inv. inv. inv. dU VR
|
|
|
|
fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
|
|
fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
|
|
fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
|
|
|
|
fxch st(4) ; dU inv. inv. inv. UR VR
|
|
fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
|
|
fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
|
|
fistp Tmap.DeltaU ; inv. inv. inv. UR VR
|
|
|
|
// @todo gross! these are to line up with the other loop
|
|
fld st(1) ; inv. inv. inv. inv. UR VR
|
|
fld st(2) ; inv. inv. inv. inv. inv. UR VR
|
|
|
|
|
|
// setup delta values
|
|
mov eax, Tmap.DeltaV // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.DeltaU // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
|
|
OnePixelSpan:
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.UFixed // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.VFixed // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
// mov edx, Tmap.DeltaUFrac
|
|
|
|
cmp Tmap.WidthModLength, 1
|
|
jle NoDeltaLight
|
|
|
|
push ebx
|
|
|
|
mov ebx, Tmap.fx_l_right
|
|
shr ebx, 8
|
|
|
|
sub ebx, eax
|
|
mov eax, ebx
|
|
|
|
mov eax, Tmap.fx_dl_dx
|
|
shr eax, 8
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
mov dx, ax
|
|
mov Tmap.DeltaUFrac, edx
|
|
|
|
pop ebx
|
|
|
|
NoDeltaLight:
|
|
|
|
mov ebp, Tmap.fx_w
|
|
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
shl eax, 2
|
|
mov edx, gr_zbuffer
|
|
add edx, eax
|
|
|
|
inc Tmap.WidthModLength
|
|
mov eax,Tmap.WidthModLength
|
|
shr eax, 1
|
|
jz one_more_pix
|
|
pushf
|
|
mov Tmap.WidthModLength, eax
|
|
|
|
xor eax, eax
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi]
|
|
|
|
|
|
|
|
NextPixel:
|
|
// Pixel 0
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0a // If pixel is covered, skip drawing
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0a: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 1
|
|
cmp ebp, [edx+4] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1a // If pixel is covered, skip drawing
|
|
mov [edx+4], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+1],al // Write new pixel
|
|
|
|
Skip1a: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
add edi, 2
|
|
add edx, 8
|
|
dec Tmap.WidthModLength
|
|
jg NextPixel
|
|
|
|
popf
|
|
jnc FPUReturn
|
|
|
|
one_more_pix:
|
|
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0c // If pixel is covered, skip drawing
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
// Get pixel and light it
|
|
push ebx
|
|
xor eax, eax // Clear all bits of EAX. This avoids a partial register stall on Pentium Pros
|
|
mov al, [esi] // Get texel into AL
|
|
and ebx, 0ff00h // Clear out fractional part of EBX
|
|
mov eax, DWORD PTR gr_fade_table[eax+ebx] // Lookup pixel in lighting table
|
|
pop ebx
|
|
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0c:
|
|
|
|
FPUReturn:
|
|
|
|
// busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// xxx xxx xxx xxx xxx xxx xxx
|
|
ffree st(0)
|
|
ffree st(1)
|
|
ffree st(2)
|
|
ffree st(3)
|
|
ffree st(4)
|
|
ffree st(5)
|
|
ffree st(6)
|
|
|
|
fldcw Tmap.OldFPUCW // restore the FPU
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_pln8_zbuffered_pentium()
|
|
{
|
|
_asm {
|
|
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
// Put the FPU in low precision mode
|
|
fstcw Tmap.OldFPUCW // store copy of CW
|
|
mov ax,Tmap.OldFPUCW // get it in ax
|
|
and eax, ~0x300L
|
|
mov Tmap.FPUCW,ax // store it
|
|
fldcw Tmap.FPUCW // load the FPU
|
|
|
|
|
|
mov ecx, Tmap.loop_count // ecx = width
|
|
mov edi, Tmap.dest_row_data // edi = dest pointer
|
|
|
|
// edi = pointer to start pixel in dest dib
|
|
// ecx = spanwidth
|
|
|
|
mov eax,ecx // eax and ecx = width
|
|
shr ecx,5 // ecx = width / subdivision length
|
|
and eax,31 // eax = width mod subdivision length
|
|
jnz some_left_over // any leftover?
|
|
dec ecx // no, so special case last span
|
|
mov eax,32 // it's 8 pixels long
|
|
some_left_over:
|
|
mov Tmap.Subdivisions,ecx // store widths
|
|
mov Tmap.WidthModLength,eax
|
|
|
|
// calculate ULeft and VLeft // FPU Stack (ZL = ZLeft)
|
|
// st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld Tmap.l.v // V/ZL
|
|
fld Tmap.l.u // U/ZL V/ZL
|
|
fld Tmap.l.sw // 1/ZL U/ZL V/ZL
|
|
fld1 // 1 1/ZL U/ZL V/ZL
|
|
fdiv st,st(1) // ZL 1/ZL U/ZL V/ZL
|
|
fld st // ZL ZL 1/ZL U/ZL V/ZL
|
|
fmul st,st(4) // VL ZL 1/ZL U/ZL V/ZL
|
|
fxch st(1) // ZL VL 1/ZL U/ZL V/ZL
|
|
fmul st,st(3) // UL VL 1/ZL U/ZL V/ZL
|
|
|
|
fstp st(5) // VL 1/ZL U/ZL V/ZL UL
|
|
fstp st(5) // 1/ZL U/ZL V/ZL UL VL
|
|
|
|
// calculate right side OverZ terms ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR U/ZL V/ZL UL VL
|
|
fxch st(1) // U/ZL 1/ZR V/ZL UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR 1/ZR V/ZL UL VL
|
|
fxch st(2) // V/ZL 1/ZR U/ZR UL VL
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate right side coords // st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// @todo overlap this guy
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
cmp ecx,0 // check for any full spans
|
|
jle HandleLeftoverPixels
|
|
|
|
SpanLoop:
|
|
|
|
// at this point the FPU contains // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// convert left side coords
|
|
|
|
fld st(5) ; UL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; UL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.UFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st(6) ; VL UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul Tmap.FixedScale ; VL16 UR VR V/ZR 1/ZR U/ZR UL VL
|
|
fistp Tmap.VFixed ; UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR V/ZR 1/ZR U/ZR dU VL
|
|
fxch st(1) ; VR UR V/ZR 1/ZR U/ZR dU VL
|
|
fsubr st(6),st ; VR UR V/ZR 1/ZR U/ZR dU dV
|
|
fxch st(6) ; dV UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fmul Tmap.FixedScale8 ; dV8 UR V/ZR 1/ZR U/ZR dU VR
|
|
fistp Tmap.DeltaV ; UR V/ZR 1/ZR U/ZR dU VR
|
|
|
|
fxch st(4) ; dU V/ZR 1/ZR U/ZR UR VR
|
|
fmul Tmap.FixedScale8 ; dU8 V/ZR 1/ZR U/ZR UR VR
|
|
fistp Tmap.DeltaU ; V/ZR 1/ZR U/ZR UR VR
|
|
|
|
// increment terms for next span // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// Right terms become Left terms--->// V/ZL 1/ZL U/ZL UL VL
|
|
|
|
fadd Tmap.fl_dvdx_wide // V/ZR 1/ZL U/ZL UL VL
|
|
fxch st(1) // 1/ZL V/ZR U/ZL UL VL
|
|
fadd Tmap.fl_dwdx_wide // 1/ZR V/ZR U/ZL UL VL
|
|
fxch st(2) // U/ZL V/ZR 1/ZR UL VL
|
|
fadd Tmap.fl_dudx_wide // U/ZR V/ZR 1/ZR UL VL
|
|
fxch st(2) // 1/ZR V/ZR U/ZR UL VL
|
|
fxch st(1) // V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// setup delta values
|
|
|
|
mov eax,Tmap.DeltaV // get v 16.16 step
|
|
mov ebx,eax // copy it
|
|
sar eax,16 // get v int step
|
|
shl ebx,16 // get v frac step
|
|
mov Tmap.DeltaVFrac,ebx // store it
|
|
imul eax,Tmap.src_offset // calculate texture step for v int step
|
|
|
|
mov ebx,Tmap.DeltaU // get u 16.16 step
|
|
mov ecx,ebx // copy it
|
|
sar ebx,16 // get u int step
|
|
shl ecx,16 // get u frac step
|
|
mov Tmap.DeltaUFrac,ecx // store it
|
|
add eax,ebx // calculate uint + vint step
|
|
mov Tmap.uv_delta[4],eax // save whole step in non-v-carry slot
|
|
add eax,Tmap.src_offset // calculate whole step + v carry
|
|
mov Tmap.uv_delta[0],eax // save in v-carry slot
|
|
|
|
// setup initial coordinates
|
|
mov esi,Tmap.UFixed // get u 16.16 fixedpoint coordinate
|
|
|
|
mov ebx,esi // copy it
|
|
sar esi,16 // get integer part
|
|
shl ebx,16 // get fractional part
|
|
|
|
mov ecx,Tmap.VFixed // get v 16.16 fixedpoint coordinate
|
|
|
|
mov edx,ecx // copy it
|
|
sar edx,16 // get integer part
|
|
shl ecx,16 // get fractional part
|
|
imul edx,Tmap.src_offset // calc texture scanline address
|
|
add esi,edx // calc texture offset
|
|
add esi,Tmap.pixptr // calc address
|
|
|
|
// set up affine registers
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
mov ebp, Tmap.fx_dl_dx
|
|
shl ebp, 5 //*32
|
|
add Tmap.fx_l, ebp
|
|
|
|
mov ebp, Tmap.fx_l
|
|
shr ebp, 8
|
|
sub bp, ax
|
|
shr bp, 5
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
mov dx, bp
|
|
mov Tmap.DeltaUFrac, edx
|
|
|
|
|
|
// calculate right side coords st0 st1 st2 st3 st4 st5 st6 st7
|
|
fld1 // 1 V/ZR 1/ZR U/ZR UL VL
|
|
// This divide should happen while the pixel span is drawn.
|
|
fdiv st,st(2) // ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi] // get texture pixel 0
|
|
|
|
mov Tmap.InnerLooper, 32/4 // Set up loop counter
|
|
|
|
mov ebp, Tmap.fx_w
|
|
|
|
mov edx, gr_zbuffer
|
|
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
InnerInnerLoop:
|
|
|
|
// Pixel 0
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip0 // If pixel is covered, skip drawing
|
|
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 1
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
cmp ebp, [edx+4] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip1 // If pixel is covered, skip drawing
|
|
|
|
|
|
mov [edx+4], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+1],al // Write new pixel
|
|
|
|
Skip1: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
// Pixel 2
|
|
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
|
|
cmp ebp, [edx+8] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip2 // If pixel is covered, skip drawing
|
|
|
|
|
|
mov [edx+8], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+2],al // Write new pixel
|
|
|
|
Skip2: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
// Pixel 3
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
|
|
cmp ebp, [edx+12] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip3 // If pixel is covered, skip drawing
|
|
|
|
|
|
mov [edx+12], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+3],al // Write new pixel
|
|
|
|
Skip3: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
add edi, 4
|
|
add edx, 16
|
|
dec Tmap.InnerLooper
|
|
jnz InnerInnerLoop
|
|
|
|
mov Tmap.fx_w, ebp
|
|
|
|
// the fdiv is done, finish right // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// ZR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
fld st // ZR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(2) // VR ZR V/ZR 1/ZR U/ZR UL VL
|
|
fxch st(1) // ZR VR V/ZR 1/ZR U/ZR UL VL
|
|
fmul st,st(4) // UR VR V/ZR 1/ZR U/ZR UL VL
|
|
|
|
dec Tmap.Subdivisions // decrement span count
|
|
jnz SpanLoop // loop back
|
|
|
|
|
|
HandleLeftoverPixels:
|
|
|
|
mov esi,Tmap.pixptr // load texture pointer
|
|
|
|
// edi = dest dib bits
|
|
// esi = current texture dib bits
|
|
// at this point the FPU contains ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// inv. means invalid numbers ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
cmp Tmap.WidthModLength,0 ; are there remaining pixels to draw?
|
|
jz FPUReturn ; nope, pop the FPU and bail
|
|
|
|
// convert left side coords ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fld st(5) ; UL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale ; UL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.UFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
fld st(6) ; VL inv. inv. inv. inv. inv. UL VL
|
|
fmul Tmap.FixedScale // VL16 inv. inv. inv. inv. inv. UL VL
|
|
fistp Tmap.VFixed ; inv. inv. inv. inv. inv. UL VL
|
|
|
|
dec Tmap.WidthModLength ; calc how many steps to take
|
|
jz OnePixelSpan ; just one, don't do deltas
|
|
|
|
// calculate right edge coordinates ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
// r -> R+1
|
|
|
|
// @todo rearrange things so we don't need these two instructions
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. inv. UL VL
|
|
fstp Tmap.FloatTemp ; inv. inv. inv. UL VL
|
|
|
|
fld Tmap.r.v ; V/Zr inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.v ; V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.u ; U/Zr V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.u ; U/ZR V/ZR inv. inv. inv. UL VL
|
|
fld Tmap.r.sw ; 1/Zr U/ZR V/ZR inv. inv. inv. UL VL
|
|
fsub Tmap.deltas.sw ; 1/ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fdivr Tmap.One ; ZR U/ZR V/ZR inv. inv. inv. UL VL
|
|
|
|
fmul st(1),st ; ZR UR V/ZR inv. inv. inv. UL VL
|
|
fmulp st(2),st ; UR VR inv. inv. inv. UL VL
|
|
|
|
// calculate deltas ; st0 st1 st2 st3 st4 st5 st6 st7
|
|
|
|
fsubr st(5),st ; UR VR inv. inv. inv. dU VL
|
|
fxch st(1) ; VR UR inv. inv. inv. dU VL
|
|
fsubr st(6),st ; VR UR inv. inv. inv. dU dV
|
|
fxch st(6) ; dV UR inv. inv. inv. dU VR
|
|
|
|
fidiv Tmap.WidthModLength ; dv UR inv. inv. inv. dU VR
|
|
fmul Tmap.FixedScale ; dv16 UR inv. inv. inv. dU VR
|
|
fistp Tmap.DeltaV ; UR inv. inv. inv. dU VR
|
|
|
|
fxch st(4) ; dU inv. inv. inv. UR VR
|
|
fidiv Tmap.WidthModLength ; du inv. inv. inv. UR VR
|
|
fmul Tmap.FixedScale ; du16 inv. inv. inv. UR VR
|
|
fistp Tmap.DeltaU ; inv. inv. inv. UR VR
|
|
|
|
// @todo gross! these are to line up with the other loop
|
|
fld st(1) ; inv. inv. inv. inv. UR VR
|
|
fld st(2) ; inv. inv. inv. inv. inv. UR VR
|
|
|
|
|
|
// setup delta values
|
|
mov eax, Tmap.DeltaV // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.DeltaU // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
|
|
OnePixelSpan:
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.UFixed // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.VFixed // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
|
|
mov eax, Tmap.fx_l
|
|
shr eax, 8
|
|
mov bx, ax
|
|
|
|
// mov edx, Tmap.DeltaUFrac
|
|
|
|
cmp Tmap.WidthModLength, 1
|
|
jle NoDeltaLight
|
|
|
|
push ebx
|
|
|
|
mov ebx, Tmap.fx_l_right
|
|
shr ebx, 8
|
|
|
|
sub ebx, eax
|
|
mov eax, ebx
|
|
|
|
mov eax, Tmap.fx_dl_dx
|
|
shr eax, 8
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
mov dx, ax
|
|
mov Tmap.DeltaUFrac, edx
|
|
|
|
pop ebx
|
|
|
|
NoDeltaLight:
|
|
|
|
mov ebp, Tmap.fx_w
|
|
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
mov edx, gr_zbuffer
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
inc Tmap.WidthModLength
|
|
mov eax,Tmap.WidthModLength
|
|
shr eax, 1
|
|
jz one_more_pix
|
|
pushf
|
|
mov Tmap.WidthModLength, eax
|
|
|
|
xor eax, eax
|
|
|
|
mov al,[edi] // preread the destination cache line
|
|
mov al,[esi]
|
|
|
|
|
|
|
|
NextPixel:
|
|
// Pixel 0
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip0a // If pixel is covered, skip drawing
|
|
|
|
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0a: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
// Pixel 1
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
|
|
cmp ebp, [edx+4] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip1a // If pixel is covered, skip drawing
|
|
|
|
mov [edx+4], ebp // Write new Z value
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
mov [edi+1],al // Write new pixel
|
|
|
|
Skip1a: add ecx,Tmap.DeltaVFrac
|
|
sbb eax,eax
|
|
|
|
//add edx, 4 // Go to next
|
|
add ebp,Tmap.fx_dwdx
|
|
|
|
add ebx,Tmap.DeltaUFrac
|
|
|
|
adc esi,Tmap.uv_delta[4*eax+4]
|
|
|
|
|
|
add edi, 2
|
|
add edx, 8
|
|
dec Tmap.WidthModLength
|
|
jg NextPixel
|
|
|
|
popf
|
|
jnc FPUReturn
|
|
|
|
one_more_pix:
|
|
|
|
mov eax, ebx // Get lighting value from BH into AH
|
|
and eax, 0ffffh; // Clear upper bits of EAX
|
|
|
|
cmp ebp, [edx+0] // Compare the Z depth of this pixel with zbuffer
|
|
mov al, [esi] // Get texel into AL
|
|
jle Skip0c // If pixel is covered, skip drawing
|
|
|
|
mov al, gr_fade_table[eax] // Lookup pixel in lighting table
|
|
|
|
mov [edx+0], ebp // Write new Z value
|
|
|
|
mov [edi+0],al // Write new pixel
|
|
|
|
Skip0c:
|
|
|
|
FPUReturn:
|
|
|
|
// busy FPU registers: // st0 st1 st2 st3 st4 st5 st6 st7
|
|
// xxx xxx xxx xxx xxx xxx xxx
|
|
ffree st(0)
|
|
ffree st(1)
|
|
ffree st(2)
|
|
ffree st(3)
|
|
ffree st(4)
|
|
ffree st(5)
|
|
ffree st(6)
|
|
|
|
fldcw Tmap.OldFPUCW // restore the FPU
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
}
|
|
|
|
void tmapscan_pln8_zbuffered()
|
|
{
|
|
if ( Gr_cpu > 5 ) {
|
|
// Pentium Pro optimized code.
|
|
tmapscan_pln8_zbuffered_ppro();
|
|
} else {
|
|
tmapscan_pln8_zbuffered_pentium();
|
|
}
|
|
}
|
|
|
|
void tmapscan_lnaa8_zbuffered()
|
|
{
|
|
#ifndef HARDWARE_ONLY
|
|
Tmap.lookup = (uint)&Current_alphacolor->table.lookup[0][0];
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
mov ebp, Tmap.fx_w
|
|
mov edx, gr_zbuffer
|
|
mov eax, edi
|
|
sub eax, Tmap.pScreenBits
|
|
shl eax, 2
|
|
add edx, eax
|
|
|
|
mov eax, Tmap.loop_count
|
|
|
|
shr eax, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, eax
|
|
and Tmap.loop_count, 3
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0a // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
Skip0a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1a // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
Skip1a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*2] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip2a // If pixel is covered, skip drawing
|
|
// mov [edx+4*2], ebp // Write new Z value
|
|
mov al,[edi+2] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+2],al // store pixel
|
|
Skip2a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*3] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip3a // If pixel is covered, skip drawing
|
|
// mov [edx+4*3], ebp // Write new Z value
|
|
mov al,[edi+3] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+3],al // store pixel
|
|
Skip3a:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edx, 16
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov eax,Tmap.loop_count
|
|
test eax, -1
|
|
jz _none_to_do
|
|
shr eax, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, eax
|
|
pushf
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
NextPixel:
|
|
|
|
cmp ebp, [edx+4*0] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0b // If pixel is covered, skip drawing
|
|
// mov [edx+4*0], ebp // Write new Z value
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
Skip0b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
cmp ebp, [edx+4*1] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip1b // If pixel is covered, skip drawing
|
|
// mov [edx+4*1], ebp // Write new Z value
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
Skip1b:
|
|
add ebp, Tmap.fx_dwdx
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb eax,eax // get -1 if carry
|
|
add ebx,Tmap.DeltaUFrac // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*eax+4] // add in step ints & carries
|
|
|
|
add edi, 2
|
|
add edx, 8
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
cmp ebp, [edx] // Compare the Z depth of this pixel with zbuffer
|
|
jle Skip0c // If pixel is covered, skip drawing
|
|
// mov [edx], ebp // Write new Z value
|
|
mov al,[edi] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
and eax, 0ffffh
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi],al // store pixel
|
|
Skip0c:
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
#else
|
|
Int3();
|
|
#endif
|
|
}
|
|
|
|
void tmapscan_lnaa8()
|
|
{
|
|
#ifndef HARDWARE_ONLY
|
|
if (gr_zbuffering) {
|
|
switch(gr_zbuffering_mode) {
|
|
case GR_ZBUFF_NONE:
|
|
break;
|
|
case GR_ZBUFF_FULL: // both
|
|
case GR_ZBUFF_WRITE: // write only
|
|
case GR_ZBUFF_READ: // read only
|
|
tmapscan_lnaa8_zbuffered();
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
Tmap.lookup = (uint)&Current_alphacolor->table.lookup[0][0];
|
|
|
|
_asm {
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
push ebp
|
|
push esi
|
|
push edi
|
|
|
|
; setup delta values
|
|
mov eax, Tmap.fx_dv_dx // get v 16.16 step
|
|
mov ebx, eax // copy it
|
|
sar eax, 16 // get v int step
|
|
shl ebx, 16 // get v frac step
|
|
mov Tmap.DeltaVFrac, ebx // store it
|
|
imul eax, Tmap.src_offset // calc texture step for v int step
|
|
|
|
mov ebx, Tmap.fx_du_dx // get u 16.16 step
|
|
mov ecx, ebx // copy it
|
|
sar ebx, 16 // get the u int step
|
|
shl ecx, 16 // get the u frac step
|
|
mov Tmap.DeltaUFrac, ecx // store it
|
|
add eax, ebx // calc uint + vint step
|
|
|
|
mov Tmap.uv_delta[4], eax // save whole step in non-v-carry slot
|
|
add eax, Tmap.src_offset // calc whole step + v carry
|
|
mov Tmap.uv_delta[0], eax // save in v-carry slot
|
|
|
|
; setup initial coordinates
|
|
mov esi, Tmap.fx_u // get u 16.16
|
|
mov ebx, esi // copy it
|
|
sar esi, 16 // get integer part
|
|
shl ebx, 16 // get fractional part
|
|
|
|
mov ecx, Tmap.fx_v // get v 16.16
|
|
mov edx, ecx // copy it
|
|
sar edx, 16 // get integer part
|
|
shl ecx, 16 // get fractional part
|
|
imul edx, Tmap.src_offset // calc texture scanline address
|
|
add esi, edx // calc texture offset
|
|
add esi, Tmap.pixptr // calc address
|
|
|
|
; set edi = address of first pixel to modify
|
|
mov edi, Tmap.dest_row_data
|
|
|
|
mov edx, Tmap.DeltaUFrac
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
mov ebp, Tmap.loop_count
|
|
|
|
shr ebp, 2
|
|
je DoLeftOverPixels
|
|
|
|
mov Tmap.num_big_steps, ebp
|
|
and Tmap.loop_count, 3
|
|
|
|
|
|
NextPixelBlock:
|
|
|
|
// 8 pixel span code
|
|
// edi = dest dib bits at current pixel
|
|
// esi = texture pointer at current u,v
|
|
// eax = scratch
|
|
// ebx = u fraction 0.32
|
|
// ecx = v fraction 0.32
|
|
// edx = u frac step
|
|
// ebp = v carry scratch
|
|
|
|
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
|
|
mov al,[edi+2] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+2],al // store pixel
|
|
|
|
mov al,[edi+3] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+3],al // store pixel
|
|
|
|
add edi, 4
|
|
dec Tmap.num_big_steps
|
|
jne NextPixelBlock
|
|
|
|
|
|
DoLeftOverPixels:
|
|
|
|
mov ebp,Tmap.loop_count
|
|
test ebp, -1
|
|
jz _none_to_do
|
|
shr ebp, 1
|
|
je one_more_pix
|
|
mov Tmap.loop_count, ebp
|
|
pushf
|
|
|
|
xor eax, eax
|
|
mov al,[edi] // get the destination pixel
|
|
|
|
NextPixel:
|
|
|
|
mov al,[edi+0] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+0],al // store pixel
|
|
|
|
mov al,[edi+1] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add ecx,Tmap.DeltaVFrac // increment v fraction
|
|
sbb ebp,ebp // get -1 if carry
|
|
add ebx,edx // increment u fraction
|
|
adc esi,Tmap.uv_delta[4*ebp+4] // add in step ints & carries
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi+1],al // store pixel
|
|
|
|
add edi, 2
|
|
dec Tmap.loop_count
|
|
jne NextPixel
|
|
|
|
popf
|
|
jnc _none_to_do
|
|
|
|
one_more_pix:
|
|
mov al,[edi] // get the destination pixel
|
|
mov ah,[esi] // get texture pixel 0
|
|
add eax, Tmap.lookup
|
|
mov al, [eax] // blend them
|
|
mov [edi],al // store pixel
|
|
|
|
_none_to_do:
|
|
pop edi
|
|
pop esi
|
|
pop ebp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
}
|
|
#else
|
|
Int3();
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
|
|
|