/***************************************************************************
PSX GPU
Preliminary software renderer by smf.
Thanks to Ryan Holtz, Pete B & Farfetch'd.
Supports:
type 1 1024x1024 framebuffer (CXD8538Q)
type 2 1024x512 framebuffer (CXD8561Q)
type 2 1024x1024 framebuffer (CXD8514Q/CXD8561Q/CXD8654Q)
Debug Keys:
M toggles mesh viewer.
V toggles vram viewer.
I toggles interleave in vram viewer.
***************************************************************************/
#include <stdarg.h>
#include "driver.h"
#include "includes/psx.h"
#define STOP_ON_ERROR ( 0 )
#define VERBOSE_LEVEL ( 0 )
INLINE void verboselog( int n_level, const char *s_fmt, ... )
{
if( VERBOSE_LEVEL >= n_level )
{
va_list v;
char buf[ 32768 ];
va_start( v, s_fmt );
vsprintf( buf, s_fmt, v );
va_end( v );
if( cpu_getactivecpu() != -1 )
{
logerror( "%08x: %s", activecpu_get_pc(), buf );
}
else
{
logerror( "(timer) : %s", buf );
}
}
}
struct FLATVERTEX
{
PAIR n_coord;
};
struct GOURAUDVERTEX
{
PAIR n_bgr;
PAIR n_coord;
};
struct FLATTEXTUREDVERTEX
{
PAIR n_coord;
PAIR n_texture;
};
struct GOURAUDTEXTUREDVERTEX
{
PAIR n_bgr;
PAIR n_coord;
PAIR n_texture;
};
static union
{
UINT32 n_entry[ 16 ];
struct
{
PAIR n_cmd;
struct FLATVERTEX vertex[ 2 ];
PAIR n_size;
} MoveImage;
struct
{
PAIR n_bgr;
PAIR n_coord;
PAIR n_size;
} FlatRectangle;
struct
{
PAIR n_bgr;
PAIR n_coord;
} FlatRectangle8x8;
struct
{
PAIR n_bgr;
PAIR n_coord;
} FlatRectangle16x16;
struct
{
PAIR n_bgr;
PAIR n_coord;
PAIR n_texture;
} Sprite8x8;
struct
{
PAIR n_bgr;
PAIR n_coord;
PAIR n_texture;
} Sprite16x16;
struct
{
PAIR n_bgr;
PAIR n_coord;
PAIR n_texture;
PAIR n_size;
} FlatTexturedRectangle;
struct
{
PAIR n_bgr;
struct FLATVERTEX vertex[ 4 ];
} FlatPolygon;
struct
{
struct GOURAUDVERTEX vertex[ 4 ];
} GouraudPolygon;
struct
{
PAIR n_bgr;
struct FLATVERTEX vertex[ 2 ];
} MonochromeLine;
struct
{
struct GOURAUDVERTEX vertex[ 2 ];
} GouraudLine;
struct
{
PAIR n_bgr;
struct FLATTEXTUREDVERTEX vertex[ 4 ];
} FlatTexturedPolygon;
struct
{
struct GOURAUDTEXTUREDVERTEX vertex[ 4 ];
} GouraudTexturedPolygon;
struct
{
PAIR n_bgr;
struct FLATVERTEX vertex;
} Dot;
} m_packet;
static struct PSXGPU
{
INT32 n_tx;
INT32 n_ty;
INT32 n_abr;
INT32 n_tp;
INT32 n_ix;
INT32 n_iy;
INT32 n_ti;
} psxgpu;
static UINT16 *m_p_vram;
static UINT32 m_n_vram_size;
static UINT32 m_n_gpu_buffer_offset;
static UINT32 m_n_vramx;
static UINT32 m_n_vramy;
static UINT32 m_n_twy;
static UINT32 m_n_twx;
static UINT32 m_n_twh;
static UINT32 m_n_tww;
static UINT32 m_n_drawarea_x1;
static UINT32 m_n_drawarea_y1;
static UINT32 m_n_drawarea_x2;
static UINT32 m_n_drawarea_y2;
static UINT32 m_n_horiz_disstart;
static UINT32 m_n_horiz_disend;
static UINT32 m_n_vert_disstart;
static UINT32 m_n_vert_disend;
static UINT32 m_b_reverseflag;
static INT32 m_n_drawoffset_x;
static INT32 m_n_drawoffset_y;
static UINT32 m_n_displaystartx;
static UINT32 m_n_displaystarty;
static UINT32 m_n_gpustatus;
static UINT32 m_n_gpuinfo;
static UINT32 m_n_lightgun_x;
static UINT32 m_n_lightgun_y;
static UINT32 m_n_screenwidth;
static UINT32 m_n_screenheight;
#define MAX_LEVEL ( 32 )
#define MID_LEVEL ( ( MAX_LEVEL / 2 ) << 8 )
#define MAX_SHADE ( 0x100 )
#define MID_SHADE ( 0x80 )
static int m_n_gputype;
static UINT16 *m_p_p_vram[ 1024 ];
static UINT16 m_p_n_redshade[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_greenshade[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_blueshade[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_redlevel[ 0x10000 ];
static UINT16 m_p_n_greenlevel[ 0x10000 ];
static UINT16 m_p_n_bluelevel[ 0x10000 ];
static UINT16 m_p_n_f025[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_f05[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_f1[ MAX_LEVEL * MAX_SHADE ];
static UINT16 m_p_n_redb05[ 0x10000 ];
static UINT16 m_p_n_greenb05[ 0x10000 ];
static UINT16 m_p_n_blueb05[ 0x10000 ];
static UINT16 m_p_n_redb1[ 0x10000 ];
static UINT16 m_p_n_greenb1[ 0x10000 ];
static UINT16 m_p_n_blueb1[ 0x10000 ];
static UINT16 m_p_n_redaddtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_greenaddtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_blueaddtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_redsubtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_greensubtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_bluesubtrans[ MAX_LEVEL * MAX_LEVEL ];
static UINT16 m_p_n_nextpointlist4[] = { 1, 3, 0, 2 };
static UINT16 m_p_n_prevpointlist4[] = { 2, 0, 3, 1 };
static UINT16 m_p_n_nextpointlist3[] = { 1, 2, 0 };
static UINT16 m_p_n_prevpointlist3[] = { 2, 0, 1 };
static UINT16 m_p_n_g0r0[ 0x10000 ];
static UINT16 m_p_n_b0[ 0x10000 ];
static UINT16 m_p_n_r1[ 0x10000 ];
static UINT16 m_p_n_b1g1[ 0x10000 ];
#define SINT11( x ) ( ( (INT32)( x ) << 21 ) >> 21 )
#define ADJUST_COORD( a ) \
a.w.l = COORD_X( a ) + m_n_drawoffset_x; \
a.w.h = COORD_Y( a ) + m_n_drawoffset_y;
#define COORD_X( a ) ( (INT16)a.w.l )
#define COORD_Y( a ) ( (INT16)a.w.h )
#define SIZE_W( a ) ( a.w.l )
#define SIZE_H( a ) ( a.w.h )
#define BGR_C( a ) ( a.b.h3 )
#define BGR_B( a ) ( a.b.h2 )
#define BGR_G( a ) ( a.b.h )
#define BGR_R( a ) ( a.b.l )
#define TEXTURE_V( a ) ( (UINT8)a.b.h )
#define TEXTURE_U( a ) ( (UINT8)a.b.l )
PALETTE_INIT( psx )
{
UINT32 n_colour;
for( n_colour = 0; n_colour < 0x10000; n_colour++ )
{
palette_set_color_rgb( machine, n_colour, pal5bit(n_colour >> 0), pal5bit(n_colour >> 5), pal5bit(n_colour >> 10) );
}
}
#if defined( MAME_DEBUG )
#define DEBUG_COORDS ( 10 )
static mame_bitmap *debugmesh;
static int m_b_debugclear;
static int m_b_debugmesh;
static int m_n_debugskip;
static int m_b_debugtexture;
static int m_n_debuginterleave;
static int m_n_debugcoord;
static int m_n_debugcoordx[ DEBUG_COORDS ];
static int m_n_debugcoordy[ DEBUG_COORDS ];
#define DEBUG_MAX ( 512 )
static void DebugMeshInit( void )
{
m_b_debugmesh = 0;
m_b_debugtexture = 0;
m_n_debuginterleave = -1;
m_b_debugclear = 1;
m_n_debugcoord = 0;
m_n_debugskip = 0;
debugmesh = auto_bitmap_alloc( Machine->screen[0].width, Machine->screen[0].height, BITMAP_FORMAT_INDEXED16 );
}
static void DebugMesh( int n_coordx, int n_coordy )
{
int n_coord;
int n_colour;
if( m_b_debugclear )
{
fillbitmap( debugmesh, 0x0000, NULL );
m_b_debugclear = 0;
}
if( m_n_debugcoord < DEBUG_COORDS )
{
n_coordx += m_n_displaystartx;
n_coordy += m_n_displaystarty;
n_coordx *= 511;
n_coordx /= DEBUG_MAX - 1;
n_coordx += 256;
n_coordy *= 511;
n_coordy /= DEBUG_MAX - 1;
n_coordy += 256;
m_n_debugcoordx[ m_n_debugcoord ] = n_coordx;
m_n_debugcoordy[ m_n_debugcoord ] = n_coordy;
m_n_debugcoord++;
}
n_colour = 0x1f;
for( n_coord = 0; n_coord < m_n_debugcoord; n_coord++ )
{
if( n_coordx != m_n_debugcoordx[ n_coord ] ||
n_coordy != m_n_debugcoordy[ n_coord ] )
{
break;
}
}
if( n_coord == m_n_debugcoord && m_n_debugcoord > 1 )
{
n_colour = 0xffff;
}
for( n_coord = 0; n_coord < m_n_debugcoord; n_coord++ )
{
PAIR n_x;
PAIR n_y;
INT32 n_xstart;
INT32 n_ystart;
INT32 n_xend;
INT32 n_yend;
INT32 n_xlen;
INT32 n_ylen;
INT32 n_len;
INT32 n_dx;
INT32 n_dy;
n_xstart = m_n_debugcoordx[ n_coord ];
n_xend = n_coordx;
if( n_xend > n_xstart )
{
n_xlen = n_xend - n_xstart;
}
else
{
n_xlen = n_xstart - n_xend;
}
n_ystart = m_n_debugcoordy[ n_coord ];
n_yend = n_coordy;
if( n_yend > n_ystart )
{
n_ylen = n_yend - n_ystart;
}
else
{
n_ylen = n_ystart - n_yend;
}
if( n_xlen > n_ylen )
{
n_len = n_xlen;
}
else
{
n_len = n_ylen;
}
n_x.w.h = n_xstart; n_x.w.l = 0;
n_y.w.h = n_ystart; n_y.w.l = 0;
if( n_len == 0 )
{
n_len = 1;
}
n_dx = (INT32)( ( n_xend << 16 ) - n_x.d ) / n_len;
n_dy = (INT32)( ( n_yend << 16 ) - n_y.d ) / n_len;
while( n_len > 0 )
{
if( (INT16)n_x.w.h >= 0 &&
(INT16)n_y.w.h >= 0 &&
(INT16)n_x.w.h <= Machine->screen[0].width - 1 &&
(INT16)n_y.w.h <= Machine->screen[0].height - 1 )
{
if( *BITMAP_ADDR16(debugmesh, n_y.w.h, n_x.w.h) != 0xffff )
{
*BITMAP_ADDR16(debugmesh, n_y.w.h, n_x.w.h) = n_colour;
}
}
n_x.d += n_dx;
n_y.d += n_dy;
n_len--;
}
}
}
static void DebugMeshEnd( void )
{
m_n_debugcoord = 0;
}
static void DebugCheckKeys( void )
{
if( input_code_pressed_once( KEYCODE_M ) )
{
m_b_debugmesh = !m_b_debugmesh;
}
if( input_code_pressed_once( KEYCODE_V ) )
{
m_b_debugtexture = !m_b_debugtexture;
}
if( m_b_debugmesh || m_b_debugtexture )
{
video_screen_set_visarea(0, 0, Machine->screen[0].width - 1, 0, Machine->screen[0].height - 1 );
}
else
{
video_screen_set_visarea(0, 0, m_n_screenwidth - 1, 0, m_n_screenheight - 1 );
}
if( input_code_pressed_once( KEYCODE_I ) )
{
if( m_b_debugtexture )
{
m_n_debuginterleave++;
if( m_n_debuginterleave == 2 )
{
m_n_debuginterleave = -1;
}
if( m_n_debuginterleave == -1 )
{
popmessage( "interleave off" );
}
else if( m_n_debuginterleave == 0 )
{
popmessage( "4 bit interleave" );
}
else if( m_n_debuginterleave == 1 )
{
popmessage( "8 bit interleave" );
}
}
else
{
m_n_debugskip++;
if( m_n_debugskip > 15 )
{
m_n_debugskip = 0;
}
popmessage( "debug skip %d", m_n_debugskip );
}
}
#if 0
if( input_code_pressed_once( KEYCODE_D ) )
{
FILE *f;
int n_x;
f = fopen( "dump.txt", "w" );
for( n_y = 256; n_y < 512; n_y++ )
{
for( n_x = 640; n_x < 1024; n_x++ )
{
fprintf( f, "%04u,%04u = %04x\n", n_y, n_x, m_p_p_vram[ n_y ][ n_x ] );
}
}
fclose( f );
}
if( input_code_pressed_once( KEYCODE_S ) )
{
FILE *f;
popmessage( "saving..." );
f = fopen( "VRAM.BIN", "wb" );
for( n_y = 0; n_y < 1024; n_y++ )
{
fwrite( m_p_p_vram[ n_y ], 1024 * 2, 1, f );
}
fclose( f );
}
if( input_code_pressed_once( KEYCODE_L ) )
{
FILE *f;
popmessage( "loading..." );
f = fopen( "VRAM.BIN", "rb" );
for( n_y = 0; n_y < 1024; n_y++ )
{
fread( m_p_p_vram[ n_y ], 1024 * 2, 1, f );
}
fclose( f );
}
#endif
}
static int DebugMeshDisplay( mame_bitmap *bitmap, const rectangle *cliprect )
{
if( m_b_debugmesh )
{
copybitmap( bitmap, debugmesh, 0, 0, 0, 0, cliprect, TRANSPARENCY_NONE, 0 );
}
m_b_debugclear = 1;
return m_b_debugmesh;
}
static int DebugTextureDisplay( mame_bitmap *bitmap )
{
UINT32 n_y;
if( m_b_debugtexture )
{
for( n_y = 0; n_y < Machine->screen[0].height; n_y++ )
{
int n_x;
int n_xi;
int n_yi;
UINT16 p_n_interleave[ 1024 ];
for( n_x = 0; n_x < Machine->screen[0].width; n_x++ )
{
if( m_n_debuginterleave == 0 )
{
n_xi = ( n_x & ~0x3c ) + ( ( n_y << 2 ) & 0x3c );
n_yi = ( n_y & ~0xf ) + ( ( n_x >> 2 ) & 0xf );
}
else if( m_n_debuginterleave == 1 )
{
n_xi = ( n_x & ~0x78 ) + ( ( n_x << 3 ) & 0x40 ) + ( ( n_y << 3 ) & 0x38 ); \
n_yi = ( n_y & ~0x7 ) + ( ( n_x >> 4 ) & 0x7 ); \
}
else
{
n_xi = n_x;
n_yi = n_y;
}
p_n_interleave[ n_x ] = m_p_p_vram[ n_yi ][ n_xi ];
}
draw_scanline16( bitmap, 0, n_y, Machine->screen[0].width, p_n_interleave, Machine->pens, -1 );
}
}
return m_b_debugtexture;
}
#endif
static void updatevisiblearea( void )
{
rectangle visarea;
float refresh;
if( ( m_n_gpustatus & ( 1 << 0x14 ) ) != 0 )
{
/* pal */
refresh = 50;
switch( ( m_n_gpustatus >> 0x13 ) & 1 )
{
case 0:
m_n_screenheight = 256;
break;
case 1:
m_n_screenheight = 512;
break;
}
}
else
{
/* ntsc */
refresh = 60;
switch( ( m_n_gpustatus >> 0x13 ) & 1 )
{
case 0:
m_n_screenheight = 240;
break;
case 1:
m_n_screenheight = 480;
break;
}
}
switch( ( m_n_gpustatus >> 0x11 ) & 3 )
{
case 0:
switch( ( m_n_gpustatus >> 0x10 ) & 1 )
{
case 0:
m_n_screenwidth = 256;
break;
case 1:
m_n_screenwidth = 368;
break;
}
break;
case 1:
switch( ( m_n_gpustatus >> 0x10 ) & 1 )
{
case 0:
m_n_screenwidth = 320;
break;
case 1:
m_n_screenwidth = 384;
break;
}
break;
case 2:
m_n_screenwidth = 512;
break;
case 3:
m_n_screenwidth = 640;
break;
}
visarea.min_x = visarea.min_y = 0;
visarea.max_x = m_n_screenwidth - 1;
visarea.max_y = m_n_screenheight - 1;
video_screen_configure(0, m_n_screenwidth, m_n_screenheight, &visarea, HZ_TO_ATTOSECONDS(refresh));
}
static void psx_gpu_init( void )
{
int n_line;
int n_level;
int n_level2;
int n_shade;
int n_shaded;
#if defined( MAME_DEBUG )
DebugMeshInit();
#endif
m_n_gpustatus = 0x14802000;
m_n_gpuinfo = 0;
m_n_gpu_buffer_offset = 0;
m_n_lightgun_x = 0;
m_n_lightgun_y = 0;
m_n_vram_size = Machine->screen[0].width * Machine->screen[0].height;
m_p_vram = auto_malloc( m_n_vram_size * 2 );
memset( m_p_vram, 0x00, m_n_vram_size * 2 );
for( n_line = 0; n_line < 1024; n_line++ )
{
m_p_p_vram[ n_line ] = &m_p_vram[ ( n_line % Machine->screen[0].height ) * Machine->screen[0].width ];
}
for( n_level = 0; n_level < MAX_LEVEL; n_level++ )
{
for( n_shade = 0; n_shade < MAX_SHADE; n_shade++ )
{
/* shaded */
n_shaded = ( n_level * n_shade ) / MID_SHADE;
if( n_shaded > MAX_LEVEL - 1 )
{
n_shaded = MAX_LEVEL - 1;
}
m_p_n_redshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
m_p_n_greenshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded << 5;
m_p_n_blueshade[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded << 10;
/* 1/4 x transparency */
n_shaded = ( n_level * n_shade ) / MID_SHADE;
n_shaded >>= 2;
if( n_shaded > MAX_LEVEL - 1 )
{
n_shaded = MAX_LEVEL - 1;
}
m_p_n_f025[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
/* 1/2 x transparency */
n_shaded = ( n_level * n_shade ) / MID_SHADE;
n_shaded >>= 1;
if( n_shaded > MAX_LEVEL - 1 )
{
n_shaded = MAX_LEVEL - 1;
}
m_p_n_f05[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
/* 1 x transparency */
n_shaded = ( n_level * n_shade ) / MID_SHADE;
if( n_shaded > MAX_LEVEL - 1 )
{
n_shaded = MAX_LEVEL - 1;
}
m_p_n_f1[ ( n_level * MAX_SHADE ) | n_shade ] = n_shaded;
}
}
for( n_level = 0; n_level < 0x10000; n_level++ )
{
m_p_n_redlevel[ n_level ] = ( n_level & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
m_p_n_greenlevel[ n_level ] = ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
m_p_n_bluelevel[ n_level ] = ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) * MAX_SHADE;
/* 0.5 * background */
m_p_n_redb05[ n_level ] = ( ( n_level & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
m_p_n_greenb05[ n_level ] = ( ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
m_p_n_blueb05[ n_level ] = ( ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) / 2 ) * MAX_LEVEL;
/* 1 * background */
m_p_n_redb1[ n_level ] = ( n_level & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
m_p_n_greenb1[ n_level ] = ( ( n_level >> 5 ) & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
m_p_n_blueb1[ n_level ] = ( ( n_level >> 10 ) & ( MAX_LEVEL - 1 ) ) * MAX_LEVEL;
/* 24bit to 15 bit conversion */
m_p_n_g0r0[ n_level ] = ( ( ( n_level >> 11 ) & ( MAX_LEVEL - 1 ) ) << 5 ) | ( ( ( n_level >> 3 ) & ( MAX_LEVEL - 1 ) ) << 0 );
m_p_n_b0[ n_level ] = ( ( n_level >> 3 ) & ( MAX_LEVEL - 1 ) ) << 10;
m_p_n_r1[ n_level ] = ( ( n_level >> 11 ) & ( MAX_LEVEL - 1 ) ) << 0;
m_p_n_b1g1[ n_level ] = ( ( ( n_level >> 11 ) & ( MAX_LEVEL - 1 ) ) << 10 ) | ( ( ( n_level >> 3 ) & ( MAX_LEVEL - 1 ) ) << 5 );
}
for( n_level = 0; n_level < MAX_LEVEL; n_level++ )
{
for( n_level2 = 0; n_level2 < MAX_LEVEL; n_level2++ )
{
/* add transparency */
n_shaded = ( n_level + n_level2 );
if( n_shaded > MAX_LEVEL - 1 )
{
n_shaded = MAX_LEVEL - 1;
}
m_p_n_redaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded;
m_p_n_greenaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 5;
m_p_n_blueaddtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 10;
/* sub transparency */
n_shaded = ( n_level - n_level2 );
if( n_shaded < 0 )
{
n_shaded = 0;
}
m_p_n_redsubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded;
m_p_n_greensubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 5;
m_p_n_bluesubtrans[ ( n_level * MAX_LEVEL ) | n_level2 ] = n_shaded << 10;
}
}
// icky!!!
state_save_register_memory( "globals", 0, "m_packet", (UINT8 *)&m_packet, 1, sizeof( m_packet ) );
state_save_register_global_pointer( m_p_vram, m_n_vram_size );
state_save_register_global( m_n_gpu_buffer_offset );
state_save_register_global( m_n_vramx );
state_save_register_global( m_n_vramy );
state_save_register_global( m_n_twy );
state_save_register_global( m_n_twx );
state_save_register_global( m_n_tww );
state_save_register_global( m_n_drawarea_x1 );
state_save_register_global( m_n_drawarea_y1 );
state_save_register_global( m_n_drawarea_x2 );
state_save_register_global( m_n_drawarea_y2 );
state_save_register_global( m_n_horiz_disstart );
state_save_register_global( m_n_horiz_disend );
state_save_register_global( m_n_vert_disstart );
state_save_register_global( m_n_vert_disend );
state_save_register_global( m_b_reverseflag );
state_save_register_global( m_n_drawoffset_x );
state_save_register_global( m_n_drawoffset_y );
state_save_register_global( m_n_displaystartx );
state_save_register_global( m_n_displaystarty );
state_save_register_global( m_n_gpustatus );
state_save_register_global( m_n_gpuinfo );
state_save_register_global( m_n_lightgun_x );
state_save_register_global( m_n_lightgun_y );
state_save_register_global( psxgpu.n_tx );
state_save_register_global( psxgpu.n_ty );
state_save_register_global( psxgpu.n_abr );
state_save_register_global( psxgpu.n_tp );
state_save_register_global( psxgpu.n_ix );
state_save_register_global( psxgpu.n_iy );
state_save_register_global( psxgpu.n_ti );
state_save_register_func_postload( updatevisiblearea );
}
VIDEO_START( psx_type1 )
{
m_n_gputype = 1;
psx_gpu_init();
}
VIDEO_START( psx_type2 )
{
m_n_gputype = 2;
psx_gpu_init();
}
VIDEO_UPDATE( psx )
{
UINT32 n_x;
UINT32 n_y;
int n_top;
int n_line;
int n_lines;
int n_left;
int n_column;
int n_columns;
int n_displaystartx;
int n_overscantop;
int n_overscanleft;
#if defined( MAME_DEBUG )
if( DebugMeshDisplay( bitmap, cliprect ) )
{
return 0;
}
if( DebugTextureDisplay( bitmap ) )
{
return 0;
}
#endif
if( ( m_n_gpustatus & ( 1 << 0x17 ) ) != 0 )
{
/* todo: only draw to necessary area */
fillbitmap( bitmap, 0, cliprect );
}
else
{
if( m_b_reverseflag )
{
n_displaystartx = ( 1023 - m_n_displaystartx );
/* todo: make this flip the screen, in the meantime.. */
n_displaystartx -= ( m_n_screenwidth - 1 );
}
else
{
n_displaystartx = m_n_displaystartx;
}
if( ( m_n_gpustatus & ( 1 << 0x14 ) ) != 0 )
{
/* pal */
n_overscantop = 0x23;
n_overscanleft = 0x27e;
}
else
{
/* ntsc */
n_overscantop = 0x10;
n_overscanleft = 0x260;
}
n_top = (INT32)m_n_vert_disstart - n_overscantop;
n_lines = (INT32)m_n_vert_disend - (INT32)m_n_vert_disstart;
if( n_top < 0 )
{
n_y = -n_top;
n_lines += n_top;
}
else
{
/* todo: draw top border */
n_y = 0;
}
if( ( m_n_gpustatus & ( 1 << 0x16 ) ) != 0 )
{
/* interlaced */
n_lines *= 2;
}
if( n_lines > m_n_screenheight - ( n_y + n_top ) )
{
n_lines = m_n_screenheight - ( n_y + n_top );
}
else
{
/* todo: draw bottom border */
}
n_left = ( ( (INT32)m_n_horiz_disstart - n_overscanleft ) * (INT32)m_n_screenwidth ) / 2560;
n_columns = ( ( ( (INT32)m_n_horiz_disend - m_n_horiz_disstart ) * (INT32)m_n_screenwidth ) / 2560 );
if( n_left < 0 )
{
n_x = -n_left;
n_columns += n_left;
}
else
{
/* todo: draw left border */
n_x = 0;
}
if( n_columns > m_n_screenwidth - ( n_x + n_left ) )
{
n_columns = m_n_screenwidth - ( n_x + n_left );
}
else
{
/* todo: draw right border */
}
if( ( m_n_gpustatus & ( 1 << 0x15 ) ) != 0 )
{
/* 24bit */
n_line = n_lines;
while( n_line > 0 )
{
UINT16 *p_n_src = m_p_p_vram[ n_y + m_n_displaystarty ] + n_x + n_displaystartx;
UINT16 *p_n_dest = BITMAP_ADDR16(bitmap, n_y + n_top, n_x + n_left);
n_column = n_columns;
while( n_column > 0 )
{
UINT32 n_g0r0 = *( p_n_src++ );
UINT32 n_r1b0 = *( p_n_src++ );
UINT32 n_b1g1 = *( p_n_src++ );
*( p_n_dest++ ) = m_p_n_g0r0[ n_g0r0 ] | m_p_n_b0[ n_r1b0 ];
n_column--;
if( n_column > 0 )
{
*( p_n_dest++ ) = m_p_n_r1[ n_r1b0 ] | m_p_n_b1g1[ n_b1g1 ];
n_column--;
}
}
n_y++;
n_line--;
}
}
else
{
/* 15bit */
n_line = n_lines;
while( n_line > 0 )
{
draw_scanline16( bitmap, n_x + n_left, n_y + n_top, n_columns, m_p_p_vram[ n_y + m_n_displaystarty ] + n_x + n_displaystartx, machine->pens, -1 );
n_y++;
n_line--;
}
}
}
return 0;
}
#define WRITE_PIXEL( p ) *( p_vram ) = p
/*
type 1
f e| d| c b| a 9| 8 7| 6 5| 4| 3 2 1 0
|ti| | tp| abr| ty| | tx
*/
/*
type 2
f e| d c| b| a 9| 8 7| 6 5| 4| 3 2 1 0
|iy|ix|ty| | tp| abr|ty| tx
*/
INLINE void decode_tpage( struct PSXGPU *p_psxgpu, UINT32 tpage )
{
if( m_n_gputype == 2 )
{
m_n_gpustatus = ( m_n_gpustatus & 0xfffff800 ) | ( tpage & 0x7ff );
p_psxgpu->n_tx = ( tpage & 0x0f ) << 6;
p_psxgpu->n_ty = ( ( tpage & 0x10 ) << 4 ) | ( ( tpage & 0x800 ) >> 2 );
p_psxgpu->n_abr = ( tpage & 0x60 ) >> 5;
p_psxgpu->n_tp = ( tpage & 0x180 ) >> 7;
p_psxgpu->n_ix = ( tpage & 0x1000 ) >> 12;
p_psxgpu->n_iy = ( tpage & 0x2000 ) >> 13;
p_psxgpu->n_ti = 0;
if( ( tpage & ~0x39ff ) != 0 )
{
verboselog( 1, "not handled: draw mode %08x\n", tpage & ~0x39ff );
}
if( p_psxgpu->n_tp == 3 )
{
verboselog( 0, "not handled: tp == 3\n" );
}
}
else
{
m_n_gpustatus = ( m_n_gpustatus & 0xffffe000 ) | ( tpage & 0x1fff );
p_psxgpu->n_tx = ( tpage & 0x0f ) << 6;
p_psxgpu->n_ty = ( ( tpage & 0x60 ) << 3 );
p_psxgpu->n_abr = ( tpage & 0x180 ) >> 7;
p_psxgpu->n_tp = ( tpage & 0x600 ) >> 9;
p_psxgpu->n_ti = ( tpage & 0x2000 ) >> 13;
p_psxgpu->n_ix = 0;
p_psxgpu->n_iy = 0;
if( ( tpage & ~0x27ef ) != 0 )
{
verboselog( 1, "not handled: draw mode %08x\n", tpage & ~0x27ef );
}
if( p_psxgpu->n_tp == 3 )
{
verboselog( 0, "not handled: tp == 3\n" );
}
else if( p_psxgpu->n_tp == 2 && p_psxgpu->n_ti != 0 )
{
verboselog( 0, "not handled: interleaved 15 bit texture\n" );
}
}
}
#define SPRITESETUP \
if( psxgpu.n_iy != 0 ) \
{ \
n_dv = -1; \
} \
else \
{ \
n_dv = 1; \
} \
if( psxgpu.n_ix != 0 ) \
{ \
n_du = -1; \
} \
else \
{ \
n_du = 1; \
}
#define TRANSPARENCYSETUP \
p_n_f = m_p_n_f1; \
p_n_redb = m_p_n_redb1; \
p_n_greenb = m_p_n_greenb1; \
p_n_blueb = m_p_n_blueb1; \
p_n_redtrans = m_p_n_redaddtrans; \
p_n_greentrans = m_p_n_greenaddtrans; \
p_n_bluetrans = m_p_n_blueaddtrans; \
\
switch( n_cmd & 0x02 ) \
{ \
case 0x02: \
switch( psxgpu.n_abr ) \
{ \
case 0x00: \
p_n_f = m_p_n_f05; \
p_n_redb = m_p_n_redb05; \
p_n_greenb = m_p_n_greenb05; \
p_n_blueb = m_p_n_blueb05; \
p_n_redtrans = m_p_n_redaddtrans; \
p_n_greentrans = m_p_n_greenaddtrans; \
p_n_bluetrans = m_p_n_blueaddtrans; \
verboselog( 2, "Transparency Mode: 0.5*B + 0.5*F\n" ); \
break; \
case 0x01: \
p_n_f = m_p_n_f1; \
p_n_redb = m_p_n_redb1; \
p_n_greenb = m_p_n_greenb1; \
p_n_blueb = m_p_n_blueb1; \
p_n_redtrans = m_p_n_redaddtrans; \
p_n_greentrans = m_p_n_greenaddtrans; \
p_n_bluetrans = m_p_n_blueaddtrans; \
verboselog( 2, "Transparency Mode: 1.0*B + 1.0*F\n" ); \
break; \
case 0x02: \
p_n_f = m_p_n_f1; \
p_n_redb = m_p_n_redb1; \
p_n_greenb = m_p_n_greenb1; \
p_n_blueb = m_p_n_blueb1; \
p_n_redtrans = m_p_n_redsubtrans; \
p_n_greentrans = m_p_n_greensubtrans; \
p_n_bluetrans = m_p_n_bluesubtrans; \
verboselog( 2, "Transparency Mode: 1.0*B - 1.0*F\n" ); \
break; \
case 0x03: \
p_n_f = m_p_n_f025; \
p_n_redb = m_p_n_redb1; \
p_n_greenb = m_p_n_greenb1; \
p_n_blueb = m_p_n_blueb1; \
p_n_redtrans = m_p_n_redaddtrans; \
p_n_greentrans = m_p_n_greenaddtrans; \
p_n_bluetrans = m_p_n_blueaddtrans; \
verboselog( 2, "Transparency Mode: 1.0*B + 0.25*F\n" ); \
break; \
} \
break; \
}
#define SOLIDSETUP \
TRANSPARENCYSETUP
#define TEXTURESETUP \
n_tx = psxgpu.n_tx; \
n_ty = psxgpu.n_ty; \
p_clut = m_p_p_vram[ n_cluty ] + n_clutx; \
switch( psxgpu.n_tp ) \
{ \
case 0: \
n_tx += m_n_twx >> 2; \
n_ty += m_n_twy; \
break; \
case 1: \
n_tx += m_n_twx >> 1; \
n_ty += m_n_twy; \
break; \
case 2: \
n_tx += m_n_twx >> 0; \
n_ty += m_n_twy; \
break; \
} \
TRANSPARENCYSETUP
#define FLATPOLYGONUPDATE
#define FLATRECTANGEUPDATE
#define GOURAUDPOLYGONUPDATE \
n_r.d += n_dr; \
n_g.d += n_dg; \
n_b.d += n_db;
#define SOLIDFILL( PIXELUPDATE ) \
if( n_distance > ( (INT32)m_n_drawarea_x2 - n_x ) + 1 ) \
{ \
n_distance = ( m_n_drawarea_x2 - n_x ) + 1; \
} \
p_vram = m_p_p_vram[ n_y ] + n_x; \
\
switch( n_cmd & 0x02 ) \
{ \
case 0x00: \
/* transparency off */ \
while( n_distance > 0 ) \
{ \
WRITE_PIXEL( \
m_p_n_redshade[ MID_LEVEL | n_r.w.h ] | \
m_p_n_greenshade[ MID_LEVEL | n_g.w.h ] | \
m_p_n_blueshade[ MID_LEVEL | n_b.w.h ] ); \
p_vram++; \
PIXELUPDATE \
n_distance--; \
} \
break; \
case 0x02: \
/* transparency on */ \
while( n_distance > 0 ) \
{ \
WRITE_PIXEL( \
p_n_redtrans[ p_n_f[ MID_LEVEL | n_r.w.h ] | p_n_redb[ *( p_vram ) ] ] | \
p_n_greentrans[ p_n_f[ MID_LEVEL | n_g.w.h ] | p_n_greenb[ *( p_vram ) ] ] | \
p_n_bluetrans[ p_n_f[ MID_LEVEL | n_b.w.h ] | p_n_blueb[ *( p_vram ) ] ] ); \
p_vram++; \
PIXELUPDATE \
n_distance--; \
} \
break; \
} \
#define FLATTEXTUREDPOLYGONUPDATE \
n_u.d += n_du; \
n_v.d += n_dv;
#define GOURAUDTEXTUREDPOLYGONUPDATE \
n_r.d += n_dr; \
n_g.d += n_dg; \
n_b.d += n_db; \
n_u.d += n_du; \
n_v.d += n_dv;
#define FLATTEXTUREDRECTANGLEUPDATE \
n_u += n_du;
#define TEXTURE4BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
n_bgr = p_clut[ ( *( m_p_p_vram[ n_ty + TXV ] + n_tx + ( TXU >> 2 ) ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f ];
#define TEXTURE8BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
n_bgr = p_clut[ ( *( m_p_p_vram[ n_ty + TXV ] + n_tx + ( TXU >> 1 ) ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff ];
#define TEXTURE15BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
n_bgr = *( m_p_p_vram[ n_ty + TXV ] + n_tx + TXU );
#define TEXTUREWINDOW4BIT( TXV, TXU ) TEXTURE4BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define TEXTUREWINDOW8BIT( TXV, TXU ) TEXTURE8BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define TEXTUREWINDOW15BIT( TXV, TXU ) TEXTURE15BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
int n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); \
int n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); \
n_bgr = p_clut[ ( *( m_p_p_vram[ n_ty + n_yi ] + n_tx + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f ];
#define TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
int n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); \
int n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); \
n_bgr = p_clut[ ( *( m_p_p_vram[ n_ty + n_yi ] + n_tx + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff ];
#define TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
while( n_distance > 0 ) \
{ \
int n_xi = TXU; \
int n_yi = TXV; \
n_bgr = *( m_p_p_vram[ n_ty + n_yi ] + n_tx + n_xi );
#define TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) TEXTUREINTERLEAVED4BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) TEXTUREINTERLEAVED8BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) TEXTUREINTERLEAVED15BIT( ( TXV & m_n_twh ), ( TXU & m_n_tww ) )
#define SHADEDPIXEL( PIXELUPDATE ) \
if( n_bgr != 0 ) \
{ \
WRITE_PIXEL( \
m_p_n_redshade[ m_p_n_redlevel[ n_bgr ] | n_r.w.h ] | \
m_p_n_greenshade[ m_p_n_greenlevel[ n_bgr ] | n_g.w.h ] | \
m_p_n_blueshade[ m_p_n_bluelevel[ n_bgr ] | n_b.w.h ] ); \
} \
p_vram++; \
PIXELUPDATE \
n_distance--; \
}
#define TRANSPARENTPIXEL( PIXELUPDATE ) \
if( n_bgr != 0 ) \
{ \
if( ( n_bgr & 0x8000 ) != 0 ) \
{ \
WRITE_PIXEL( \
p_n_redtrans[ p_n_f[ m_p_n_redlevel[ n_bgr ] | n_r.w.h ] | p_n_redb[ *( p_vram ) ] ] | \
p_n_greentrans[ p_n_f[ m_p_n_greenlevel[ n_bgr ] | n_g.w.h ] | p_n_greenb[ *( p_vram ) ] ] | \
p_n_bluetrans[ p_n_f[ m_p_n_bluelevel[ n_bgr ] | n_b.w.h ] | p_n_blueb[ *( p_vram ) ] ] ); \
} \
else \
{ \
WRITE_PIXEL( \
m_p_n_redshade[ m_p_n_redlevel[ n_bgr ] | n_r.w.h ] | \
m_p_n_greenshade[ m_p_n_greenlevel[ n_bgr ] | n_g.w.h ] | \
m_p_n_blueshade[ m_p_n_bluelevel[ n_bgr ] | n_b.w.h ] ); \
} \
} \
p_vram++; \
PIXELUPDATE \
n_distance--; \
}
#define TEXTUREFILL( PIXELUPDATE, TXU, TXV ) \
if( n_distance > ( (INT32)m_n_drawarea_x2 - n_x ) + 1 ) \
{ \
n_distance = ( m_n_drawarea_x2 - n_x ) + 1; \
} \
p_vram = m_p_p_vram[ n_y ] + n_x; \
\
if( psxgpu.n_ti != 0 ) \
{ \
/* interleaved texture */ \
if( m_n_twh != 255 || \
m_n_tww != 255 || \
m_n_twx != 0 || \
m_n_twy != 0 ) \
{ \
/* texture window */ \
switch( n_cmd & 0x02 ) \
{ \
case 0x00: \
/* shading */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
case 0x02: \
/* semi transparency */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREWINDOWINTERLEAVED4BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREWINDOWINTERLEAVED8BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREWINDOWINTERLEAVED15BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
} \
} \
else \
{ \
/* no texture window */ \
switch( n_cmd & 0x02 ) \
{ \
case 0x00: \
/* shading */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
case 0x02: \
/* semi transparency */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREINTERLEAVED4BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREINTERLEAVED8BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREINTERLEAVED15BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
} \
} \
} \
else \
{ \
/* standard texture */ \
if( m_n_twh != 255 || \
m_n_tww != 255 || \
m_n_twx != 0 || \
m_n_twy != 0 ) \
{ \
/* texture window */ \
switch( n_cmd & 0x02 ) \
{ \
case 0x00: \
/* shading */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREWINDOW4BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREWINDOW8BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREWINDOW15BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
case 0x02: \
/* semi transparency */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTUREWINDOW4BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTUREWINDOW8BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTUREWINDOW15BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
} \
} \
else \
{ \
/* no texture window */ \
switch( n_cmd & 0x02 ) \
{ \
case 0x00: \
/* shading */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
TEXTURE4BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTURE8BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTURE15BIT( TXV, TXU ) \
SHADEDPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
case 0x02: \
/* semi transparency */ \
switch( psxgpu.n_tp ) \
{ \
case 0: \
/* 4 bit clut */ \
TEXTURE4BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 1: \
/* 8 bit clut */ \
TEXTURE8BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
case 2: \
/* 15 bit */ \
TEXTURE15BIT( TXV, TXU ) \
TRANSPARENTPIXEL( PIXELUPDATE ) \
break; \
} \
break; \
} \
} \
}
static void FlatPolygon( int n_points )
{
INT16 n_y;
INT16 n_x;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
PAIR n_cx1;
PAIR n_cx2;
INT32 n_dx1;
INT32 n_dx2;
UINT8 n_cmd;
INT32 n_distance;
UINT16 n_point;
UINT16 n_rightpoint;
UINT16 n_leftpoint;
UINT16 *p_n_rightpointlist;
UINT16 *p_n_leftpointlist;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 1 )
{
return;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
DebugMesh( COORD_X( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_y );
}
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatPolygon.n_bgr );
n_cx1.d = 0;
n_cx2.d = 0;
SOLIDSETUP
n_r.w.h = BGR_R( m_packet.FlatPolygon.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatPolygon.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatPolygon.n_bgr ); n_b.w.l = 0;
if( n_points == 4 )
{
p_n_rightpointlist = m_p_n_nextpointlist4;
p_n_leftpointlist = m_p_n_prevpointlist4;
}
else
{
p_n_rightpointlist = m_p_n_nextpointlist3;
p_n_leftpointlist = m_p_n_prevpointlist3;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
ADJUST_COORD( m_packet.FlatPolygon.vertex[ n_point ].n_coord );
}
n_leftpoint = 0;
for( n_point = 1; n_point < n_points; n_point++ )
{
if( COORD_Y( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) < COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) ||
( COORD_Y( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) == COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) &&
COORD_X( m_packet.FlatPolygon.vertex[ n_point ].n_coord ) < COORD_X( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) ) )
{
n_leftpoint = n_point;
}
}
n_rightpoint = n_leftpoint;
n_dx1 = 0;
n_dx2 = 0;
n_y = COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord );
for( ;; )
{
if( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
{
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
if( n_leftpoint == n_rightpoint )
{
break;
}
}
n_cx1.w.h = COORD_X( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.w.l = 0;
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
n_distance = COORD_Y( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx1 = (INT32)( ( COORD_X( m_packet.FlatPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
}
if( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.FlatPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
{
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
if( n_rightpoint == n_leftpoint )
{
break;
}
}
n_cx2.w.h = COORD_X( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.w.l = 0;
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
n_distance = COORD_Y( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx2 = (INT32)( ( COORD_X( m_packet.FlatPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
}
if( (INT16)n_cx1.w.h != (INT16)n_cx2.w.h && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( (INT16)n_cx1.w.h < (INT16)n_cx2.w.h )
{
n_x = n_cx1.w.h;
n_distance = (INT16)n_cx2.w.h - n_x;
}
else
{
n_x = n_cx2.w.h;
n_distance = (INT16)n_cx1.w.h - n_x;
}
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
SOLIDFILL( FLATPOLYGONUPDATE )
}
n_cx1.d += n_dx1;
n_cx2.d += n_dx2;
n_y++;
}
}
static void FlatTexturedPolygon( int n_points )
{
INT16 n_y;
INT16 n_x;
int n_tx;
int n_ty;
UINT8 n_cmd;
UINT32 n_clutx;
UINT32 n_cluty;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
PAIR n_u;
PAIR n_v;
PAIR n_cx1;
PAIR n_cx2;
PAIR n_cu1;
PAIR n_cv1;
PAIR n_cu2;
PAIR n_cv2;
INT32 n_du;
INT32 n_dv;
INT32 n_dx1;
INT32 n_dx2;
INT32 n_du1;
INT32 n_dv1;
INT32 n_du2;
INT32 n_dv2;
INT32 n_distance;
UINT16 n_point;
UINT16 n_rightpoint;
UINT16 n_leftpoint;
UINT16 *p_n_rightpointlist;
UINT16 *p_n_leftpointlist;
UINT16 *p_clut;
UINT16 *p_vram;
UINT32 n_bgr;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 2 )
{
return;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
DebugMesh( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_y );
}
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatTexturedPolygon.n_bgr );
n_clutx = ( m_packet.FlatTexturedPolygon.vertex[ 0 ].n_texture.w.h & 0x3f ) << 4;
n_cluty = ( m_packet.FlatTexturedPolygon.vertex[ 0 ].n_texture.w.h >> 6 ) & 0x3ff;
n_r.d = 0;
n_g.d = 0;
n_b.d = 0;
n_cx1.d = 0;
n_cu1.d = 0;
n_cv1.d = 0;
n_cx2.d = 0;
n_cu2.d = 0;
n_cv2.d = 0;
decode_tpage( &psxgpu, m_packet.FlatTexturedPolygon.vertex[ 1 ].n_texture.w.h );
TEXTURESETUP
switch( n_cmd & 0x01 )
{
case 0:
n_r.w.h = BGR_R( m_packet.FlatTexturedPolygon.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatTexturedPolygon.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatTexturedPolygon.n_bgr ); n_b.w.l = 0;
break;
case 1:
n_r.w.h = 0x80; n_r.w.l = 0;
n_g.w.h = 0x80; n_g.w.l = 0;
n_b.w.h = 0x80; n_b.w.l = 0;
break;
}
if( n_points == 4 )
{
p_n_rightpointlist = m_p_n_nextpointlist4;
p_n_leftpointlist = m_p_n_prevpointlist4;
}
else
{
p_n_rightpointlist = m_p_n_nextpointlist3;
p_n_leftpointlist = m_p_n_prevpointlist3;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
ADJUST_COORD( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord );
}
n_leftpoint = 0;
for( n_point = 1; n_point < n_points; n_point++ )
{
if( COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) < COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) ||
( COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) &&
COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_point ].n_coord ) < COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) ) )
{
n_leftpoint = n_point;
}
}
n_rightpoint = n_leftpoint;
n_dx1 = 0;
n_dx2 = 0;
n_du1 = 0;
n_du2 = 0;
n_dv1 = 0;
n_dv2 = 0;
n_y = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord );
for( ;; )
{
if( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
{
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
if( n_leftpoint == n_rightpoint )
{
break;
}
}
n_cx1.w.h = COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.w.l = 0;
n_cu1.w.h = TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cu1.w.l = 0;
n_cv1.w.h = TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cv1.w.l = 0;
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
n_distance = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx1 = (INT32)( ( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
n_du1 = (INT32)( ( TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cu1.d ) / n_distance;
n_dv1 = (INT32)( ( TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cv1.d ) / n_distance;
}
if( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.FlatTexturedPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
{
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
if( n_rightpoint == n_leftpoint )
{
break;
}
}
n_cx2.w.h = COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.w.l = 0;
n_cu2.w.h = TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cu2.w.l = 0;
n_cv2.w.h = TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cv2.w.l = 0;
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
n_distance = COORD_Y( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx2 = (INT32)( ( COORD_X( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
n_du2 = (INT32)( ( TEXTURE_U( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cu2.d ) / n_distance;
n_dv2 = (INT32)( ( TEXTURE_V( m_packet.FlatTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cv2.d ) / n_distance;
}
if( (INT16)n_cx1.w.h != (INT16)n_cx2.w.h && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( (INT16)n_cx1.w.h < (INT16)n_cx2.w.h )
{
n_x = n_cx1.w.h;
n_distance = (INT16)n_cx2.w.h - n_x;
n_u.d = n_cu1.d;
n_v.d = n_cv1.d;
n_du = (INT32)( n_cu2.d - n_cu1.d ) / n_distance;
n_dv = (INT32)( n_cv2.d - n_cv1.d ) / n_distance;
}
else
{
n_x = n_cx2.w.h;
n_distance = (INT16)n_cx1.w.h - n_x;
n_u.d = n_cu2.d;
n_v.d = n_cv2.d;
n_du = (INT32)( n_cu1.d - n_cu2.d ) / n_distance;
n_dv = (INT32)( n_cv1.d - n_cv2.d ) / n_distance;
}
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_u.d += n_du * ( m_n_drawarea_x1 - n_x );
n_v.d += n_dv * ( m_n_drawarea_x1 - n_x );
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
TEXTUREFILL( FLATTEXTUREDPOLYGONUPDATE, n_u.w.h, n_v.w.h );
}
n_cx1.d += n_dx1;
n_cu1.d += n_du1;
n_cv1.d += n_dv1;
n_cx2.d += n_dx2;
n_cu2.d += n_du2;
n_cv2.d += n_dv2;
n_y++;
}
}
static void GouraudPolygon( int n_points )
{
INT16 n_y;
INT16 n_x;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
UINT8 n_cmd;
PAIR n_r;
PAIR n_g;
PAIR n_b;
PAIR n_cx1;
PAIR n_cx2;
PAIR n_cr1;
PAIR n_cg1;
PAIR n_cb1;
PAIR n_cr2;
PAIR n_cg2;
PAIR n_cb2;
INT32 n_dr;
INT32 n_dg;
INT32 n_db;
INT32 n_dx1;
INT32 n_dx2;
INT32 n_dr1;
INT32 n_dg1;
INT32 n_db1;
INT32 n_dr2;
INT32 n_dg2;
INT32 n_db2;
INT32 n_distance;
UINT16 n_point;
UINT16 n_rightpoint;
UINT16 n_leftpoint;
UINT16 *p_n_rightpointlist;
UINT16 *p_n_leftpointlist;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 3 )
{
return;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
DebugMesh( COORD_X( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_y );
}
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.GouraudPolygon.vertex[ 0 ].n_bgr );
n_cx1.d = 0;
n_cr1.d = 0;
n_cg1.d = 0;
n_cb1.d = 0;
n_cx2.d = 0;
n_cr2.d = 0;
n_cg2.d = 0;
n_cb2.d = 0;
SOLIDSETUP
if( n_points == 4 )
{
p_n_rightpointlist = m_p_n_nextpointlist4;
p_n_leftpointlist = m_p_n_prevpointlist4;
}
else
{
p_n_rightpointlist = m_p_n_nextpointlist3;
p_n_leftpointlist = m_p_n_prevpointlist3;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
ADJUST_COORD( m_packet.GouraudPolygon.vertex[ n_point ].n_coord );
}
n_leftpoint = 0;
for( n_point = 1; n_point < n_points; n_point++ )
{
if( COORD_Y( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) < COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) ||
( COORD_Y( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) == COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) &&
COORD_X( m_packet.GouraudPolygon.vertex[ n_point ].n_coord ) < COORD_X( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) ) )
{
n_leftpoint = n_point;
}
}
n_rightpoint = n_leftpoint;
n_dx1 = 0;
n_dx2 = 0;
n_dr1 = 0;
n_dr2 = 0;
n_dg1 = 0;
n_dg2 = 0;
n_db1 = 0;
n_db2 = 0;
n_y = COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord );
for( ;; )
{
if( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
{
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
if( n_leftpoint == n_rightpoint )
{
break;
}
}
n_cx1.w.h = COORD_X( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.w.l = 0;
n_cr1.w.h = BGR_R( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cr1.w.l = 0;
n_cg1.w.h = BGR_G( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cg1.w.l = 0;
n_cb1.w.h = BGR_B( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ); n_cb1.w.l = 0;
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
n_distance = COORD_Y( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx1 = (INT32)( ( COORD_X( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
n_dr1 = (INT32)( ( BGR_R( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cr1.d ) / n_distance;
n_dg1 = (INT32)( ( BGR_G( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cg1.d ) / n_distance;
n_db1 = (INT32)( ( BGR_B( m_packet.GouraudPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cb1.d ) / n_distance;
}
if( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.GouraudPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
{
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
if( n_rightpoint == n_leftpoint )
{
break;
}
}
n_cx2.w.h = COORD_X( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.w.l = 0;
n_cr2.w.h = BGR_R( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cr2.w.l = 0;
n_cg2.w.h = BGR_G( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cg2.w.l = 0;
n_cb2.w.h = BGR_B( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ); n_cb2.w.l = 0;
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
n_distance = COORD_Y( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx2 = (INT32)( ( COORD_X( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
n_dr2 = (INT32)( ( BGR_R( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cr2.d ) / n_distance;
n_dg2 = (INT32)( ( BGR_G( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cg2.d ) / n_distance;
n_db2 = (INT32)( ( BGR_B( m_packet.GouraudPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cb2.d ) / n_distance;
}
if( (INT16)n_cx1.w.h != (INT16)n_cx2.w.h && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( (INT16)n_cx1.w.h < (INT16)n_cx2.w.h )
{
n_x = n_cx1.w.h;
n_distance = (INT16)n_cx2.w.h - n_x;
n_r.d = n_cr1.d;
n_g.d = n_cg1.d;
n_b.d = n_cb1.d;
n_dr = (INT32)( n_cr2.d - n_cr1.d ) / n_distance;
n_dg = (INT32)( n_cg2.d - n_cg1.d ) / n_distance;
n_db = (INT32)( n_cb2.d - n_cb1.d ) / n_distance;
}
else
{
n_x = n_cx2.w.h;
n_distance = (INT16)n_cx1.w.h - n_x;
n_r.d = n_cr2.d;
n_g.d = n_cg2.d;
n_b.d = n_cb2.d;
n_dr = (INT32)( n_cr1.d - n_cr2.d ) / n_distance;
n_dg = (INT32)( n_cg1.d - n_cg2.d ) / n_distance;
n_db = (INT32)( n_cb1.d - n_cb2.d ) / n_distance;
}
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_r.d += n_dr * ( m_n_drawarea_x1 - n_x );
n_g.d += n_dg * ( m_n_drawarea_x1 - n_x );
n_b.d += n_db * ( m_n_drawarea_x1 - n_x );
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
SOLIDFILL( GOURAUDPOLYGONUPDATE )
}
n_cx1.d += n_dx1;
n_cr1.d += n_dr1;
n_cg1.d += n_dg1;
n_cb1.d += n_db1;
n_cx2.d += n_dx2;
n_cr2.d += n_dr2;
n_cg2.d += n_dg2;
n_cb2.d += n_db2;
n_y++;
}
}
static void GouraudTexturedPolygon( int n_points )
{
INT16 n_y;
INT16 n_x;
int n_tx;
int n_ty;
UINT8 n_cmd;
UINT32 n_clutx;
UINT32 n_cluty;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
PAIR n_u;
PAIR n_v;
PAIR n_cx1;
PAIR n_cx2;
PAIR n_cu1;
PAIR n_cv1;
PAIR n_cu2;
PAIR n_cv2;
PAIR n_cr1;
PAIR n_cg1;
PAIR n_cb1;
PAIR n_cr2;
PAIR n_cg2;
PAIR n_cb2;
INT32 n_dr;
INT32 n_dg;
INT32 n_db;
INT32 n_du;
INT32 n_dv;
INT32 n_dx1;
INT32 n_dx2;
INT32 n_dr1;
INT32 n_dg1;
INT32 n_db1;
INT32 n_dr2;
INT32 n_dg2;
INT32 n_db2;
INT32 n_du1;
INT32 n_dv1;
INT32 n_du2;
INT32 n_dv2;
INT32 n_distance;
UINT16 n_point;
UINT16 n_rightpoint;
UINT16 n_leftpoint;
UINT16 *p_n_rightpointlist;
UINT16 *p_n_leftpointlist;
UINT16 *p_clut;
UINT16 *p_vram;
UINT32 n_bgr;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 4 )
{
return;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
DebugMesh( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) + m_n_drawoffset_y );
}
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_bgr );
n_clutx = ( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_texture.w.h & 0x3f ) << 4;
n_cluty = ( m_packet.GouraudTexturedPolygon.vertex[ 0 ].n_texture.w.h >> 6 ) & 0x3ff;
n_cx1.d = 0;
n_cr1.d = 0;
n_cg1.d = 0;
n_cb1.d = 0;
n_cu1.d = 0;
n_cv1.d = 0;
n_cx2.d = 0;
n_cr2.d = 0;
n_cg2.d = 0;
n_cb2.d = 0;
n_cu2.d = 0;
n_cv2.d = 0;
decode_tpage( &psxgpu, m_packet.GouraudTexturedPolygon.vertex[ 1 ].n_texture.w.h );
TEXTURESETUP
if( n_points == 4 )
{
p_n_rightpointlist = m_p_n_nextpointlist4;
p_n_leftpointlist = m_p_n_prevpointlist4;
}
else
{
p_n_rightpointlist = m_p_n_nextpointlist3;
p_n_leftpointlist = m_p_n_prevpointlist3;
}
for( n_point = 0; n_point < n_points; n_point++ )
{
ADJUST_COORD( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord );
}
n_leftpoint = 0;
for( n_point = 1; n_point < n_points; n_point++ )
{
if( COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) < COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) ||
( COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) &&
COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_point ].n_coord ) < COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) ) )
{
n_leftpoint = n_point;
}
}
n_rightpoint = n_leftpoint;
n_dx1 = 0;
n_dx2 = 0;
n_du1 = 0;
n_du2 = 0;
n_dr1 = 0;
n_dr2 = 0;
n_dg1 = 0;
n_dg2 = 0;
n_db1 = 0;
n_db2 = 0;
n_dv1 = 0;
n_dv2 = 0;
n_y = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord );
for( ;; )
{
if( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ p_n_leftpointlist[ n_leftpoint ] ].n_coord ) )
{
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
if( n_leftpoint == n_rightpoint )
{
break;
}
}
n_cx1.w.h = COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ); n_cx1.w.l = 0;
switch( n_cmd & 0x01 )
{
case 0x00:
n_cr1.w.h = BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cr1.w.l = 0;
n_cg1.w.h = BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cg1.w.l = 0;
n_cb1.w.h = BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ); n_cb1.w.l = 0;
break;
case 0x01:
n_cr1.w.h = 0x80; n_cr1.w.l = 0;
n_cg1.w.h = 0x80; n_cg1.w.l = 0;
n_cb1.w.h = 0x80; n_cb1.w.l = 0;
break;
}
n_cu1.w.h = TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cu1.w.l = 0;
n_cv1.w.h = TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ); n_cv1.w.l = 0;
n_leftpoint = p_n_leftpointlist[ n_leftpoint ];
n_distance = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx1 = (INT32)( ( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_coord ) << 16 ) - n_cx1.d ) / n_distance;
switch( n_cmd & 0x01 )
{
case 0x00:
n_dr1 = (INT32)( ( BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cr1.d ) / n_distance;
n_dg1 = (INT32)( ( BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cg1.d ) / n_distance;
n_db1 = (INT32)( ( BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_bgr ) << 16 ) - n_cb1.d ) / n_distance;
break;
case 0x01:
n_dr1 = 0;
n_dg1 = 0;
n_db1 = 0;
break;
}
n_du1 = (INT32)( ( TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cu1.d ) / n_distance;
n_dv1 = (INT32)( ( TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_leftpoint ].n_texture ) << 16 ) - n_cv1.d ) / n_distance;
}
if( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) )
{
while( n_y == COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ p_n_rightpointlist[ n_rightpoint ] ].n_coord ) )
{
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
if( n_rightpoint == n_leftpoint )
{
break;
}
}
n_cx2.w.h = COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ); n_cx2.w.l = 0;
switch( n_cmd & 0x01 )
{
case 0x00:
n_cr2.w.h = BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cr2.w.l = 0;
n_cg2.w.h = BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cg2.w.l = 0;
n_cb2.w.h = BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ); n_cb2.w.l = 0;
break;
case 0x01:
n_cr2.w.h = 0x80; n_cr2.w.l = 0;
n_cg2.w.h = 0x80; n_cg2.w.l = 0;
n_cb2.w.h = 0x80; n_cb2.w.l = 0;
break;
}
n_cu2.w.h = TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cu2.w.l = 0;
n_cv2.w.h = TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ); n_cv2.w.l = 0;
n_rightpoint = p_n_rightpointlist[ n_rightpoint ];
n_distance = COORD_Y( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) - n_y;
if( n_distance < 1 )
{
break;
}
n_dx2 = (INT32)( ( COORD_X( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_coord ) << 16 ) - n_cx2.d ) / n_distance;
switch( n_cmd & 0x01 )
{
case 0x00:
n_dr2 = (INT32)( ( BGR_R( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cr2.d ) / n_distance;
n_dg2 = (INT32)( ( BGR_G( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cg2.d ) / n_distance;
n_db2 = (INT32)( ( BGR_B( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_bgr ) << 16 ) - n_cb2.d ) / n_distance;
break;
case 0x01:
n_dr2 = 0;
n_dg2 = 0;
n_db2 = 0;
break;
}
n_du2 = (INT32)( ( TEXTURE_U( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cu2.d ) / n_distance;
n_dv2 = (INT32)( ( TEXTURE_V( m_packet.GouraudTexturedPolygon.vertex[ n_rightpoint ].n_texture ) << 16 ) - n_cv2.d ) / n_distance;
}
if( (INT16)n_cx1.w.h != (INT16)n_cx2.w.h && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( (INT16)n_cx1.w.h < (INT16)n_cx2.w.h )
{
n_x = n_cx1.w.h;
n_distance = (INT16)n_cx2.w.h - n_x;
n_r.d = n_cr1.d;
n_g.d = n_cg1.d;
n_b.d = n_cb1.d;
n_u.d = n_cu1.d;
n_v.d = n_cv1.d;
n_dr = (INT32)( n_cr2.d - n_cr1.d ) / n_distance;
n_dg = (INT32)( n_cg2.d - n_cg1.d ) / n_distance;
n_db = (INT32)( n_cb2.d - n_cb1.d ) / n_distance;
n_du = (INT32)( n_cu2.d - n_cu1.d ) / n_distance;
n_dv = (INT32)( n_cv2.d - n_cv1.d ) / n_distance;
}
else
{
n_x = n_cx2.w.h;
n_distance = (INT16)n_cx1.w.h - n_x;
n_r.d = n_cr2.d;
n_g.d = n_cg2.d;
n_b.d = n_cb2.d;
n_u.d = n_cu2.d;
n_v.d = n_cv2.d;
n_dr = (INT32)( n_cr1.d - n_cr2.d ) / n_distance;
n_dg = (INT32)( n_cg1.d - n_cg2.d ) / n_distance;
n_db = (INT32)( n_cb1.d - n_cb2.d ) / n_distance;
n_du = (INT32)( n_cu1.d - n_cu2.d ) / n_distance;
n_dv = (INT32)( n_cv1.d - n_cv2.d ) / n_distance;
}
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_r.d += n_dr * ( m_n_drawarea_x1 - n_x );
n_g.d += n_dg * ( m_n_drawarea_x1 - n_x );
n_b.d += n_db * ( m_n_drawarea_x1 - n_x );
n_u.d += n_du * ( m_n_drawarea_x1 - n_x );
n_v.d += n_dv * ( m_n_drawarea_x1 - n_x );
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
TEXTUREFILL( GOURAUDTEXTUREDPOLYGONUPDATE, n_u.w.h, n_v.w.h );
}
n_cx1.d += n_dx1;
n_cr1.d += n_dr1;
n_cg1.d += n_dg1;
n_cb1.d += n_db1;
n_cu1.d += n_du1;
n_cv1.d += n_dv1;
n_cx2.d += n_dx2;
n_cr2.d += n_dr2;
n_cg2.d += n_dg2;
n_cb2.d += n_db2;
n_cu2.d += n_du2;
n_cv2.d += n_dv2;
n_y++;
}
}
static void MonochromeLine( void )
{
PAIR n_x;
PAIR n_y;
INT32 n_dx;
INT32 n_dy;
INT32 n_dr;
INT32 n_dg;
INT32 n_db;
INT32 n_len;
INT32 n_xlen;
INT32 n_ylen;
INT32 n_xstart;
INT32 n_ystart;
INT32 n_xend;
INT32 n_yend;
UINT32 n_r;
UINT32 n_g;
UINT32 n_b;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 5 )
{
return;
}
DebugMesh( COORD_X( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_y );
DebugMeshEnd();
#endif
n_xstart = COORD_X( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_x;
n_xend = COORD_X( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_x;
n_ystart = COORD_Y( m_packet.MonochromeLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_y;
n_yend = COORD_Y( m_packet.MonochromeLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_y;
n_r = BGR_R( m_packet.MonochromeLine.n_bgr );
n_g = BGR_G( m_packet.MonochromeLine.n_bgr );
n_b = BGR_B( m_packet.MonochromeLine.n_bgr );
if( n_xend > n_xstart )
{
n_xlen = n_xend - n_xstart;
}
else
{
n_xlen = n_xstart - n_xend;
}
if( n_yend > n_ystart )
{
n_ylen = n_yend - n_ystart;
}
else
{
n_ylen = n_ystart - n_yend;
}
if( n_xlen > n_ylen )
{
n_len = n_xlen;
}
else
{
n_len = n_ylen;
}
if( n_len == 0 )
{
n_len = 1;
}
n_x.w.h = n_xstart; n_x.w.l = 0;
n_y.w.h = n_ystart; n_y.w.l = 0;
n_dx = (INT32)( ( n_xend << 16 ) - n_x.d ) / n_len;
n_dy = (INT32)( ( n_yend << 16 ) - n_y.d ) / n_len;
n_dr = 0;
n_dg = 0;
n_db = 0;
while( n_len > 0 )
{
if( (INT16)n_x.w.h >= (INT32)m_n_drawarea_x1 &&
(INT16)n_y.w.h >= (INT32)m_n_drawarea_y1 &&
(INT16)n_x.w.h <= (INT32)m_n_drawarea_x2 &&
(INT16)n_y.w.h <= (INT32)m_n_drawarea_y2 )
{
p_vram = m_p_p_vram[ n_y.w.h ] + n_x.w.h;
WRITE_PIXEL(
m_p_n_redshade[ MID_LEVEL | n_r ] |
m_p_n_greenshade[ MID_LEVEL | n_g ] |
m_p_n_blueshade[ MID_LEVEL | n_b ] );
}
n_x.d += n_dx;
n_y.d += n_dy;
n_len--;
}
}
static void GouraudLine( void )
{
PAIR n_x;
PAIR n_y;
INT32 n_dx;
INT32 n_dy;
INT32 n_dr;
INT32 n_dg;
INT32 n_db;
INT32 n_distance;
INT32 n_xlen;
INT32 n_ylen;
INT32 n_xstart;
INT32 n_ystart;
INT32 n_xend;
INT32 n_yend;
PAIR n_r;
PAIR n_g;
PAIR n_b;
PAIR n_cr1;
PAIR n_cg1;
PAIR n_cb1;
PAIR n_cr2;
PAIR n_cg2;
PAIR n_cb2;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 6 )
{
return;
}
DebugMesh( COORD_X( m_packet.GouraudLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.GouraudLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.GouraudLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.GouraudLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_y );
DebugMeshEnd();
#endif
n_xstart = COORD_X( m_packet.GouraudLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_x;
n_ystart = COORD_Y( m_packet.GouraudLine.vertex[ 0 ].n_coord ) + m_n_drawoffset_y;
n_cr1.w.h = BGR_R( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cr1.w.l = 0;
n_cg1.w.h = BGR_G( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cg1.w.l = 0;
n_cb1.w.h = BGR_B( m_packet.GouraudLine.vertex[ 0 ].n_bgr ); n_cb1.w.l = 0;
n_xend = COORD_X( m_packet.GouraudLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_x;
n_yend = COORD_Y( m_packet.GouraudLine.vertex[ 1 ].n_coord ) + m_n_drawoffset_y;
n_cr2.w.h = BGR_R( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cr1.w.l = 0;
n_cg2.w.h = BGR_G( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cg1.w.l = 0;
n_cb2.w.h = BGR_B( m_packet.GouraudLine.vertex[ 1 ].n_bgr ); n_cb1.w.l = 0;
n_x.w.h = n_xstart; n_x.w.l = 0;
n_y.w.h = n_ystart; n_y.w.l = 0;
n_r.d = n_cr1.d;
n_g.d = n_cg1.d;
n_b.d = n_cb1.d;
if( n_xend > n_xstart )
{
n_xlen = n_xend - n_xstart;
}
else
{
n_xlen = n_xstart - n_xend;
}
if( n_yend > n_ystart )
{
n_ylen = n_yend - n_ystart;
}
else
{
n_ylen = n_ystart - n_yend;
}
if( n_xlen > n_ylen )
{
n_distance = n_xlen;
}
else
{
n_distance = n_ylen;
}
if( n_distance == 0 )
{
n_distance = 1;
}
n_dx = (INT32)( ( n_xend << 16 ) - n_x.d ) / n_distance;
n_dy = (INT32)( ( n_yend << 16 ) - n_y.d ) / n_distance;
n_dr = (INT32)( n_cr2.d - n_cr1.d ) / n_distance;
n_dg = (INT32)( n_cg2.d - n_cg1.d ) / n_distance;
n_db = (INT32)( n_cb2.d - n_cb1.d ) / n_distance;
while( n_distance > 0 )
{
if( (INT16)n_x.w.h >= (INT32)m_n_drawarea_x1 &&
(INT16)n_y.w.h >= (INT32)m_n_drawarea_y1 &&
(INT16)n_x.w.h <= (INT32)m_n_drawarea_x2 &&
(INT16)n_y.w.h <= (INT32)m_n_drawarea_y2 )
{
p_vram = m_p_p_vram[ n_y.w.h ] + n_x.w.h;
WRITE_PIXEL(
m_p_n_redshade[ MID_LEVEL | n_r.w.h ] |
m_p_n_greenshade[ MID_LEVEL | n_g.w.h ] |
m_p_n_blueshade[ MID_LEVEL | n_b.w.h ] );
}
n_x.d += n_dx;
n_y.d += n_dy;
n_r.d += n_dr;
n_g.d += n_dg;
n_b.d += n_db;
n_distance--;
}
}
static void FrameBufferRectangleDraw( void )
{
PAIR n_r;
PAIR n_g;
PAIR n_b;
INT32 n_distance;
INT32 n_h;
INT16 n_y;
INT16 n_x;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 7 )
{
return;
}
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ), COORD_Y( m_packet.FlatRectangle.n_coord ) );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + SIZE_W( m_packet.FlatRectangle.n_size ), COORD_Y( m_packet.FlatRectangle.n_coord ) );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ), COORD_Y( m_packet.FlatRectangle.n_coord ) + SIZE_H( m_packet.FlatRectangle.n_size ) );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + SIZE_W( m_packet.FlatRectangle.n_size ), COORD_Y( m_packet.FlatRectangle.n_coord ) + SIZE_H( m_packet.FlatRectangle.n_size ) );
DebugMeshEnd();
#endif
n_r.w.h = BGR_R( m_packet.FlatRectangle.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatRectangle.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatRectangle.n_bgr ); n_b.w.l = 0;
n_y = COORD_Y( m_packet.FlatRectangle.n_coord );
n_h = SIZE_H( m_packet.FlatRectangle.n_size );
while( n_h > 0 )
{
n_x = COORD_X( m_packet.FlatRectangle.n_coord );
n_distance = SIZE_W( m_packet.FlatRectangle.n_size );
while( n_distance > 0 )
{
p_vram = m_p_p_vram[ n_y & 1023 ] + ( n_x & 1023 );
WRITE_PIXEL(
m_p_n_redshade[ MID_LEVEL | n_r.w.h ] |
m_p_n_greenshade[ MID_LEVEL | n_g.w.h ] |
m_p_n_blueshade[ MID_LEVEL | n_b.w.h ] );
n_x++;
n_distance--;
}
n_y++;
n_h--;
}
}
static void FlatRectangle( void )
{
INT16 n_y;
INT16 n_x;
UINT8 n_cmd;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
INT32 n_distance;
INT32 n_h;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 8 )
{
return;
}
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_x + SIZE_W( m_packet.FlatRectangle.n_size ), COORD_Y( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_y + SIZE_H( m_packet.FlatRectangle.n_size ) );
DebugMesh( COORD_X( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_x + SIZE_W( m_packet.FlatRectangle.n_size ), COORD_Y( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_y + SIZE_H( m_packet.FlatRectangle.n_size ) );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatRectangle.n_bgr );
SOLIDSETUP
n_r.w.h = BGR_R( m_packet.FlatRectangle.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatRectangle.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatRectangle.n_bgr ); n_b.w.l = 0;
n_y = COORD_Y( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_y;
n_h = SIZE_H( m_packet.FlatRectangle.n_size );
while( n_h > 0 )
{
n_x = COORD_X( m_packet.FlatRectangle.n_coord ) + m_n_drawoffset_x;
n_distance = SIZE_W( m_packet.FlatRectangle.n_size );
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
SOLIDFILL( FLATRECTANGEUPDATE )
}
n_y++;
n_h--;
}
}
static void FlatRectangle8x8( void )
{
INT16 n_y;
INT16 n_x;
UINT8 n_cmd;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
INT32 n_distance;
INT32 n_h;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 9 )
{
return;
}
DebugMesh( COORD_X( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_x + 8, COORD_Y( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_y + 8 );
DebugMesh( COORD_X( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_x + 8, COORD_Y( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_y + 8 );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatRectangle8x8.n_bgr );
SOLIDSETUP
n_r.w.h = BGR_R( m_packet.FlatRectangle8x8.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatRectangle8x8.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatRectangle8x8.n_bgr ); n_b.w.l = 0;
n_y = COORD_Y( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_y;
n_h = 8;
while( n_h > 0 )
{
n_x = COORD_X( m_packet.FlatRectangle8x8.n_coord ) + m_n_drawoffset_x;
n_distance = 8;
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
SOLIDFILL( FLATRECTANGEUPDATE )
}
n_y++;
n_h--;
}
}
static void FlatRectangle16x16( void )
{
INT16 n_y;
INT16 n_x;
UINT8 n_cmd;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
INT32 n_distance;
INT32 n_h;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 10 )
{
return;
}
DebugMesh( COORD_X( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_x + 16, COORD_Y( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_y + 16 );
DebugMesh( COORD_X( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_x + 16, COORD_Y( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_y + 16 );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatRectangle16x16.n_bgr );
SOLIDSETUP
n_r.w.h = BGR_R( m_packet.FlatRectangle16x16.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatRectangle16x16.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatRectangle16x16.n_bgr ); n_b.w.l = 0;
n_y = COORD_Y( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_y;
n_h = 16;
while( n_h > 0 )
{
n_x = COORD_X( m_packet.FlatRectangle16x16.n_coord ) + m_n_drawoffset_x;
n_distance = 16;
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
SOLIDFILL( FLATRECTANGEUPDATE )
}
n_y++;
n_h--;
}
}
static void FlatTexturedRectangle( void )
{
INT16 n_y;
INT16 n_x;
int n_tx;
int n_ty;
UINT8 n_cmd;
UINT32 n_clutx;
UINT32 n_cluty;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
UINT8 n_u;
UINT8 n_v;
int n_du;
int n_dv;
INT16 n_distance;
UINT32 n_h;
UINT16 *p_vram;
UINT16 *p_clut;
UINT16 n_bgr;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 11 )
{
return;
}
DebugMesh( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_x + SIZE_W( m_packet.FlatTexturedRectangle.n_size ), COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_y + SIZE_H( m_packet.FlatTexturedRectangle.n_size ) );
DebugMesh( COORD_X( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_x + SIZE_W( m_packet.FlatTexturedRectangle.n_size ), COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_y + SIZE_H( m_packet.FlatTexturedRectangle.n_size ) );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.FlatTexturedRectangle.n_bgr );
n_clutx = ( m_packet.FlatTexturedRectangle.n_texture.w.h & 0x3f ) << 4;
n_cluty = ( m_packet.FlatTexturedRectangle.n_texture.w.h >> 6 ) & 0x3ff;
n_r.d = 0;
n_g.d = 0;
n_b.d = 0;
TEXTURESETUP
SPRITESETUP
switch( n_cmd & 0x01 )
{
case 0:
n_r.w.h = BGR_R( m_packet.FlatTexturedRectangle.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.FlatTexturedRectangle.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.FlatTexturedRectangle.n_bgr ); n_b.w.l = 0;
break;
case 1:
n_r.w.h = 0x80; n_r.w.l = 0;
n_g.w.h = 0x80; n_g.w.l = 0;
n_b.w.h = 0x80; n_b.w.l = 0;
break;
}
n_v = TEXTURE_V( m_packet.FlatTexturedRectangle.n_texture );
n_y = COORD_Y( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_y;
n_h = SIZE_H( m_packet.FlatTexturedRectangle.n_size );
while( n_h > 0 )
{
n_x = COORD_X( m_packet.FlatTexturedRectangle.n_coord ) + m_n_drawoffset_x;
n_u = TEXTURE_U( m_packet.FlatTexturedRectangle.n_texture );
n_distance = SIZE_W( m_packet.FlatTexturedRectangle.n_size );
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_u += ( m_n_drawarea_x1 - n_x ) * n_du;
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
}
n_v += n_dv;
n_y++;
n_h--;
}
}
static void Sprite8x8( void )
{
INT16 n_y;
INT16 n_x;
int n_tx;
int n_ty;
UINT8 n_cmd;
UINT32 n_clutx;
UINT32 n_cluty;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
UINT8 n_u;
UINT8 n_v;
int n_du;
int n_dv;
INT16 n_distance;
UINT32 n_h;
UINT16 *p_vram;
UINT16 *p_clut;
UINT16 n_bgr;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 12 )
{
return;
}
DebugMesh( COORD_X( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_x + 7, COORD_Y( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_y + 7 );
DebugMesh( COORD_X( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_x + 7, COORD_Y( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_y + 7 );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.Sprite8x8.n_bgr );
n_clutx = ( m_packet.Sprite8x8.n_texture.w.h & 0x3f ) << 4;
n_cluty = ( m_packet.Sprite8x8.n_texture.w.h >> 6 ) & 0x3ff;
n_r.d = 0;
n_g.d = 0;
n_b.d = 0;
TEXTURESETUP
SPRITESETUP
switch( n_cmd & 0x01 )
{
case 0:
n_r.w.h = BGR_R( m_packet.Sprite8x8.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.Sprite8x8.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.Sprite8x8.n_bgr ); n_b.w.l = 0;
break;
case 1:
n_r.w.h = 0x80; n_r.w.l = 0;
n_g.w.h = 0x80; n_g.w.l = 0;
n_b.w.h = 0x80; n_b.w.l = 0;
break;
}
n_v = TEXTURE_V( m_packet.Sprite8x8.n_texture );
n_y = COORD_Y( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_y;
n_h = 8;
while( n_h > 0 )
{
n_x = COORD_X( m_packet.Sprite8x8.n_coord ) + m_n_drawoffset_x;
n_u = TEXTURE_U( m_packet.Sprite8x8.n_texture );
n_distance = 8;
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_u += ( m_n_drawarea_x1 - n_x ) * n_du;
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
}
n_v += n_dv;
n_y++;
n_h--;
}
}
static void Sprite16x16( void )
{
INT16 n_y;
INT16 n_x;
int n_tx;
int n_ty;
UINT8 n_cmd;
UINT32 n_clutx;
UINT32 n_cluty;
UINT16 *p_n_f;
UINT16 *p_n_redb;
UINT16 *p_n_greenb;
UINT16 *p_n_blueb;
UINT16 *p_n_redtrans;
UINT16 *p_n_greentrans;
UINT16 *p_n_bluetrans;
PAIR n_r;
PAIR n_g;
PAIR n_b;
UINT8 n_u;
UINT8 n_v;
int n_du;
int n_dv;
INT16 n_distance;
UINT32 n_h;
UINT16 *p_vram;
UINT16 *p_clut;
UINT16 n_bgr;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 13 )
{
return;
}
DebugMesh( COORD_X( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_x + 7, COORD_Y( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_y );
DebugMesh( COORD_X( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_y + 7 );
DebugMesh( COORD_X( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_x + 7, COORD_Y( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_y + 7 );
DebugMeshEnd();
#endif
n_cmd = BGR_C( m_packet.Sprite16x16.n_bgr );
n_clutx = ( m_packet.Sprite16x16.n_texture.w.h & 0x3f ) << 4;
n_cluty = ( m_packet.Sprite16x16.n_texture.w.h >> 6 ) & 0x3ff;
n_r.d = 0;
n_g.d = 0;
n_b.d = 0;
TEXTURESETUP
SPRITESETUP
switch( n_cmd & 0x01 )
{
case 0:
n_r.w.h = BGR_R( m_packet.Sprite16x16.n_bgr ); n_r.w.l = 0;
n_g.w.h = BGR_G( m_packet.Sprite16x16.n_bgr ); n_g.w.l = 0;
n_b.w.h = BGR_B( m_packet.Sprite16x16.n_bgr ); n_b.w.l = 0;
break;
case 1:
n_r.w.h = 0x80; n_r.w.l = 0;
n_g.w.h = 0x80; n_g.w.l = 0;
n_b.w.h = 0x80; n_b.w.l = 0;
break;
}
n_v = TEXTURE_V( m_packet.Sprite16x16.n_texture );
n_y = COORD_Y( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_y;
n_h = 16;
while( n_h > 0 )
{
n_x = COORD_X( m_packet.Sprite16x16.n_coord ) + m_n_drawoffset_x;
n_u = TEXTURE_U( m_packet.Sprite16x16.n_texture );
n_distance = 16;
if( n_distance > 0 && n_y >= (INT32)m_n_drawarea_y1 && n_y <= (INT32)m_n_drawarea_y2 )
{
if( ( (INT32)m_n_drawarea_x1 - n_x ) > 0 )
{
n_u += ( m_n_drawarea_x1 - n_x ) * n_du;
n_distance -= ( m_n_drawarea_x1 - n_x );
n_x = m_n_drawarea_x1;
}
TEXTUREFILL( FLATTEXTUREDRECTANGLEUPDATE, n_u, n_v );
}
n_v += n_dv;
n_y++;
n_h--;
}
}
static void Dot( void )
{
INT32 n_x;
INT32 n_y;
UINT32 n_r;
UINT32 n_g;
UINT32 n_b;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 14 )
{
return;
}
DebugMesh( COORD_X( m_packet.Dot.vertex.n_coord ) + m_n_drawoffset_x, COORD_Y( m_packet.Dot.vertex.n_coord ) + m_n_drawoffset_y );
DebugMeshEnd();
#endif
n_r = BGR_R( m_packet.Dot.n_bgr );
n_g = BGR_G( m_packet.Dot.n_bgr );
n_b = BGR_B( m_packet.Dot.n_bgr );
n_x = COORD_X( m_packet.Dot.vertex.n_coord ) + m_n_drawoffset_x;
n_y = COORD_Y( m_packet.Dot.vertex.n_coord ) + m_n_drawoffset_y;
if( (INT16)n_x >= (INT32)m_n_drawarea_x1 &&
(INT16)n_y >= (INT32)m_n_drawarea_y1 &&
(INT16)n_x <= (INT32)m_n_drawarea_x2 &&
(INT16)n_y <= (INT32)m_n_drawarea_y2 )
{
p_vram = m_p_p_vram[ n_y ] + n_x;
WRITE_PIXEL(
m_p_n_redshade[ MID_LEVEL | n_r ] |
m_p_n_greenshade[ MID_LEVEL | n_g ] |
m_p_n_blueshade[ MID_LEVEL | n_b ] );
}
}
static void MoveImage( void )
{
INT16 n_w;
INT16 n_h;
INT16 n_srcx;
INT16 n_srcy;
INT16 n_dsty;
INT16 n_dstx;
UINT16 *p_vram;
#if defined( MAME_DEBUG )
if( m_n_debugskip == 15 )
{
return;
}
DebugMesh( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ), COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) );
DebugMesh( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) + SIZE_W( m_packet.MoveImage.n_size ), COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) );
DebugMesh( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ), COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) + SIZE_H( m_packet.MoveImage.n_size ) );
DebugMesh( COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord ) + SIZE_W( m_packet.MoveImage.n_size ), COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord ) + SIZE_H( m_packet.MoveImage.n_size ) );
DebugMeshEnd();
#endif
n_srcy = COORD_Y( m_packet.MoveImage.vertex[ 0 ].n_coord );
n_dsty = COORD_Y( m_packet.MoveImage.vertex[ 1 ].n_coord );
n_h = SIZE_H( m_packet.MoveImage.n_size );
while( n_h > 0 )
{
n_srcx = COORD_X( m_packet.MoveImage.vertex[ 0 ].n_coord );
n_dstx = COORD_X( m_packet.MoveImage.vertex[ 1 ].n_coord );
n_w = SIZE_W( m_packet.MoveImage.n_size );
while( n_w > 0 )
{
p_vram = m_p_p_vram[ n_dsty & 1023 ] + ( n_dstx & 1023 );
WRITE_PIXEL( *( m_p_p_vram[ n_srcy & 1023 ] + ( n_srcx & 1023 ) ) );
n_srcx++;
n_dstx++;
n_w--;
}
n_srcy++;
n_dsty++;
n_h--;
}
}
void psx_gpu_write( UINT32 *p_ram, INT32 n_size )
{
while( n_size > 0 )
{
UINT32 data = *( p_ram );
verboselog( 2, "PSX Packet #%u %08x\n", m_n_gpu_buffer_offset, data );
m_packet.n_entry[ m_n_gpu_buffer_offset ] = data;
switch( m_packet.n_entry[ 0 ] >> 24 )
{
case 0x00:
verboselog( 1, "not handled: GPU Command 0x00: (%08x)\n", data );
break;
case 0x01:
verboselog( 1, "not handled: clear cache\n" );
break;
case 0x02:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: frame buffer rectangle %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 1 ] & 0xffff, m_packet.n_entry[ 1 ] >> 16, m_packet.n_entry[ 2 ] & 0xffff, m_packet.n_entry[ 2 ] >> 16 );
FrameBufferRectangleDraw();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x20:
case 0x21:
case 0x22:
case 0x23:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: monochrome 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
FlatPolygon( 3 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x24:
case 0x25:
case 0x26:
case 0x27:
if( m_n_gpu_buffer_offset < 6 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: textured 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
FlatTexturedPolygon( 3 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
if( m_n_gpu_buffer_offset < 4 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: monochrome 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
FlatPolygon( 4 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x2c:
case 0x2d:
case 0x2e:
case 0x2f:
if( m_n_gpu_buffer_offset < 8 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: textured 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
FlatTexturedPolygon( 4 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x30:
case 0x31:
case 0x32:
case 0x33:
if( m_n_gpu_buffer_offset < 5 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudPolygon( 3 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x34:
case 0x35:
case 0x36:
case 0x37:
if( m_n_gpu_buffer_offset < 8 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud textured 3 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudTexturedPolygon( 3 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x38:
case 0x39:
case 0x3a:
case 0x3b:
if( m_n_gpu_buffer_offset < 7 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudPolygon( 4 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
if( m_n_gpu_buffer_offset < 11 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud textured 4 point polygon\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudTexturedPolygon( 4 );
m_n_gpu_buffer_offset = 0;
}
break;
case 0x40:
case 0x41:
case 0x42:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: monochrome line\n", m_packet.n_entry[ 0 ] >> 24 );
MonochromeLine();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x48:
case 0x4a:
case 0x4c:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: monochrome polyline\n", m_packet.n_entry[ 0 ] >> 24 );
MonochromeLine();
if( ( m_packet.n_entry[ 3 ] & 0xf000f000 ) != 0x50005000 )
{
m_packet.n_entry[ 1 ] = m_packet.n_entry[ 2 ];
m_packet.n_entry[ 2 ] = m_packet.n_entry[ 3 ];
m_n_gpu_buffer_offset = 3;
}
else
{
m_n_gpu_buffer_offset = 0;
}
}
break;
case 0x50:
case 0x52:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud line\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudLine();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x58:
case 0x5c:
case 0x5e:
if( m_n_gpu_buffer_offset < 5 &&
( m_n_gpu_buffer_offset != 4 || ( m_packet.n_entry[ 4 ] & 0xf000f000 ) != 0x50005000 ) )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: gouraud polyline\n", m_packet.n_entry[ 0 ] >> 24 );
GouraudLine();
if( ( m_packet.n_entry[ 4 ] & 0xf000f000 ) != 0x50005000 )
{
m_packet.n_entry[ 0 ] = ( m_packet.n_entry[ 0 ] & 0xff000000 ) | ( m_packet.n_entry[ 2 ] & 0x00ffffff );
m_packet.n_entry[ 1 ] = m_packet.n_entry[ 3 ];
m_packet.n_entry[ 2 ] = m_packet.n_entry[ 4 ];
m_packet.n_entry[ 3 ] = m_packet.n_entry[ 5 ];
m_n_gpu_buffer_offset = 4;
}
else
{
m_n_gpu_buffer_offset = 0;
}
}
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: rectangle %d,%d %d,%d\n",
m_packet.n_entry[ 0 ] >> 24,
(INT16)( m_packet.n_entry[ 1 ] & 0xffff ), (INT16)( m_packet.n_entry[ 1 ] >> 16 ),
(INT16)( m_packet.n_entry[ 2 ] & 0xffff ), (INT16)( m_packet.n_entry[ 2 ] >> 16 ) );
FlatRectangle();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x64:
case 0x65:
case 0x66:
case 0x67:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: sprite %d,%d %u,%u %08x, %08x\n",
m_packet.n_entry[ 0 ] >> 24,
(INT16)( m_packet.n_entry[ 1 ] & 0xffff ), (INT16)( m_packet.n_entry[ 1 ] >> 16 ),
m_packet.n_entry[ 3 ] & 0xffff, m_packet.n_entry[ 3 ] >> 16,
m_packet.n_entry[ 0 ], m_packet.n_entry[ 2 ] );
FlatTexturedRectangle();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x68:
case 0x6a:
if( m_n_gpu_buffer_offset < 1 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: dot %d,%d %08x\n",
m_packet.n_entry[ 0 ] >> 24,
(INT16)( m_packet.n_entry[ 1 ] & 0xffff ), (INT16)( m_packet.n_entry[ 1 ] >> 16 ),
m_packet.n_entry[ 0 ] & 0xffffff );
Dot();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x70:
case 0x71:
/* 8*8 rectangle */
if( m_n_gpu_buffer_offset < 1 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: 16x16 rectangle %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ] );
FlatRectangle8x8();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x74:
case 0x75:
case 0x76:
case 0x77:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: 8x8 sprite %08x %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ] );
Sprite8x8();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x78:
case 0x79:
/* 16*16 rectangle */
if( m_n_gpu_buffer_offset < 1 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: 16x16 rectangle %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ] );
FlatRectangle16x16();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: 16x16 sprite %08x %08x %08x\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ] );
Sprite16x16();
m_n_gpu_buffer_offset = 0;
}
break;
case 0x80:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "move image in frame buffer %08x %08x %08x %08x\n", m_packet.n_entry[ 0 ], m_packet.n_entry[ 1 ], m_packet.n_entry[ 2 ], m_packet.n_entry[ 3 ] );
MoveImage();
m_n_gpu_buffer_offset = 0;
}
break;
case 0xa0:
if( m_n_gpu_buffer_offset < 3 )
{
m_n_gpu_buffer_offset++;
}
else
{
UINT32 n_pixel;
for( n_pixel = 0; n_pixel < 2; n_pixel++ )
{
UINT16 *p_vram;
verboselog( 2, "send image to framebuffer ( pixel %u,%u = %u )\n",
( m_n_vramx + m_packet.n_entry[ 1 ] ) & 1023,
( m_n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ) & 1023,
data & 0xffff );
p_vram = m_p_p_vram[ ( m_n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ) & 1023 ] + ( ( m_n_vramx + m_packet.n_entry[ 1 ] ) & 1023 );
WRITE_PIXEL( data & 0xffff );
m_n_vramx++;
if( m_n_vramx >= ( m_packet.n_entry[ 2 ] & 0xffff ) )
{
m_n_vramx = 0;
m_n_vramy++;
if( m_n_vramy >= ( m_packet.n_entry[ 2 ] >> 16 ) )
{
verboselog( 1, "%02x: send image to framebuffer %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 1 ] & 0xffff, ( m_packet.n_entry[ 1 ] >> 16 ),
m_packet.n_entry[ 2 ] & 0xffff, ( m_packet.n_entry[ 2 ] >> 16 ) );
m_n_gpu_buffer_offset = 0;
m_n_vramx = 0;
m_n_vramy = 0;
break;
}
}
data >>= 16;
}
}
break;
case 0xc0:
if( m_n_gpu_buffer_offset < 2 )
{
m_n_gpu_buffer_offset++;
}
else
{
verboselog( 1, "%02x: copy image from frame buffer\n", m_packet.n_entry[ 0 ] >> 24 );
m_n_gpustatus |= ( 1L << 0x1b );
}
break;
case 0xe1:
verboselog( 1, "%02x: draw mode %06x\n", m_packet.n_entry[ 0 ] >> 24,
m_packet.n_entry[ 0 ] & 0xffffff );
decode_tpage( &psxgpu, m_packet.n_entry[ 0 ] & 0xffffff );
break;
case 0xe2:
m_n_twy = ( ( ( m_packet.n_entry[ 0 ] >> 15 ) & 0x1f ) << 3 );
m_n_twx = ( ( ( m_packet.n_entry[ 0 ] >> 10 ) & 0x1f ) << 3 );
m_n_twh = 255 - ( ( ( m_packet.n_entry[ 0 ] >> 5 ) & 0x1f ) << 3 );
m_n_tww = 255 - ( ( m_packet.n_entry[ 0 ] & 0x1f ) << 3 );
verboselog( 1, "%02x: texture window %u,%u %u,%u\n", m_packet.n_entry[ 0 ] >> 24,
m_n_twx, m_n_twy, m_n_tww, m_n_twh );
break;
case 0xe3:
m_n_drawarea_x1 = m_packet.n_entry[ 0 ] & 1023;
if( m_n_gputype == 2 )
{
m_n_drawarea_y1 = ( m_packet.n_entry[ 0 ] >> 10 ) & 1023;
}
else
{
m_n_drawarea_y1 = ( m_packet.n_entry[ 0 ] >> 12 ) & 1023;
}
verboselog( 1, "%02x: drawing area top left %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
m_n_drawarea_x1, m_n_drawarea_y1 );
break;
case 0xe4:
m_n_drawarea_x2 = m_packet.n_entry[ 0 ] & 1023;
if( m_n_gputype == 2 )
{
m_n_drawarea_y2 = ( m_packet.n_entry[ 0 ] >> 10 ) & 1023;
}
else
{
m_n_drawarea_y2 = ( m_packet.n_entry[ 0 ] >> 12 ) & 1023;
}
verboselog( 1, "%02x: drawing area bottom right %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
m_n_drawarea_x2, m_n_drawarea_y2 );
break;
case 0xe5:
m_n_drawoffset_x = SINT11( m_packet.n_entry[ 0 ] & 2047 );
if( m_n_gputype == 2 )
{
m_n_drawoffset_y = SINT11( ( m_packet.n_entry[ 0 ] >> 11 ) & 2047 );
}
else
{
m_n_drawoffset_y = SINT11( ( m_packet.n_entry[ 0 ] >> 12 ) & 2047 );
}
verboselog( 1, "%02x: drawing offset %d,%d\n", m_packet.n_entry[ 0 ] >> 24,
m_n_drawoffset_x, m_n_drawoffset_y );
break;
case 0xe6:
m_n_gpustatus &= ~( 3L << 0xb );
m_n_gpustatus |= ( data & 0x03 ) << 0xb;
if( ( m_packet.n_entry[ 0 ] & 3 ) != 0 )
{
verboselog( 1, "not handled: mask setting %d\n", m_packet.n_entry[ 0 ] & 3 );
}
else
{
verboselog( 1, "mask setting %d\n", m_packet.n_entry[ 0 ] & 3 );
}
break;
default:
#if defined( MAME_DEBUG )
popmessage( "unknown GPU packet %08x", m_packet.n_entry[ 0 ] );
#endif
verboselog( 0, "unknown GPU packet %08x (%08x)\n", m_packet.n_entry[ 0 ], data );
#if ( STOP_ON_ERROR )
m_n_gpu_buffer_offset = 1;
#endif
break;
}
p_ram++;
n_size--;
}
}
WRITE32_HANDLER( psx_gpu_w )
{
switch( offset )
{
case 0x00:
psx_gpu_write( &data, 1 );
break;
case 0x01:
switch( data >> 24 )
{
case 0x00:
verboselog( 1, "reset gpu\n" );
m_n_gpu_buffer_offset = 0;
m_n_gpustatus = 0x14802000;
m_n_drawarea_x1 = 0;
m_n_drawarea_y1 = 0;
m_n_drawarea_x2 = 1023;
m_n_drawarea_y2 = 1023;
m_n_drawoffset_x = 0;
m_n_drawoffset_y = 0;
m_n_displaystartx = 0;
m_n_displaystarty = 0;
m_n_horiz_disstart = 0x260;
m_n_horiz_disend = 0xc60;
m_n_vert_disstart = 0x010;
m_n_vert_disend = 0x100;
m_n_vramx = 0;
m_n_vramy = 0;
m_n_twx = 0;
m_n_twy = 0;
m_n_twh = 255;
m_n_tww = 255;
updatevisiblearea();
break;
case 0x01:
verboselog( 1, "not handled: reset command buffer\n" );
m_n_gpu_buffer_offset = 0;
break;
case 0x02:
verboselog( 1, "not handled: reset irq\n" );
break;
case 0x03:
m_n_gpustatus &= ~( 1L << 0x17 );
m_n_gpustatus |= ( data & 0x01 ) << 0x17;
break;
case 0x04:
verboselog( 1, "dma setup %d\n", data & 3 );
m_n_gpustatus &= ~( 3L << 0x1d );
m_n_gpustatus |= ( data & 0x03 ) << 0x1d;
m_n_gpustatus &= ~( 1L << 0x19 );
if( ( data & 3 ) == 1 || ( data & 3 ) == 2 )
{
m_n_gpustatus |= ( 1L << 0x19 );
}
break;
case 0x05:
m_n_displaystartx = data & 1023;
if( m_n_gputype == 2 )
{
m_n_displaystarty = ( data >> 10 ) & 1023;
}
else
{
m_n_displaystarty = ( data >> 12 ) & 1023;
}
verboselog( 1, "start of display area %d %d\n", m_n_displaystartx, m_n_displaystarty );
break;
case 0x06:
m_n_horiz_disstart = data & 4095;
m_n_horiz_disend = ( data >> 12 ) & 4095;
verboselog( 1, "horizontal display range %d %d\n", m_n_horiz_disstart, m_n_horiz_disend );
break;
case 0x07:
m_n_vert_disstart = data & 1023;
m_n_vert_disend = ( data >> 10 ) & 2047;
verboselog( 1, "vertical display range %d %d\n", m_n_vert_disstart, m_n_vert_disend );
break;
case 0x08:
verboselog( 1, "display mode %02x\n", data & 0xff );
m_n_gpustatus &= ~( 127L << 0x10 );
m_n_gpustatus |= ( data & 0x3f ) << 0x11; /* width 0 + height + videmode + isrgb24 + isinter */
m_n_gpustatus |= ( ( data & 0x40 ) >> 0x06 ) << 0x10; /* width 1 */
if( m_n_gputype == 1 )
{
m_b_reverseflag = ( data >> 7 ) & 1;
}
updatevisiblearea();
break;
case 0x09:
verboselog( 1, "not handled: GPU Control 0x09: %08x\n", data );
break;
case 0x0d:
verboselog( 1, "reset lightgun coordinates %08x\n", data );
m_n_lightgun_x = 0;
m_n_lightgun_y = 0;
break;
case 0x10:
switch( data & 0xff )
{
case 0x03:
if( m_n_gputype == 2 )
{
m_n_gpuinfo = m_n_drawarea_x1 | ( m_n_drawarea_y1 << 10 );
}
else
{
m_n_gpuinfo = m_n_drawarea_x1 | ( m_n_drawarea_y1 << 12 );
}
verboselog( 1, "GPU Info - Draw area top left %08x\n", m_n_gpuinfo );
break;
case 0x04:
if( m_n_gputype == 2 )
{
m_n_gpuinfo = m_n_drawarea_x2 | ( m_n_drawarea_y2 << 10 );
}
else
{
m_n_gpuinfo = m_n_drawarea_x2 | ( m_n_drawarea_y2 << 12 );
}
verboselog( 1, "GPU Info - Draw area bottom right %08x\n", m_n_gpuinfo );
break;
case 0x05:
if( m_n_gputype == 2 )
{
m_n_gpuinfo = ( m_n_drawoffset_x & 2047 ) | ( ( m_n_drawoffset_y & 2047 ) << 11 );
}
else
{
m_n_gpuinfo = ( m_n_drawoffset_x & 2047 ) | ( ( m_n_drawoffset_y & 2047 ) << 12 );
}
verboselog( 1, "GPU Info - Draw offset %08x\n", m_n_gpuinfo );
break;
case 0x07:
m_n_gpuinfo = m_n_gputype;
verboselog( 1, "GPU Info - GPU Type %08x\n", m_n_gpuinfo );
break;
case 0x08:
m_n_gpuinfo = m_n_lightgun_x | ( m_n_lightgun_y << 16 );
verboselog( 1, "GPU Info - lightgun coordinates %08x\n", m_n_gpuinfo );
break;
default:
verboselog( 0, "GPU Info - unknown request (%08x)\n", data );
m_n_gpuinfo = 0;
break;
}
break;
case 0x20:
verboselog( 1, "not handled: GPU Control 0x20: %08x\n", data );
break;
default:
#if defined( MAME_DEBUG )
popmessage( "unknown GPU command %08x", data );
#endif
verboselog( 0, "gpu_w( %08x ) unknown GPU command\n", data );
break;
}
break;
default:
verboselog( 0, "gpu_w( %08x, %08x, %08x ) unknown register\n", offset, data, mem_mask );
break;
}
}
void psx_gpu_read( UINT32 *p_ram, INT32 n_size )
{
while( n_size > 0 )
{
if( ( m_n_gpustatus & ( 1L << 0x1b ) ) != 0 )
{
UINT32 n_pixel;
PAIR data;
verboselog( 2, "copy image from frame buffer ( %d, %d )\n", m_n_vramx, m_n_vramy );
data.d = 0;
for( n_pixel = 0; n_pixel < 2; n_pixel++ )
{
data.w.l = data.w.h;
data.w.h = *( m_p_p_vram[ m_n_vramy + ( m_packet.n_entry[ 1 ] >> 16 ) ] + m_n_vramx + ( m_packet.n_entry[ 1 ] & 0xffff ) );
m_n_vramx++;
if( m_n_vramx >= ( m_packet.n_entry[ 2 ] & 0xffff ) )
{
m_n_vramx = 0;
m_n_vramy++;
if( m_n_vramy >= ( m_packet.n_entry[ 2 ] >> 16 ) )
{
verboselog( 1, "copy image from frame buffer end\n" );
m_n_gpustatus &= ~( 1L << 0x1b );
m_n_gpu_buffer_offset = 0;
m_n_vramx = 0;
m_n_vramy = 0;
if( n_pixel == 0 )
{
data.w.l = data.w.h;
data.w.h = 0;
}
break;
}
}
}
*( p_ram ) = data.d;
}
else
{
verboselog( 2, "read GPU info (%08x)\n", m_n_gpuinfo );
*( p_ram ) = m_n_gpuinfo;
}
p_ram++;
n_size--;
}
}
READ32_HANDLER( psx_gpu_r )
{
UINT32 data;
switch( offset )
{
case 0x00:
psx_gpu_read( &data, 1 );
break;
case 0x01:
verboselog( 1, "read GPU status (%08x)\n", m_n_gpustatus );
data = m_n_gpustatus;
break;
default:
verboselog( 0, "gpu_r( %08x, %08x ) unknown register\n", offset, mem_mask );
data = 0;
break;
}
return data;
}
INTERRUPT_GEN( psx_vblank )
{
#if defined( MAME_DEBUG )
DebugCheckKeys();
#endif
m_n_gpustatus ^= ( 1L << 31 );
psx_irq_set( 0x0001 );
}
void psx_gpu_reset( void )
{
psx_gpu_w( 1, 0, 0 );
}
void psx_lightgun_set( int n_x, int n_y )
{
m_n_lightgun_x = n_x;
m_n_lightgun_y = n_y;
}