mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 04:16:07 -10:00
Model 2: faster 3D, 2D layers, SCSP DSP, i960 and SHARC (#2201)
Renderer: - texture sheets also kept one byte per texel, the texel fetch reads them straight (inlined, an opaque and a translucent span) - the pixel of each texel worked out once for the colours of a polygon - translucent texel pairs packed from a table; a translucent pixel sure to be discarded skips the next mipmap level - 3D pixels kept as the 15-bit colour of the bitmap - the tile layers drawn straight into the bitmap: the polygons are only drawn over the tile pixels behind them, no copy passes System 24 tiles (rgb version, Model 1 and 2): eight pixels at a time, a group all of the layer's priority without a test each, the last pixels of the line as groups too. SCSP DSP: the steps that only multiply and accumulate on a short path, decoded when MPRO changes; the delay RAM float packing from a table. i960: opcodes read straight from the memory block of the last fetch (memory_get_read_range), execute_op inlined. SHARC: no DMA call while channels 6 and 7 are idle. AArch64 (QEMU, instructions per frame): fvipers -26%, doa -28%, daytona -31%, vf2 -25%. Frames and audio are the same on the Model 2 sets, the ST-V sets and in save states. Claude-Session: https://claude.ai/code/session_013Vje3pEtpLHubqCGwCgoQX Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
35fee378f5
commit
7ed1af5370
10 files changed
+480
-92
No files matched your search
+34
-2
@@ -120,9 +120,33 @@ static INLINE int i960_is_burst( UINT32 address )
|
||||
return i960_burst_cb == NULL || i960_burst_cb( address );
|
||||
}
|
||||
|
||||
/* port: the opcodes are read straight from the memory block of the last
|
||||
fetch (ROM, RAM or a bank: what cpu_readmem32ledw_dword reads there);
|
||||
anything else goes through the memory system. Forgotten at every
|
||||
timeslice, as the banks are only set up between them */
|
||||
static UINT32 i960_fetch_start, i960_fetch_len;
|
||||
static const UINT8 *i960_fetch_ptr;
|
||||
|
||||
static UINT32 i960_readop_slow( UINT32 address )
|
||||
{
|
||||
offs_t start, len;
|
||||
const UINT8 *p = (const UINT8 *)memory_get_read_range( cpu_getactivecpu(), address, &start, &len );
|
||||
if( p != NULL )
|
||||
{
|
||||
/* the block in the CPU's addresses (the mask only drops high bits) */
|
||||
i960_fetch_start = address - ( ( address & mem_amask ) - start );
|
||||
i960_fetch_len = len;
|
||||
i960_fetch_ptr = p;
|
||||
}
|
||||
return cpu_readmem32ledw_dword( address );
|
||||
}
|
||||
|
||||
static INLINE UINT32 i960_readop( UINT32 address )
|
||||
{
|
||||
return cpu_readmem32ledw_dword( address );
|
||||
UINT32 off = address - i960_fetch_start;
|
||||
if( off < i960_fetch_len )
|
||||
return *(const data32_t *)( i960_fetch_ptr + ( off & ~3 ) );
|
||||
return i960_readop_slow( address );
|
||||
}
|
||||
|
||||
static void i960_fatal( const char *fmt, ... )
|
||||
@@ -880,7 +904,14 @@ static void execute_burst_stall_op(UINT32 opcode)
|
||||
check_immediate_irqs();
|
||||
}
|
||||
|
||||
static void execute_op(UINT32 opcode)
|
||||
/* port: inlined in its only caller, the i960_execute loop: as a function,
|
||||
saving and restoring its registers on every instruction cost a fifth of
|
||||
the time spent in the CPU */
|
||||
#if defined(__GNUC__)
|
||||
static INLINE __attribute__((always_inline)) void execute_op(UINT32 opcode)
|
||||
#else
|
||||
static INLINE void execute_op(UINT32 opcode)
|
||||
#endif
|
||||
{
|
||||
UINT32 t1, t2;
|
||||
double t1f, t2f;
|
||||
@@ -2521,6 +2552,7 @@ int i960_execute( int cycles )
|
||||
UINT32 opcode;
|
||||
|
||||
i960_icount = cycles;
|
||||
i960_fetch_len = 0;
|
||||
|
||||
/* delay checking irqs if we are in burst stall mode */
|
||||
if( m_stall_state.burst_mode == 0 )
|
||||
|
||||
@@ -1188,7 +1188,8 @@ int sharc_execute(int cycles)
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_core->write_stalled)
|
||||
/* port: no call when channels 6 and 7 are idle (most instructions) */
|
||||
if (!m_core->write_stalled && (m_core->dma_status & ((1 << 6) | (1 << 7))))
|
||||
{
|
||||
dma_stalled = dma_run_cycle(6);
|
||||
dma_stalled |= dma_run_cycle(7);
|
||||
|
||||
@@ -37,6 +37,42 @@ data32_t *model2_bufferram;
|
||||
static data32_t *model2_backup1;
|
||||
data32_t *model2_textureram0;
|
||||
data32_t *model2_textureram1;
|
||||
UINT8 *model2_texdec0;
|
||||
UINT8 *model2_texdec1;
|
||||
|
||||
/*
|
||||
The texture sheets taken apart, one byte per texel, for the renderer
|
||||
(fetch_bilinear_texel): a 32-bit word of texture RAM holds two 2x2
|
||||
blocks of 4-bit texels. Its texels are at x = xbase + 0..3 and
|
||||
y = ybase + 0..1 of the 2048x1024 sheet, the rows of the columns past
|
||||
1024 being folded into the upper half of the RAM; within the word, bit 1
|
||||
of x picks the block and the parity of x and y the texel. The byte array
|
||||
is indexed y * 2048 + x and is rebuilt with every write.
|
||||
*/
|
||||
static void model2_tex_decode( UINT8 *dec, UINT32 index, UINT32 word )
|
||||
{
|
||||
UINT32 r = ( index >> 8 ) & 0x3ff, xa = index & 0xff;
|
||||
UINT32 xbase = ( r < 512 ) ? xa * 4 : 1024 + xa * 4;
|
||||
UINT32 ybase = ( r < 512 ) ? r * 2 : r * 2 - 1024;
|
||||
int j, k;
|
||||
for( j = 0; j < 2; j++ )
|
||||
for( k = 0; k < 4; k++ )
|
||||
{
|
||||
UINT32 x = xbase + k, y = ybase + j;
|
||||
UINT32 shift = ( ( x & 2 ) << 3 ) | ( ( ~x & 1 ) << 2 ) | ( ( ~y & 1 ) << 3 );
|
||||
dec[ y * 2048 + x ] = ( word >> shift ) & 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
static void model2_tex_decode_all( void )
|
||||
{
|
||||
UINT32 i;
|
||||
for( i = 0; i < 0x40000; i++ )
|
||||
{
|
||||
model2_tex_decode( model2_texdec0, i, model2_textureram0[ i ] );
|
||||
model2_tex_decode( model2_texdec1, i, model2_textureram1[ i ] );
|
||||
}
|
||||
}
|
||||
data16_t *model2_palram;
|
||||
data16_t *model2_colorxlat;
|
||||
UINT8 *model2_lumaram;
|
||||
@@ -637,6 +673,7 @@ static WRITE32_HANDLER( tex0_w )
|
||||
model2_textureram0[ offset >> 1 ] = ( model2_textureram0[ offset >> 1 ] & 0xffff0000 ) | ( data & 0xffff );
|
||||
else
|
||||
model2_textureram0[ offset >> 1 ] = ( model2_textureram0[ offset >> 1 ] & 0x0000ffff ) | ( ( data & 0xffff ) << 16 );
|
||||
model2_tex_decode( model2_texdec0, offset >> 1, model2_textureram0[ offset >> 1 ] );
|
||||
}
|
||||
|
||||
static WRITE32_HANDLER( tex1_w )
|
||||
@@ -646,6 +683,7 @@ static WRITE32_HANDLER( tex1_w )
|
||||
model2_textureram1[ offset >> 1 ] = ( model2_textureram1[ offset >> 1 ] & 0xffff0000 ) | ( data & 0xffff );
|
||||
else
|
||||
model2_textureram1[ offset >> 1 ] = ( model2_textureram1[ offset >> 1 ] & 0x0000ffff ) | ( ( data & 0xffff ) << 16 );
|
||||
model2_tex_decode( model2_texdec1, offset >> 1, model2_textureram1[ offset >> 1 ] );
|
||||
}
|
||||
|
||||
static READ32_HANDLER( tex0_r )
|
||||
@@ -672,6 +710,7 @@ static WRITE32_HANDLER( tex2b_w )
|
||||
{
|
||||
data32_t *ram = ( offset & 0x80000 ) ? model2_textureram1 : model2_textureram0;
|
||||
COMBINE_DATA( &ram[ offset & 0x3ffff ] );
|
||||
model2_tex_decode( ( offset & 0x80000 ) ? model2_texdec1 : model2_texdec0, offset & 0x3ffff, ram[ offset & 0x3ffff ] );
|
||||
}
|
||||
|
||||
static READ32_HANDLER( luma2b_r )
|
||||
@@ -1750,6 +1789,7 @@ static void model2_postload( void )
|
||||
{
|
||||
int i;
|
||||
model2_sound_postload();
|
||||
model2_tex_decode_all();
|
||||
m_palette_dirty = 1;
|
||||
model2_palette_refresh();
|
||||
for( i = 0; i < 4; i++ )
|
||||
@@ -1779,6 +1819,8 @@ static DRIVER_INIT( model2a )
|
||||
model2_backup1 = auto_malloc( 0x4000 );
|
||||
model2_textureram0 = auto_malloc( 0x100000 );
|
||||
model2_textureram1 = auto_malloc( 0x100000 );
|
||||
model2_texdec0 = auto_malloc( 2048 * 1024 );
|
||||
model2_texdec1 = auto_malloc( 2048 * 1024 );
|
||||
model2_palram = auto_malloc( 0x4000 );
|
||||
model2_colorxlat = auto_malloc( 0xc000 );
|
||||
model2_lumaram = auto_malloc( 0x8000 );
|
||||
@@ -1786,6 +1828,8 @@ static DRIVER_INIT( model2a )
|
||||
memset( model2_ram2, 0, 0x40000 );
|
||||
memset( model2_textureram0, 0, 0x100000 );
|
||||
memset( model2_textureram1, 0, 0x100000 );
|
||||
memset( model2_texdec0, 0, 2048 * 1024 );
|
||||
memset( model2_texdec1, 0, 2048 * 1024 );
|
||||
memset( model2_palram, 0, 0x4000 );
|
||||
memset( model2_colorxlat, 0, 0xc000 );
|
||||
memset( model2_lumaram, 0, 0x8000 );
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
extern data32_t *model2_bufferram;
|
||||
extern data32_t *model2_textureram0;
|
||||
extern data32_t *model2_textureram1;
|
||||
extern UINT8 *model2_texdec0; /* the sheets one byte per texel, y * 2048 + x */
|
||||
extern UINT8 *model2_texdec1;
|
||||
extern data16_t *model2_palram;
|
||||
extern data16_t *model2_colorxlat;
|
||||
extern UINT8 *model2_lumaram;
|
||||
|
||||
@@ -777,6 +777,53 @@ void *memory_get_read_ptr(int cpunum, offs_t offset)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
memory_get_read_range - like memory_get_read_ptr,
|
||||
also giving the range of addresses around the
|
||||
offset read from the same memory (*start, *len,
|
||||
masked addresses); NULL when the offset is not
|
||||
plain memory
|
||||
-------------------------------------------------*/
|
||||
|
||||
void *memory_get_read_range(int cpunum, offs_t offset, offs_t *start, offs_t *len)
|
||||
{
|
||||
struct memport_data *memport = &cpudata[cpunum].mem;
|
||||
struct handler_data *handlist = (memport->dbits == 32) ? rmemhandler32 : (memport->dbits == 16) ? rmemhandler16 : rmemhandler8;
|
||||
UINT8 minbits = memport->abits - memport->ebits;
|
||||
int l2bits = LEVEL2_BITS(memport->abits - minbits);
|
||||
UINT8 entry;
|
||||
offs_t first, last;
|
||||
|
||||
offset &= memport->mask;
|
||||
entry = memport->read.table[LEVEL1_INDEX(offset, memport->abits, minbits)];
|
||||
if (entry >= SUBTABLE_BASE)
|
||||
{
|
||||
/* the run of the same entry in the subtable, at most 4 KB each side */
|
||||
UINT8 sub = entry;
|
||||
offs_t base = offset & ~(((offs_t)1 << (l2bits + minbits)) - 1);
|
||||
offs_t i = (offset - base) >> minbits, n = (offs_t)1 << l2bits, j;
|
||||
offs_t lim = 0x1000 >> minbits;
|
||||
entry = memport->read.table[LEVEL2_INDEX(sub, offset, memport->abits, minbits)];
|
||||
for (j = i; j > 0 && i - j < lim && memport->read.table[LEVEL2_INDEX(sub, base + ((j - 1) << minbits), memport->abits, minbits)] == entry; j--) ;
|
||||
first = base + (j << minbits);
|
||||
for (j = i; j + 1 < n && j - i < lim && memport->read.table[LEVEL2_INDEX(sub, base + ((j + 1) << minbits), memport->abits, minbits)] == entry; j++) ;
|
||||
last = base + (j << minbits) + (((offs_t)1 << minbits) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
first = offset & ~(((offs_t)1 << (l2bits + minbits)) - 1);
|
||||
last = first + (((offs_t)1 << (l2bits + minbits)) - 1);
|
||||
}
|
||||
|
||||
/* 8-bit case: RAM/ROM/RAMROM */
|
||||
if (entry > STATIC_RAM || (minbits == 0 && entry != STATIC_RAM))
|
||||
return NULL;
|
||||
*start = first;
|
||||
*len = last - first + 1;
|
||||
return &cpu_bankbase[entry][first - handlist[entry].offset];
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
memory_get_write_ptr - return a pointer to the
|
||||
base of RAM associated with the given CPU
|
||||
|
||||
@@ -825,6 +825,7 @@ extern offs_t encrypted_opcode_start[],encrypted_opcode_end[];
|
||||
/* ----- return a base pointer to memory ---- */
|
||||
void * memory_find_base(int cpunum, offs_t offset);
|
||||
void * memory_get_read_ptr(int cpunum, offs_t offset);
|
||||
void * memory_get_read_range(int cpunum, offs_t offset, offs_t *start, offs_t *len);
|
||||
void * memory_get_write_ptr(int cpunum, offs_t offset);
|
||||
|
||||
/* ----- dynamic memory mapping ----- */
|
||||
|
||||
@@ -815,6 +815,7 @@ static void SCSP_w16(unsigned int addr,unsigned short val)
|
||||
else if(addr>=0x800)
|
||||
{
|
||||
SCSP->DSP.MPRO[(addr-0x800)/2]=val;
|
||||
SCSP->DSP.Dirty=1;
|
||||
if(addr==0xbf0)
|
||||
SCSPDSP_Start(&SCSP->DSP);
|
||||
}
|
||||
@@ -1208,6 +1209,8 @@ static void SCSP_presave(void)
|
||||
int i, s;
|
||||
for (i = 0; i < 3; i++)
|
||||
SCSP_timer_left[i] = SCSP_timer[i] ? timer_timeleft(SCSP_timer[i]) : TIME_NEVER;
|
||||
for (i = 0; i < MAX_SCSP; i++)
|
||||
SCSPs[i].DSP.Dirty = 1; /* MPRO was loaded */
|
||||
for (i = 0; i < MAX_SCSP; i++)
|
||||
for (s = 0; s < 32; s++)
|
||||
{
|
||||
@@ -1230,6 +1233,8 @@ static void SCSP_postload(void)
|
||||
else
|
||||
timer_adjust(SCSP_timer[i], TIME_NEVER, i, 0);
|
||||
}
|
||||
for (i = 0; i < MAX_SCSP; i++)
|
||||
SCSPs[i].DSP.Dirty = 1; /* MPRO was loaded */
|
||||
for (i = 0; i < MAX_SCSP; i++)
|
||||
for (s = 0; s < 32; s++)
|
||||
{
|
||||
|
||||
+117
-10
@@ -36,6 +36,19 @@ struct _SCSPDSP
|
||||
|
||||
int Stopped;
|
||||
int LastStep;
|
||||
|
||||
/* port: the steps that only multiply and accumulate (no write to TEMP,
|
||||
MEMS, FRC, Y, ADRS, EFREG or the delay RAM), decoded from MPRO when
|
||||
it changes (Dirty) and run by a short path in SCSPDSP_Step */
|
||||
int Dirty;
|
||||
struct
|
||||
{
|
||||
UINT8 mac; /* the step is one of them */
|
||||
UINT8 tra, ira, coef;
|
||||
UINT8 xsel, ysel;
|
||||
UINT8 bsel; /* 0: zero, 1: ACC, 2: TEMP */
|
||||
UINT8 negb;
|
||||
} MAC[128];
|
||||
};
|
||||
|
||||
/* sign-extend the low "bits" bits of v */
|
||||
@@ -53,22 +66,29 @@ static INLINE INT32 SCSPDSP_clamp24( INT32 v )
|
||||
return v;
|
||||
}
|
||||
|
||||
/* port: leading zeros of a 12-bit value (12 for 0), for SCSPDSP_PACK */
|
||||
static UINT8 SCSPDSP_lz12[ 4096 ];
|
||||
|
||||
static void SCSPDSP_InitTables( void )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 4096; i++ )
|
||||
{
|
||||
int n = 0;
|
||||
while( n < 12 && !( i & ( 0x800 >> n ) ) )
|
||||
n++;
|
||||
SCSPDSP_lz12[ i ] = n;
|
||||
}
|
||||
}
|
||||
|
||||
/* 24 bit value to the 16 bit floating point format of the delay RAM */
|
||||
static UINT16 SCSPDSP_PACK( INT32 val )
|
||||
{
|
||||
UINT32 uval = (UINT32)val;
|
||||
UINT32 sign = ( uval >> 23 ) & 1;
|
||||
UINT32 temp = ( uval ^ ( uval << 1 ) ) & 0xffffff;
|
||||
UINT32 exponent = 0;
|
||||
int k;
|
||||
|
||||
for( k = 0; k < 12; k++ )
|
||||
{
|
||||
if( temp & 0x800000 )
|
||||
break;
|
||||
temp <<= 1;
|
||||
exponent += 1;
|
||||
}
|
||||
/* the leading zeros of bits 23-12, up to 12 */
|
||||
UINT32 exponent = SCSPDSP_lz12[ temp >> 12 ];
|
||||
if( exponent < 12 )
|
||||
uval = ( uval << exponent ) & 0x3fffff;
|
||||
else
|
||||
@@ -103,11 +123,45 @@ static INT32 SCSPDSP_UNPACK( UINT16 val )
|
||||
|
||||
static void SCSPDSP_Init( struct _SCSPDSP *DSP, UINT16 *ram, UINT32 ramsize )
|
||||
{
|
||||
SCSPDSP_InitTables();
|
||||
memset( DSP, 0, sizeof( *DSP ) );
|
||||
DSP->RAM = ram;
|
||||
DSP->RAMmask = ( ramsize / 2 ) - 1;
|
||||
DSP->RBL = 8 * 1024;
|
||||
DSP->Stopped = 1;
|
||||
DSP->Dirty = 1;
|
||||
}
|
||||
|
||||
static void SCSPDSP_Decode( struct _SCSPDSP *DSP )
|
||||
{
|
||||
int step;
|
||||
|
||||
for( step = 0; step < 128; ++step )
|
||||
{
|
||||
UINT16 *IPtr = DSP->MPRO + ( step * 4 );
|
||||
UINT32 TWT = ( IPtr[0] >> 7 ) & 0x01;
|
||||
UINT32 IRA = ( IPtr[1] >> 6 ) & 0x3f;
|
||||
UINT32 IWT = ( IPtr[1] >> 5 ) & 0x01;
|
||||
UINT32 MWT = ( IPtr[2] >> 14 ) & 0x01;
|
||||
UINT32 MRD = ( IPtr[2] >> 13 ) & 0x01;
|
||||
UINT32 EWT = ( IPtr[2] >> 12 ) & 0x01;
|
||||
UINT32 ADRL = ( IPtr[2] >> 7 ) & 0x01;
|
||||
UINT32 FRCL = ( IPtr[2] >> 6 ) & 0x01;
|
||||
UINT32 YRL = ( IPtr[2] >> 3 ) & 0x01;
|
||||
UINT32 ZERO = ( IPtr[2] >> 1 ) & 0x01;
|
||||
UINT32 BSEL = ( IPtr[2] >> 0 ) & 0x01;
|
||||
|
||||
DSP->MAC[step].mac = !TWT && !IWT && !EWT && !ADRL && !FRCL && !YRL && IRA <= 0x31 &&
|
||||
!( ( MRD || MWT ) && ( step & 1 ) );
|
||||
DSP->MAC[step].tra = ( IPtr[0] >> 8 ) & 0x7f;
|
||||
DSP->MAC[step].ira = IRA;
|
||||
DSP->MAC[step].coef = ( IPtr[3] >> 9 ) & 0x3f;
|
||||
DSP->MAC[step].xsel = ( IPtr[1] >> 15 ) & 0x01;
|
||||
DSP->MAC[step].ysel = ( IPtr[1] >> 13 ) & 0x03;
|
||||
DSP->MAC[step].bsel = ZERO ? 0 : BSEL ? 1 : 2;
|
||||
DSP->MAC[step].negb = ( IPtr[2] >> 2 ) & 0x01;
|
||||
}
|
||||
DSP->Dirty = 0;
|
||||
}
|
||||
|
||||
static void SCSPDSP_Step( struct _SCSPDSP *DSP )
|
||||
@@ -130,8 +184,59 @@ static void SCSPDSP_Step( struct _SCSPDSP *DSP )
|
||||
|
||||
memset( DSP->EFREG, 0, sizeof( DSP->EFREG ) );
|
||||
|
||||
if( DSP->Dirty )
|
||||
SCSPDSP_Decode( DSP );
|
||||
|
||||
for( step = 0; step < DSP->LastStep; ++step )
|
||||
{
|
||||
if( DSP->MAC[step].mac )
|
||||
{
|
||||
/* the same as below for such a step: the shifter output and
|
||||
INPUTS are not used */
|
||||
INT32 TEMPV = 0;
|
||||
UINT32 ysel = DSP->MAC[step].ysel;
|
||||
|
||||
if( !DSP->MAC[step].xsel || DSP->MAC[step].bsel == 2 )
|
||||
TEMPV = SCSPDSP_sext( DSP->TEMP[( DSP->MAC[step].tra + DSP->DEC ) & 0x7f], 24 );
|
||||
|
||||
if( DSP->MAC[step].xsel )
|
||||
{
|
||||
UINT32 IRA = DSP->MAC[step].ira;
|
||||
if( IRA <= 0x1f )
|
||||
X = DSP->MEMS[IRA];
|
||||
else if( IRA <= 0x2f )
|
||||
X = DSP->MIXS[IRA - 0x20] << 4;
|
||||
else
|
||||
X = DSP->EXTS[IRA - 0x30] << 8;
|
||||
X = SCSPDSP_sext( X, 24 );
|
||||
}
|
||||
else
|
||||
X = TEMPV;
|
||||
|
||||
if( DSP->MAC[step].bsel == 0 )
|
||||
B = 0;
|
||||
else
|
||||
{
|
||||
B = DSP->MAC[step].bsel == 1 ? ACC : TEMPV;
|
||||
if( DSP->MAC[step].negb )
|
||||
B = 0 - B;
|
||||
}
|
||||
|
||||
if( ysel == 0 )
|
||||
Y = FRC_REG;
|
||||
else if( ysel == 1 )
|
||||
Y = DSP->COEF[DSP->MAC[step].coef] >> 3;
|
||||
else if( ysel == 2 )
|
||||
Y = ( Y_REG >> 11 ) & 0x1fff;
|
||||
else
|
||||
Y = ( Y_REG >> 4 ) & 0x0fff;
|
||||
Y = SCSPDSP_sext( Y, 13 );
|
||||
|
||||
ACC = (INT32)( ( ( (INT64)X * (INT64)Y ) >> 12 ) + B );
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
UINT16 *IPtr = DSP->MPRO + ( step * 4 );
|
||||
|
||||
UINT32 TRA = ( IPtr[0] >> 8 ) & 0x7f;
|
||||
@@ -284,6 +389,7 @@ static void SCSPDSP_Step( struct _SCSPDSP *DSP )
|
||||
|
||||
if( EWT )
|
||||
DSP->EFREG[EWA] += SHIFTED >> 8;
|
||||
}
|
||||
}
|
||||
--DSP->DEC;
|
||||
memset( DSP->MIXS, 0, sizeof( DSP->MIXS ) );
|
||||
@@ -301,4 +407,5 @@ static void SCSPDSP_Start( struct _SCSPDSP *DSP )
|
||||
break;
|
||||
}
|
||||
DSP->LastStep = i + 1;
|
||||
DSP->Dirty = 1;
|
||||
}
|
||||
+153
-67
@@ -2285,6 +2285,8 @@ void model2_geo_parse( void )
|
||||
/* drawn pixels carry an opaque marker in the top byte (the alpha of rgb_t in
|
||||
MAME), so a black pixel (dark shadows) is not taken as transparent */
|
||||
#define M2_PIXEL_OPAQUE 0xff000000
|
||||
/* a pixel is kept as the 15-bit colour of the bitmap, from 8-bit components */
|
||||
#define M2_PIXEL( r, g, b ) ( M2_PIXEL_OPAQUE | ( ( (r) >> 3 ) << 10 ) | ( ( (g) >> 3 ) << 5 ) | ( (b) >> 3 ) )
|
||||
|
||||
/* the 3D frame. A drawn pixel is never 0 (M2_PIXEL_OPAQUE), so the buffer
|
||||
is its own fill map: polygons are drawn front to back and the first one
|
||||
@@ -2298,8 +2300,11 @@ static int m_dirty_minx, m_dirty_maxx, m_dirty_miny, m_dirty_maxy; /* empty: min
|
||||
typedef struct
|
||||
{
|
||||
const UINT32 *sheet;
|
||||
const UINT8 *dsheet; /* the same sheet one byte per texel (model2_texdec0/1) */
|
||||
UINT32 width, height; /* in texels, powers of two */
|
||||
UINT32 x, y; /* position in the texture sheet */
|
||||
int inside; /* the whole level is inside the sheet */
|
||||
const UINT8 *dbase; /* inside, at an even x and y: its texel (0, 0) in dsheet */
|
||||
} m2_tex_level;
|
||||
|
||||
typedef struct
|
||||
@@ -2318,9 +2323,39 @@ typedef struct
|
||||
m2_tex_level level[ 16 ]; /* 0: the microtexture, 1 + n: mipmap level n */
|
||||
} m2_poly_extra_data;
|
||||
|
||||
/* the texel fetch and the textured span are inlined in the opaque and the
|
||||
translucent spans */
|
||||
#if defined(__GNUC__)
|
||||
#define M2_ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define M2_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
/* two neighbouring texels of a translucent texture, 4 bits each (index:
|
||||
first << 4 | second), as the filtering takes them: the alpha component
|
||||
(0x80 when not transparent, value 15) packed into the upper 16 bits,
|
||||
and a transparent texel taking the luma of the other one, the first
|
||||
one done first */
|
||||
static UINT32 m2_tex_pair[ 256 ][ 2 ];
|
||||
|
||||
static void m2_tex_pair_init( void )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
UINT32 a = ( i >> 4 ) << 4, b = ( i & 15 ) << 4;
|
||||
if( a != 0xf0 ) a |= 0x00800000;
|
||||
if( b != 0xf0 ) b |= 0x00800000;
|
||||
if( a == 0x000000f0 ) a = b & 0xff;
|
||||
if( b == 0x000000f0 ) b = a & 0xff;
|
||||
m2_tex_pair[ i ][ 0 ] = a;
|
||||
m2_tex_pair[ i ][ 1 ] = b;
|
||||
}
|
||||
}
|
||||
|
||||
#define LERP( x, y, a ) ( ( (x) + ( ( ( (y) - (x) ) * (a) ) >> 8 ) ) & 0x00ff00ff )
|
||||
|
||||
static UINT32 fetch_bilinear_texel( const m2_poly_extra_data *object, int translucent, INT32 miplevel, INT32 u, INT32 v )
|
||||
static INLINE M2_ALWAYS_INLINE UINT32 fetch_bilinear_texel( const m2_poly_extra_data *object, int translucent, INT32 miplevel, INT32 u, INT32 v )
|
||||
{
|
||||
UINT32 tex_wrap_x = object->texwrapx;
|
||||
UINT32 tex_wrap_y = object->texwrapy;
|
||||
@@ -2378,6 +2413,32 @@ static UINT32 fetch_bilinear_texel( const m2_poly_extra_data *object, int transl
|
||||
v1 = v0, v0--, vfrac = 0x100;
|
||||
}
|
||||
|
||||
/* the four texels from the sheet taken apart (model2_tex_decode), when
|
||||
none of them is past the sheet: the columns with the parity of the
|
||||
texture coordinate, as the word layout below */
|
||||
if( level->dbase )
|
||||
{
|
||||
/* at an even position the columns and rows are in order */
|
||||
const UINT8 *r0 = level->dbase + v0 * 2048;
|
||||
const UINT8 *r1 = level->dbase + v1 * 2048;
|
||||
tex00 = r0[ u0 ] << 4;
|
||||
tex01 = r0[ u1 ] << 4;
|
||||
tex10 = r1[ u0 ] << 4;
|
||||
tex11 = r1[ u1 ] << 4;
|
||||
}
|
||||
else if( level->inside || ( tex_x + u1 < 2048 && tex_x + u0 < 2048 && tex_y + v0 < 1024 && tex_y + v1 < 1024 ) )
|
||||
{
|
||||
const UINT8 *d = level->dsheet;
|
||||
UINT32 xc0 = ( ( tex_x + u0 ) & ~1 ) | ( u0 & 1 );
|
||||
UINT32 xc1 = ( ( tex_x + u1 ) & ~1 ) | ( u1 & 1 );
|
||||
UINT32 yr0 = ( ( ( tex_y + v0 ) & ~1 ) | ( v0 & 1 ) ) * 2048;
|
||||
UINT32 yr1 = ( ( ( tex_y + v1 ) & ~1 ) | ( v1 & 1 ) ) * 2048;
|
||||
tex00 = d[ yr0 + xc0 ] << 4;
|
||||
tex01 = d[ yr0 + xc1 ] << 4;
|
||||
tex10 = d[ yr1 + xc0 ] << 4;
|
||||
tex11 = d[ yr1 + xc1 ] << 4;
|
||||
}
|
||||
else
|
||||
/* the four 4-bit texels. Texture sheets are mapped as 2048x1024 but
|
||||
stored in RAM as 1024x2048: past column 1024 a texel is in the other
|
||||
half of the rows. A 32-bit word holds two 2x2 blocks: bit 1 of the
|
||||
@@ -2409,17 +2470,16 @@ static UINT32 fetch_bilinear_texel( const m2_poly_extra_data *object, int transl
|
||||
if( ( tex00 & tex01 & tex10 & tex11 ) == 0xf0 )
|
||||
return 0x000000f0;
|
||||
|
||||
/* pack the alpha components into the upper 16 bits */
|
||||
if( tex00 != 0xf0 ) tex00 |= 0x00800000;
|
||||
if( tex01 != 0xf0 ) tex01 |= 0x00800000;
|
||||
if( tex10 != 0xf0 ) tex10 |= 0x00800000;
|
||||
if( tex11 != 0xf0 ) tex11 |= 0x00800000;
|
||||
|
||||
/* a transparent texel takes the luma of the neighbouring texel */
|
||||
if( tex00 == 0x000000f0 ) tex00 = tex01 & 0xff;
|
||||
if( tex01 == 0x000000f0 ) tex01 = tex00 & 0xff;
|
||||
if( tex10 == 0x000000f0 ) tex10 = tex11 & 0xff;
|
||||
if( tex11 == 0x000000f0 ) tex11 = tex10 & 0xff;
|
||||
/* the alpha components packed into the upper 16 bits, a transparent
|
||||
texel taking the luma of its neighbour: m2_tex_pair, per pair */
|
||||
{
|
||||
const UINT32 *q0 = m2_tex_pair[ tex00 | ( tex01 >> 4 ) ];
|
||||
const UINT32 *q1 = m2_tex_pair[ tex10 | ( tex11 >> 4 ) ];
|
||||
tex00 = q0[ 0 ];
|
||||
tex01 = q0[ 1 ];
|
||||
tex10 = q1[ 0 ];
|
||||
tex11 = q1[ 1 ];
|
||||
}
|
||||
}
|
||||
|
||||
tex0x = LERP( tex00, tex01, ufrac );
|
||||
@@ -2490,7 +2550,7 @@ static void draw_scanline_solid( int scanline, int startx, int stopx, const m2_p
|
||||
tr = model2_gamma_table[ colortable_r[ luma ] & 0xff ];
|
||||
tg = model2_gamma_table[ colortable_g[ luma ] & 0xff ];
|
||||
tb = model2_gamma_table[ colortable_b[ luma ] & 0xff ];
|
||||
color = M2_PIXEL_OPAQUE | ( tr << 16 ) | ( tg << 8 ) | tb;
|
||||
color = M2_PIXEL( tr, tg, tb );
|
||||
|
||||
x = startx;
|
||||
dx = object->checker ? 2 : 1;
|
||||
@@ -2504,7 +2564,13 @@ static void draw_scanline_solid( int scanline, int startx, int stopx, const m2_p
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, float uoz, float voz,
|
||||
/* the pixels of the texels of the last colours drawn (0: not worked out
|
||||
yet; a pixel always has M2_PIXEL_OPAQUE). Cleared at every frame, since
|
||||
the luma RAM, the colour tables and the gamma can change between frames */
|
||||
static UINT32 m_texcolor[ 128 ];
|
||||
static UINT32 m_texcolor_key[ 3 ];
|
||||
|
||||
static INLINE M2_ALWAYS_INLINE void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, float uoz, float voz,
|
||||
float dooz, float duoz, float dvoz, const m2_poly_extra_data *object, int translucent )
|
||||
{
|
||||
UINT32 *p = &m_destmap[ scanline * DEST_W ];
|
||||
@@ -2515,9 +2581,18 @@ static void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, f
|
||||
UINT32 lumabase = object->lumabase;
|
||||
INT32 max_level = object->max_level;
|
||||
UINT32 obj_luma = object->luma;
|
||||
INT32 texlod = object->texlod;
|
||||
int utex = object->utex, utexminlod = object->utexminlod;
|
||||
int x, dx;
|
||||
|
||||
colorbase = model2_palram[ ( colorbase + 0x1000 ) & 0x1fff ] & 0x7fff;
|
||||
if( colorbase != m_texcolor_key[ 0 ] || lumabase != m_texcolor_key[ 1 ] || obj_luma != m_texcolor_key[ 2 ] )
|
||||
{
|
||||
memset( m_texcolor, 0, sizeof( m_texcolor ) );
|
||||
m_texcolor_key[ 0 ] = colorbase;
|
||||
m_texcolor_key[ 1 ] = lumabase;
|
||||
m_texcolor_key[ 2 ] = obj_luma;
|
||||
}
|
||||
colortable_r += ( ( colorbase >> 0 ) & 0x1f ) << 8;
|
||||
colortable_g += ( ( colorbase >> 5 ) & 0x1f ) << 8;
|
||||
colortable_b += ( ( colorbase >> 10 ) & 0x1f ) << 8;
|
||||
@@ -2550,7 +2625,7 @@ static void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, f
|
||||
continue;
|
||||
|
||||
z = 1.0f / ooz;
|
||||
mml = -object->texlod + fast_log2( z );
|
||||
mml = -texlod + fast_log2( z );
|
||||
level = mml >> 7;
|
||||
if( level < 0 ) level = 0;
|
||||
if( level > max_level ) level = max_level;
|
||||
@@ -2562,17 +2637,23 @@ static void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, f
|
||||
|
||||
if( mml > 0 && level < max_level )
|
||||
{
|
||||
UINT32 t2 = fetch_bilinear_texel( object, translucent, level + 1, u, v );
|
||||
UINT32 t2;
|
||||
INT32 frac = ( mml & 127 ) << 1;
|
||||
/* translucent, four transparent texels and less than half of the
|
||||
next level: under 50% whatever that one gives (its alpha is at
|
||||
most 0x80), discarded below */
|
||||
if( translucent && t == 0x000000f0 && frac < 128 )
|
||||
continue;
|
||||
t2 = fetch_bilinear_texel( object, translucent, level + 1, u, v );
|
||||
t = LERP( t, t2, frac );
|
||||
}
|
||||
else if( object->utex && mml < 0 && ( !translucent || t >= 0x00010000 ) )
|
||||
else if( utex && mml < 0 && ( !translucent || t >= 0x00010000 ) )
|
||||
{
|
||||
/* (with no alpha, a translucent texel stays under 50% after this
|
||||
blend, and is discarded below) */
|
||||
/* microtexture; blend up to almost 50% */
|
||||
UINT32 t2 = fetch_bilinear_texel( object, translucent, -1, u, v );
|
||||
INT32 frac = -mml >> object->utexminlod;
|
||||
INT32 frac = -mml >> utexminlod;
|
||||
if( frac > 127 ) frac = 127;
|
||||
t = LERP( t, t2, frac );
|
||||
}
|
||||
@@ -2585,19 +2666,41 @@ static void draw_scanline_tex( int scanline, int startx, int stopx, float ooz, f
|
||||
t &= 0xff;
|
||||
}
|
||||
|
||||
/* 8 bits of filtered texel, 128 entries in the translator map */
|
||||
luma = (UINT8)( ( (UINT32)model2_lumaram[ ( lumabase + ( t >> 1 ) ) & 0x7fff ] * obj_luma ) >> 8 );
|
||||
if( luma > 0x3f )
|
||||
luma = 0x3f;
|
||||
/* 8 bits of filtered texel, 128 entries in the translator map; the
|
||||
pixel of each entry is worked out once for the polygon's colours */
|
||||
{
|
||||
UINT32 c = m_texcolor[ t >> 1 ];
|
||||
if( !c )
|
||||
{
|
||||
luma = (UINT8)( ( (UINT32)model2_lumaram[ ( lumabase + ( t >> 1 ) ) & 0x7fff ] * obj_luma ) >> 8 );
|
||||
if( luma > 0x3f )
|
||||
luma = 0x3f;
|
||||
|
||||
tr = model2_gamma_table[ colortable_r[ luma ] & 0xff ];
|
||||
tg = model2_gamma_table[ colortable_g[ luma ] & 0xff ];
|
||||
tb = model2_gamma_table[ colortable_b[ luma ] & 0xff ];
|
||||
tr = model2_gamma_table[ colortable_r[ luma ] & 0xff ];
|
||||
tg = model2_gamma_table[ colortable_g[ luma ] & 0xff ];
|
||||
tb = model2_gamma_table[ colortable_b[ luma ] & 0xff ];
|
||||
|
||||
p[ x ] = M2_PIXEL_OPAQUE | ( tr << 16 ) | ( tg << 8 ) | tb;
|
||||
c = M2_PIXEL( tr, tg, tb );
|
||||
m_texcolor[ t >> 1 ] = c;
|
||||
}
|
||||
p[ x ] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* the opaque and the translucent spans, each with the texel fetches inlined */
|
||||
static void draw_scanline_tex_opaque( int scanline, int startx, int stopx, float ooz, float uoz, float voz,
|
||||
float dooz, float duoz, float dvoz, const m2_poly_extra_data *object )
|
||||
{
|
||||
draw_scanline_tex( scanline, startx, stopx, ooz, uoz, voz, dooz, duoz, dvoz, object, 0 );
|
||||
}
|
||||
|
||||
static void draw_scanline_tex_trans( int scanline, int startx, int stopx, float ooz, float uoz, float voz,
|
||||
float dooz, float duoz, float dvoz, const m2_poly_extra_data *object )
|
||||
{
|
||||
draw_scanline_tex( scanline, startx, stopx, ooz, uoz, voz, dooz, duoz, dvoz, object, 1 );
|
||||
}
|
||||
|
||||
/* scanline rasterization of a convex polygon, pixel centres at +0.5 */
|
||||
static void rasterize_polygon( const poly_vertex *v, int n, int minx, int maxx, int miny, int maxy,
|
||||
const m2_poly_extra_data *extra, int textured, int translucent )
|
||||
@@ -2680,9 +2783,9 @@ static void rasterize_polygon( const poly_vertex *v, int n, int minx, int maxx,
|
||||
if( textured )
|
||||
{
|
||||
float off = ( startx + 0.5f ) - xl;
|
||||
draw_scanline_tex( y, startx, stopx,
|
||||
( translucent ? draw_scanline_tex_trans : draw_scanline_tex_opaque )( y, startx, stopx,
|
||||
pl[ 0 ] + dpdx[ 0 ] * off, pl[ 1 ] + dpdx[ 1 ] * off, pl[ 2 ] + dpdx[ 2 ] * off,
|
||||
dpdx[ 0 ], dpdx[ 1 ], dpdx[ 2 ], extra, translucent );
|
||||
dpdx[ 0 ], dpdx[ 1 ], dpdx[ 2 ], extra );
|
||||
}
|
||||
else
|
||||
draw_scanline_solid( y, startx, stopx, extra, translucent );
|
||||
@@ -2743,18 +2846,24 @@ static void model2_3d_render( polygon *poly, const struct rectangle *cliprect )
|
||||
int level;
|
||||
extra.max_level = 30 - count_leading_zeros32( minwh );
|
||||
extra.level[ 0 ].sheet = extra.texsheet[ 1 ];
|
||||
extra.level[ 0 ].dsheet = ( extra.texsheet[ 1 ] == model2_textureram0 ) ? model2_texdec0 : model2_texdec1;
|
||||
extra.level[ 0 ].width = 128;
|
||||
extra.level[ 0 ].height = 128;
|
||||
extra.level[ 0 ].x = extra.utexx;
|
||||
extra.level[ 0 ].y = extra.utexy;
|
||||
extra.level[ 0 ].inside = 1;
|
||||
extra.level[ 0 ].dbase = extra.level[ 0 ].dsheet + extra.utexy * 2048 + extra.utexx;
|
||||
for( level = 0; level <= extra.max_level; level++ )
|
||||
{
|
||||
m2_tex_level *l = &extra.level[ level + 1 ];
|
||||
l->sheet = extra.texsheet[ level & 1 ];
|
||||
l->dsheet = ( l->sheet == model2_textureram0 ) ? model2_texdec0 : model2_texdec1;
|
||||
l->width = extra.texwidth >> level;
|
||||
l->height = extra.texheight >> level;
|
||||
l->x = ( ( extra.texx - 2048 ) >> level ) & 2047;
|
||||
l->y = ( ( extra.texy - 1024 ) >> level ) & 1023;
|
||||
l->inside = l->x + l->width <= 2048 && l->y + l->height <= 1024;
|
||||
l->dbase = ( l->inside && !( ( l->x | l->y ) & 1 ) ) ? l->dsheet + l->y * 2048 + l->x : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2791,11 +2900,14 @@ static void composite_3d( struct mame_bitmap *bitmap, const struct rectangle *cl
|
||||
{
|
||||
UINT16 *dst = (UINT16 *)bitmap->line[ y ];
|
||||
const UINT32 *src = &m_destmap[ y * DEST_W ];
|
||||
const UINT8 *pri = (const UINT8 *)priority_bitmap->line[ y ];
|
||||
for( x = minx; x <= maxx; x++ )
|
||||
{
|
||||
UINT32 c = src[ x ];
|
||||
if( c )
|
||||
dst[ x ] = ( ( c >> 9 ) & 0x7c00 ) | ( ( c >> 6 ) & 0x03e0 ) | ( ( c >> 3 ) & 0x001f );
|
||||
/* not over a tile pixel in front of the polygons: the highest
|
||||
bit of its priority value is odd (see VIDEO_UPDATE) */
|
||||
if( c && ( pri[ x ] & 0xaa ) <= ( pri[ x ] & 0x55 ) )
|
||||
dst[ x ] = (UINT16)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2822,6 +2934,7 @@ static void render_polygons( struct mame_bitmap *bitmap, const struct rectangle
|
||||
memset( &m_destmap[ y * DEST_W + m_dirty_minx ], 0, ( m_dirty_maxx - m_dirty_minx + 1 ) * sizeof( UINT32 ) );
|
||||
m_dirty_minx = m_dirty_miny = DEST_W;
|
||||
m_dirty_maxx = m_dirty_maxy = -1;
|
||||
memset( m_texcolor, 0, sizeof( m_texcolor ) );
|
||||
|
||||
for( window = raster->cur_window; window >= 0; window-- )
|
||||
{
|
||||
@@ -2862,8 +2975,6 @@ READ32_HANDLER( model2_polygon_count_r )
|
||||
}
|
||||
|
||||
/* the tile layers, mixed (see VIDEO_UPDATE) */
|
||||
static struct mame_bitmap *m_tilemap; /* the tile layers, mixed */
|
||||
static UINT8 m_tile_front[ 256 ];
|
||||
|
||||
/* light gun crosshairs (Virtua Cop, Virtua Cop 2, The House of the Dead):
|
||||
the gun ports span the whole screen, as PORT_CROSSHAIR( X/Y, 1.0, 0.0 )
|
||||
@@ -2921,23 +3032,11 @@ static void draw_gun_crosshairs( struct mame_bitmap *bitmap, const struct rectan
|
||||
|
||||
VIDEO_START( model2 )
|
||||
{
|
||||
int i;
|
||||
m2_tex_pair_init();
|
||||
|
||||
if( sys24_tile_vh_start( 0x3fff ) )
|
||||
return 1;
|
||||
|
||||
m_tilemap = auto_bitmap_alloc( Machine->drv->screen_width, Machine->drv->screen_height );
|
||||
if( !m_tilemap )
|
||||
return 1;
|
||||
/* priority bitmap value -> the winning tile pixel is in front of the polygons */
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
int b = 7;
|
||||
while( b > 0 && !( i & ( 1 << b ) ) )
|
||||
b--;
|
||||
m_tile_front[ i ] = b & 1;
|
||||
}
|
||||
|
||||
m_raster = auto_malloc( sizeof( raster_state ) );
|
||||
m_geo = auto_malloc( sizeof( geo_state ) );
|
||||
memset( m_raster, 0, sizeof( raster_state ) );
|
||||
@@ -3006,25 +3105,13 @@ VIDEO_START( model2 )
|
||||
A: on the Virtua Cop 2 stage select the city map (B, priority set) hid
|
||||
"SHOOT TO SELECT" (A).
|
||||
|
||||
The tiles are drawn back to front into m_tilemap, each layer and
|
||||
priority setting its own bit in the priority bitmap: bit 2*depth+prio,
|
||||
with depth 0 for the back layer. The highest bit set gives the winning
|
||||
pixel and its priority.
|
||||
The tiles are drawn back to front straight into the bitmap, each
|
||||
layer and priority setting its own bit in the priority bitmap: bit
|
||||
2*depth+prio, with depth 0 for the back layer. The highest bit set
|
||||
gives the winning pixel and its priority: the polygons are then drawn
|
||||
where it is even (behind them) or there is no tile pixel. A highest bit
|
||||
odd is the same as the odd bits above the even ones.
|
||||
*/
|
||||
static void copy_tiles( struct mame_bitmap *bitmap, const struct rectangle *cliprect, int front )
|
||||
{
|
||||
int x, y;
|
||||
for( y = cliprect->min_y; y <= cliprect->max_y; y++ )
|
||||
{
|
||||
UINT16 *dst = (UINT16 *)bitmap->line[ y ];
|
||||
const UINT16 *src = (const UINT16 *)m_tilemap->line[ y ];
|
||||
const UINT8 *pri = (const UINT8 *)priority_bitmap->line[ y ];
|
||||
for( x = cliprect->min_x; x <= cliprect->max_x; x++ )
|
||||
if( pri[ x ] && m_tile_front[ pri[ x ] ] == front )
|
||||
dst[ x ] = src[ x ];
|
||||
}
|
||||
}
|
||||
|
||||
VIDEO_UPDATE( model2 )
|
||||
{
|
||||
int layer;
|
||||
@@ -3039,13 +3126,12 @@ VIDEO_UPDATE( model2 )
|
||||
for( layer = 3; layer >= 0; layer-- )
|
||||
{
|
||||
int depth = 3 - layer;
|
||||
sys24_tile_draw( m_tilemap, cliprect, layer << 1, depth * 2, 0 );
|
||||
sys24_tile_draw( m_tilemap, cliprect, ( layer << 1 ) | 1, depth * 2 + 1, 0 );
|
||||
sys24_tile_draw( bitmap, cliprect, layer << 1, depth * 2, 0 );
|
||||
sys24_tile_draw( bitmap, cliprect, ( layer << 1 ) | 1, depth * 2 + 1, 0 );
|
||||
}
|
||||
|
||||
copy_tiles( bitmap, cliprect, 0 );
|
||||
/* the polygons go over the tile pixels behind them only */
|
||||
render_polygons( bitmap, cliprect );
|
||||
copy_tiles( bitmap, cliprect, 1 );
|
||||
|
||||
draw_gun_crosshairs( bitmap, cliprect );
|
||||
}
|
||||
+75
-12
@@ -368,6 +368,25 @@ static void sys24_tile_draw_rect(struct mame_bitmap *bm, struct mame_bitmap *tm,
|
||||
find the topmost tile layer of each pixel.
|
||||
*/
|
||||
|
||||
/* eight bytes of the transparency bitmap at once: nonzero when one of them is
|
||||
the byte repeated in every lane of 'pat' (the usual zero byte test) */
|
||||
static INLINE int sys24_trans8_has(const UINT8 *p, UINT64 pat)
|
||||
{
|
||||
const UINT64 ones = ((UINT64)0x01010101 << 32) | 0x01010101;
|
||||
UINT64 w;
|
||||
memcpy(&w, p, 8);
|
||||
w ^= pat;
|
||||
return ((w - ones) & ~w & (ones << 7)) != 0;
|
||||
}
|
||||
|
||||
/* eight bytes of the transparency bitmap all the byte of 'pat' */
|
||||
static INLINE int sys24_trans8_all(const UINT8 *p, UINT64 pat)
|
||||
{
|
||||
UINT64 w;
|
||||
memcpy(&w, p, 8);
|
||||
return w == pat;
|
||||
}
|
||||
|
||||
static void sys24_tile_draw_rect_rgb(struct mame_bitmap *bm, struct mame_bitmap *tm, struct mame_bitmap *dm, const UINT16 *mask,
|
||||
UINT16 tpri, UINT8 lpri, int win, int sx, int sy, int xx1, int yy1, int xx2, int yy2)
|
||||
{
|
||||
@@ -377,8 +396,11 @@ static void sys24_tile_draw_rect_rgb(struct mame_bitmap *bm, struct mame_bitmap
|
||||
UINT16 *dest = dm->base;
|
||||
UINT8 *prib = priority_bitmap->base;
|
||||
pen_t *pens = Machine->pens;
|
||||
UINT64 tpat;
|
||||
|
||||
tpri |= TILE_FLAG_FG_OPAQUE;
|
||||
/* tpri in every byte (a value over 0xff never matches: no group is skipped) */
|
||||
tpat = (((UINT64)0x01010101 << 32) | 0x01010101) * (tpri & 0xff);
|
||||
|
||||
dest += yy1*dm->rowpixels + xx1;
|
||||
prib += yy1*priority_bitmap->rowpixels + xx1;
|
||||
@@ -410,14 +432,26 @@ static void sys24_tile_draw_rect_rgb(struct mame_bitmap *bm, struct mame_bitmap
|
||||
/* Fast paths for the 128-pixels without side clipping case */
|
||||
|
||||
if(!m) {
|
||||
/* 1- 128 pixels from this layer */
|
||||
/* 1- 128 pixels from this layer, eight at a time: a group
|
||||
with no pixel of this priority is skipped */
|
||||
int x;
|
||||
for(x=0; x<128; x++) {
|
||||
if(*srct++ == tpri)
|
||||
{ *dst = pens[*src]; *pr |= lpri; }
|
||||
src++;
|
||||
dst++;
|
||||
pr++;
|
||||
for(x=0; x<128; x+=8) {
|
||||
if(tpri > 0xff || sys24_trans8_has(srct, tpat)) {
|
||||
int xx;
|
||||
if(tpri <= 0xff && sys24_trans8_all(srct, tpat)) {
|
||||
/* eight pixels of this priority */
|
||||
for(xx=0; xx<8; xx++)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
} else {
|
||||
for(xx=0; xx<8; xx++)
|
||||
if(srct[xx] == tpri)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
}
|
||||
}
|
||||
src += 8;
|
||||
srct += 8;
|
||||
dst += 8;
|
||||
pr += 8;
|
||||
}
|
||||
|
||||
} else if(m == 0xffff) {
|
||||
@@ -431,11 +465,17 @@ static void sys24_tile_draw_rect_rgb(struct mame_bitmap *bm, struct mame_bitmap
|
||||
/* 3- 128 pixels from both layers */
|
||||
int x;
|
||||
for(x=0; x<128; x+=8) {
|
||||
if(!(m & 0x8000)) {
|
||||
if(!(m & 0x8000) && (tpri > 0xff || sys24_trans8_has(srct, tpat))) {
|
||||
int xx;
|
||||
for(xx=0; xx<8; xx++)
|
||||
if(srct[xx] == tpri)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
if(tpri <= 0xff && sys24_trans8_all(srct, tpat)) {
|
||||
/* eight pixels of this priority */
|
||||
for(xx=0; xx<8; xx++)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
} else {
|
||||
for(xx=0; xx<8; xx++)
|
||||
if(srct[xx] == tpri)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
}
|
||||
}
|
||||
src += 8;
|
||||
srct += 8;
|
||||
@@ -448,7 +488,30 @@ static void sys24_tile_draw_rect_rgb(struct mame_bitmap *bm, struct mame_bitmap
|
||||
/* Clipped path */
|
||||
int llx1 = llx >= 128 ? 128 : llx;
|
||||
|
||||
if(!m) {
|
||||
if(!m && !cur_x && !(llx1 & 7)) {
|
||||
/* 1- the last pixels of the line from this layer, a
|
||||
whole number of groups of eight: as the fast path */
|
||||
int x;
|
||||
for(x=0; x<llx1; x+=8) {
|
||||
if(tpri > 0xff || sys24_trans8_has(srct, tpat)) {
|
||||
int xx;
|
||||
if(tpri <= 0xff && sys24_trans8_all(srct, tpat)) {
|
||||
/* eight pixels of this priority */
|
||||
for(xx=0; xx<8; xx++)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
} else {
|
||||
for(xx=0; xx<8; xx++)
|
||||
if(srct[xx] == tpri)
|
||||
{ dst[xx] = pens[src[xx]]; pr[xx] |= lpri; }
|
||||
}
|
||||
}
|
||||
src += 8;
|
||||
srct += 8;
|
||||
dst += 8;
|
||||
pr += 8;
|
||||
}
|
||||
|
||||
} else if(!m) {
|
||||
/* 1- 128 pixels from this layer */
|
||||
int x;
|
||||
for(x = cur_x; x<llx1; x++) {
|
||||
|
||||
Reference in new issue
Block a user