diff options
Diffstat (limited to 'src/mame/video/ygv608.c')
-rw-r--r-- | src/mame/video/ygv608.c | 1801 |
1 files changed, 1801 insertions, 0 deletions
diff --git a/src/mame/video/ygv608.c b/src/mame/video/ygv608.c new file mode 100644 index 00000000000..ec17121c800 --- /dev/null +++ b/src/mame/video/ygv608.c @@ -0,0 +1,1801 @@ + +/* + * Yamaha YGV608 - PVDC2 Pattern mode Video Display Controller 2 + * - Mark McDougall + * + * Notes: + * ====== + * + * This implementation is far from complete. + * There's enough here to emulate Namco ND-1 games. + * Some functionality is missing, some is incomplete. + * Also missing for ND-1 is rotation and scaling (cosmetic only). + * + * It could also do with some optimisation for speed! + * + * (Still lots of debugging info/options in here!) + * + * TODO: soon + * create tilemaps at vh_start time and switch between at runtime + * mark tiles dirty when VRAM is written to instead of dirtying entire + * screen each frame + * + * T.B.D. (not critical to ND-1) + * ====== + * + * Rotation + * Scaling + * Split-screen scrolling by row (by column supported) (see test mode) + * Everything else! :) + */ + +#include <ctype.h> +#include "driver.h" +#include "namcond1.h" // only while debugging +#include "video/ygv608.h" + +#define _ENABLE_SPRITES +#define _ENABLE_SCROLLX +#define _ENABLE_SCROLLY +//#define _ENABLE_SCREEN_RESIZE +//#define _ENABLE_ROTATE_ZOOM +//#define _SHOW_VIDEO_DEBUG + +static YGV608 ygv608; + +static tilemap *tilemap_A_cache_8[3]; +static tilemap *tilemap_A_cache_16[3]; +static tilemap *tilemap_B_cache_8[3]; +static tilemap *tilemap_B_cache_16[3]; +static tilemap *tilemap_A = NULL; +static tilemap *tilemap_B = NULL; +static mame_bitmap *work_bitmap = NULL; + +static void HandleYGV608Reset( void ); +static void HandleRomTransfers( void ); +static void SetPreShortcuts( int reg, int data ); +static void SetPostShortcuts( int reg ); + +#ifdef MAME_DEBUG +static void ShowYGV608Registers( void ); +#endif + +/* interrupt generated every 1ms second */ +INTERRUPT_GEN( ygv608_timed_interrupt ) +{ +/* + this is not quite generic, because we trigger a 68k interrupt + - if this chip is ever used by another driver, we should make + this more generic - or move it into the machine driver +*/ + + static int timer = 0; + + if( ++timer == 1000 ) + timer = 0; + + /* once every 60Hz, set the vertical border interval start flag */ + if( ( timer % (1000/60) ) == 0 ) + { + ygv608.ports.s.p6 |= p6_fv; + if (ygv608.regs.s.r14 & r14_iev) + irq2_line_hold(); + } + + /* once every 60Hz, set the position detection flag (somewhere) */ + else if( ( timer % (1000/60) ) == 7 ) + { + ygv608.ports.s.p6 |= p6_fp; + if (ygv608.regs.s.r14 & r14_iep) + irq2_line_hold(); + } +} + + +static TILEMAP_MAPPER( get_tile_offset ) +{ + // this optimisation is not much good to us, + // since we really need row,col in the get_tile_info() routines + // - so just pack them into a UINT32 + + return( ( col << 6 ) | row ); +} + +#define layout_total(x) \ +(machine->drv->gfxdecodeinfo[x].gfxlayout->total) + +static TILE_GET_INFO( get_tile_info_A_8 ) +{ + // extract row,col packed into tile_index + int col = tile_index >> 6; + int row = tile_index & 0x3f; + + UINT8 attr = 0; + int pattern_name_base = 0; + int set = ((ygv608.regs.s.r7 & r7_md) == MD_1PLANE_256COLOUR + ? GFX_8X8_8BIT : GFX_8X8_4BIT ); + int base = row >> ygv608.base_y_shift; + + if( col >= ygv608.page_x ) + { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else if( row >= ygv608.page_y ) + { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else + { + int sx, sy, page; + int i = pattern_name_base + (((row << ygv608.pny_shift) + col) << ygv608.bits16); + int j = ygv608.pattern_name_table[i]; + int f = 0; + + if( ygv608.bits16 ) + { + j += ((int)(ygv608.pattern_name_table[i+1] & ygv608.na8_mask )) << 8; + // attribute only valid in 16 color mode + if (set == GFX_8X8_4BIT) + attr = ygv608.pattern_name_table[i+1] >> 4; + + if (ygv608.regs.s.r7 & r7_flip) + { + if (ygv608.pattern_name_table[i+1] & (1<<3)) f |= TILE_FLIPX; + if (ygv608.pattern_name_table[i+1] & (1<<2)) f |= TILE_FLIPY; + } + } + + /* calculate page according to scroll data */ + /* - assuming full-screen scroll only for now... */ + sy = (int)ygv608.scroll_data_table[0][0x00] + + (((int)ygv608.scroll_data_table[0][0x01] & 0x0f ) << 8); + sx = (int)ygv608.scroll_data_table[0][0x80] + + (((int)ygv608.scroll_data_table[0][0x81] & 0x0f ) << 8); + + if ((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_16BIT) + { + page = ( ( sx + col * 8 ) % 1024 ) / 256; + page += ( ( ( sy + row * 8 ) % 2048 ) / 256 ) * 4; + } + else if (ygv608.regs.s.r8 & r8_pgs) + { + page = ( ( sx + col * 8 ) % 2048 ) / 512; + page += ( ( ( sy + row * 8 ) % 2048 ) / 256 ) * 4; + } + else + { + page = ( ( sx + col * 8 ) % 2048 ) / 256; + page += ( ( ( sy + row * 8 ) % 2048 ) / 512 ) * 8; + } + + /* add page, base address to pattern name */ + j += ( (int)ygv608.scroll_data_table[0][0xc0+page] << 10 ); + j += ( ygv608.base_addr[0][base] << 8 ); + + if( j >= layout_total(set) ) + { + logerror( "A_8X8: tilemap=%d\n", j ); + j = 0; + } + if ((ygv608.regs.s.r12 & r12_apf) != 0) + { + // attribute only valid in 16 color mode + if( set == GFX_8X8_4BIT ) + attr = ( j >> ( ((ygv608.regs.s.r12 & r12_apf) - 1 ) * 2 ) ) & 0x0f; + } + // banking + if (set == GFX_8X8_4BIT) + { + j += namcond1_gfxbank * 0x10000; + } + else // 8x8x8 + { + j += namcond1_gfxbank * 0x8000; + } + + SET_TILE_INFO( set, j, attr & 0x0F, f ); + } +} + +static TILE_GET_INFO( get_tile_info_B_8 ) +{ + // extract row,col packed into tile_index + int col = tile_index >> 6; + int row = tile_index & 0x3f; + + UINT8 attr = 0; + int pattern_name_base = ( ( ygv608.page_y << ygv608.pny_shift ) + << ygv608.bits16 ); + int set = GFX_8X8_4BIT; + int base = row >> ygv608.base_y_shift; + + if ((ygv608.regs.s.r7 & r7_md) & MD_1PLANE ) + { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else if (col >= ygv608.page_x) + { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else if (row >= ygv608.page_y) + { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else + { + int sx, sy, page; + int i = pattern_name_base + (((row << ygv608.pny_shift) + col) << ygv608.bits16); + int j = ygv608.pattern_name_table[i]; + int f = 0; + + if (ygv608.bits16) + { + j += ((int)(ygv608.pattern_name_table[i+1] & ygv608.na8_mask )) << 8; + attr = ygv608.pattern_name_table[i+1] >> 4; /*& 0x00; 0xf0;*/ + + if (ygv608.regs.s.r7 & r7_flip) + { + if (ygv608.pattern_name_table[i+1] & (1<<3)) f |= TILE_FLIPX; + if (ygv608.pattern_name_table[i+1] & (1<<2)) f |= TILE_FLIPY; + } + } + + /* calculate page according to scroll data */ + /* - assuming full-screen scroll only for now... */ + sy = (int)ygv608.scroll_data_table[1][0x00] + + (((int)ygv608.scroll_data_table[1][0x01] & 0x0f ) << 8); + sx = (int)ygv608.scroll_data_table[1][0x80] + + (((int)ygv608.scroll_data_table[1][0x81] & 0x0f ) << 8); + + if ((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_16BIT ) + { + page = ( ( sx + col * 8 ) % 1024 ) / 256; + page += ( ( ( sy + row * 8 ) % 2048 ) / 256 ) * 4; + } + else if (ygv608.regs.s.r8 & r8_pgs) + { + page = ( ( sx + col * 8 ) % 2048 ) / 512; + page += ( ( ( sy + row * 8 ) % 2048 ) / 256 ) * 4; + } + else + { + page = ( ( sx + col * 8 ) % 2048 ) / 256; + page += ( ( ( sy + row * 8 ) % 2048 ) / 512 ) * 8; + } + + /* add page, base address to pattern name */ + j += ( (int)ygv608.scroll_data_table[1][0xc0+page] << 10 ); + j += ( ygv608.base_addr[1][base] << 8 ); + + if( j >= layout_total(set) ) + { + logerror( "B_8X8: tilemap=%d\n", j ); + j = 0; + } + if ((ygv608.regs.s.r12 & r12_bpf) != 0) + { + UINT8 color = (ygv608.regs.s.r12 & r12_bpf) >> 3; + + /* assume 16 colour mode for now... */ + attr = ( j >> ( (color - 1 ) * 2 ) ) & 0x0f; + } + + // banking + if (set == GFX_8X8_4BIT) + { + j += namcond1_gfxbank * 0x10000; + } + else // 8x8x8 + { + j += namcond1_gfxbank * 0x8000; + } + + SET_TILE_INFO( set, j, attr, f ); + } +} + +static TILE_GET_INFO( get_tile_info_A_16 ) +{ + // extract row,col packed into tile_index + int col = tile_index >> 6; + int row = tile_index & 0x3f; + + UINT8 attr = 0; + int pattern_name_base = 0; + int set = ((ygv608.regs.s.r7 & r7_md) == MD_1PLANE_256COLOUR + ? GFX_16X16_8BIT : GFX_16X16_4BIT ); + int base = row >> ygv608.base_y_shift; + + if( col >= ygv608.page_x ) { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else if( row >= ygv608.page_y ) { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else { + int sx, sy, page; + int j; + int i = ( ( ( row << ygv608.pny_shift ) + col ) << ygv608.bits16 ); + int f = 0; + i += pattern_name_base; + + j = ygv608.pattern_name_table[i]; + if( ygv608.bits16 ) { + j += ((int)(ygv608.pattern_name_table[i+1] & ygv608.na8_mask )) << 8; + // attribute only valid in 16 color mode + if( set == GFX_16X16_4BIT ) + attr = ygv608.pattern_name_table[i+1] >> 4; + + if (ygv608.regs.s.r7 & r7_flip) + { + if (ygv608.pattern_name_table[i+1] & (1<<3)) f |= TILE_FLIPX; + if (ygv608.pattern_name_table[i+1] & (1<<2)) f |= TILE_FLIPY; + } + } + + /* calculate page according to scroll data */ + /* - assuming full-screen scroll only for now... */ + sy = (int)ygv608.scroll_data_table[0][0x00] + + (((int)ygv608.scroll_data_table[0][0x01] & 0x0f ) << 8); + sx = (int)ygv608.scroll_data_table[0][0x80] + + (((int)ygv608.scroll_data_table[0][0x81] & 0x0f ) << 8); + if((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_16BIT ) { + page = ( ( sx + col * 16 ) % 2048 ) / 512; + page += ( ( sy + row * 16 ) / 512 ) * 4; + } + else if (ygv608.regs.s.r8 & r8_pgs) { + page = ( sx + col * 16 ) / 512; + page += ( ( sy + row * 16 ) / 1024 ) * 8; + } + else { + page = ( sx + col * 16 ) / 1024; + page += ( ( sy + row * 16 ) / 512 ) * 4; + } + + /* add page, base address to pattern name */ + j += ( (int)ygv608.scroll_data_table[0][0xc0+page] << 8 ); + j += ( ygv608.base_addr[0][base] << 8 ); + + if( j >= layout_total(set) ) { + logerror( "A_16X16: tilemap=%d\n", j ); + j = 0; + } + + if ((ygv608.regs.s.r12 & r12_apf) != 0) + { + // attribute only valid in 16 color mode + if( set == GFX_16X16_4BIT ) + attr = ( j >> ( ((ygv608.regs.s.r12 & r12_apf)) * 2 ) ) & 0x0f; + } + + // banking + if (set == GFX_16X16_4BIT) + { + j += namcond1_gfxbank * 0x4000; + } + else // 8x8x8 + { + j += namcond1_gfxbank * 0x2000; + } + + + SET_TILE_INFO( set, j, attr, f ); + } +} + +static TILE_GET_INFO( get_tile_info_B_16 ) +{ + // extract row,col packed into tile_index + int col = tile_index >> 6; + int row = tile_index & 0x3f; + + UINT8 attr = 0; + int pattern_name_base = ( ( ygv608.page_y << ygv608.pny_shift ) + << ygv608.bits16 ); + int set = GFX_16X16_4BIT; + int base = row >> ygv608.base_y_shift; + + if((ygv608.regs.s.r7 & r7_md) & MD_1PLANE ) { + SET_TILE_INFO( set, 0, 0, 0 ); + } + if( col >= ygv608.page_x ) { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else if( row >= ygv608.page_y ) { + SET_TILE_INFO( set, 0, 0, 0 ); + } + else { + int sx, sy, page; + int j; + int i = ( ( ( row << ygv608.pny_shift ) + col ) << ygv608.bits16 ); + int f = 0; + i += pattern_name_base; + + j = ygv608.pattern_name_table[i]; + if( ygv608.bits16 ) { + j += ((int)(ygv608.pattern_name_table[i+1] & ygv608.na8_mask )) << 8; + attr = ygv608.pattern_name_table[i+1] >> 4; /*& 0x00; 0xf0;*/ + + if (ygv608.regs.s.r7 & r7_flip) + { + if (ygv608.pattern_name_table[i+1] & (1<<3)) f |= TILE_FLIPX; + if (ygv608.pattern_name_table[i+1] & (1<<2)) f |= TILE_FLIPY; + } + } + + /* calculate page according to scroll data */ + /* - assuming full-screen scroll only for now... */ + sy = (int)ygv608.scroll_data_table[1][0x00] + + (((int)ygv608.scroll_data_table[1][0x01] & 0x0f ) << 8); + sx = (int)ygv608.scroll_data_table[1][0x80] + + (((int)ygv608.scroll_data_table[1][0x81] & 0x0f ) << 8); + if((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_16BIT ) { + page = ( ( sx + col * 16 ) % 2048 ) / 512; + page += ( ( sy + row * 16 ) / 512 ) * 4; + } + else if (ygv608.regs.s.r8 & r8_pgs) { + page = ( sx + col * 16 ) / 512; + page += ( ( sy + row * 16 ) / 1024 ) * 8; + } + else { + page = ( sx + col * 16 ) / 1024; + page += ( ( sy + row * 16 ) / 512 ) * 4; + } + + /* add page, base address to pattern name */ + j += ( (int)ygv608.scroll_data_table[1][0xc0+page] << 8 ); + j += ( ygv608.base_addr[1][base] << 8 ); + + if( j >= layout_total(set) ) { + logerror( "B_16X16: tilemap=%d\n", j ); + j = 0; + } + + if ((ygv608.regs.s.r12 & r12_bpf) != 0) + { + UINT8 color = (ygv608.regs.s.r12 & r12_bpf) >> 3; + + /* assume 16 colour mode for now... */ + attr = ( j >> (color * 2)) & 0x0f; + } + + // banking + if (set == GFX_16X16_4BIT) + { + j += namcond1_gfxbank * 0x4000; + } + else // 8x8x8 + { + j += namcond1_gfxbank * 0x2000; + } + + + SET_TILE_INFO( set, j, attr, f ); + } +} + +static void ygv608_postload(void) +{ + int i; + + ygv608.screen_resize = 1; + ygv608.tilemap_resize = 1; + + for(i = 0; i < 50; i++) + SetPostShortcuts(i); +} + +static void ygv608_register_state_save(void) +{ + state_save_register_item_array("ygv608", 0, ygv608.ports.b); + state_save_register_item_array("ygv608", 0, ygv608.regs.b); + state_save_register_item_array("ygv608", 0, ygv608.pattern_name_table); + state_save_register_item_array("ygv608", 0, ygv608.sprite_attribute_table.b); + state_save_register_item_2d_array("ygv608", 0, ygv608.scroll_data_table); + state_save_register_item_2d_array("ygv608", 0, ygv608.colour_palette); + + state_save_register_func_postload(ygv608_postload); +} + +VIDEO_START( ygv608 ) +{ + memset( &ygv608, 0, sizeof(ygv608) ); + + // flag rebuild of the tilemaps + ygv608.screen_resize = 1; + ygv608.tilemap_resize = 1; + namcond1_gfxbank = 0; + + /* create tilemaps of all sizes and combinations */ + tilemap_A_cache_8[0] = tilemap_create(get_tile_info_A_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 32,32); + tilemap_A_cache_8[1] = tilemap_create(get_tile_info_A_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 64,32); + tilemap_A_cache_8[2] = tilemap_create(get_tile_info_A_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 32,64); + + tilemap_A_cache_16[0] = tilemap_create(get_tile_info_A_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 32,32); + tilemap_A_cache_16[1] = tilemap_create(get_tile_info_A_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 64,32); + tilemap_A_cache_16[2] = tilemap_create(get_tile_info_A_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 32,64); + + tilemap_B_cache_8[0] = tilemap_create(get_tile_info_B_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 32,32); + tilemap_B_cache_8[1] = tilemap_create(get_tile_info_B_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 64,32); + tilemap_B_cache_8[2] = tilemap_create(get_tile_info_B_8, get_tile_offset, TILEMAP_TYPE_PEN, 8,8, 32,64); + + tilemap_B_cache_16[0] = tilemap_create(get_tile_info_B_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 32,32); + tilemap_B_cache_16[1] = tilemap_create(get_tile_info_B_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 64,32); + tilemap_B_cache_16[2] = tilemap_create(get_tile_info_B_16, get_tile_offset, TILEMAP_TYPE_PEN, 16,16, 32,64); + + tilemap_A = NULL; + tilemap_B = NULL; + + ygv608_register_state_save(); +} + +static void draw_sprites(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect ) +{ +#ifdef _ENABLE_SPRITES + + // sprites are always clipped to 512x512 + // - regardless of the visible display dimensions + static rectangle spriteClip = { 0, 512, 0, 512 }; + + PSPRITE_ATTR sa; + int flipx = 0, flipy = 0; + int i; + + /* ensure that sprites are enabled */ + if( ((ygv608.regs.s.r7 & r7_dspe) == 0 ) || (ygv608.regs.s.r10 & r10_sprd)) + return; + + /* draw sprites */ + sect_rect(&spriteClip, cliprect); + sa = &ygv608.sprite_attribute_table.s[YGV608_MAX_SPRITES-1]; + for( i=0; i<YGV608_MAX_SPRITES; i++, sa-- ) + { + int code, color, sx, sy, size, attr, g_attr, spf; + + color = (sa->attr >> 4) & 0x0f; + sx = ( (int)(sa->attr & 0x02) << 7 ) | (int)sa->sx; + sy = ( ( ( (int)(sa->attr & 0x01) << 8 ) | (int)sa->sy ) + 1 ) & 0x1ff; + attr = (sa->attr & 0x0c) >> 2; + g_attr = (ygv608.regs.s.r10 & r10_spa) >> 6; + spf = (ygv608.regs.s.r12 & r12_spf) >> 6; + + if ((ygv608.regs.s.r10 & r10_spas) == SPAS_SPRITESIZE ) + { + size = g_attr; + flipx = (attr & SZ_HORIZREVERSE) != 0; + flipy = (attr & SZ_VERTREVERSE) != 0; + } + else + { + size = attr; + flipx = (g_attr & SZ_HORIZREVERSE) != 0; + flipy = (g_attr & SZ_VERTREVERSE) != 0; + } + + switch( size ) { + + case SZ_8X8 : + code = ( (int)ygv608.regs.s.sba << 8 ) | (int)sa->sn; + if (spf != 0) + color = ( code >> ( (spf - 1) * 2 ) ) & 0x0f; + if( code >= layout_total(GFX_8X8_4BIT) ) { + logerror( "SZ_8X8: sprite=%d\n", code ); + code = 0; + } + drawgfx( bitmap, machine->gfx[GFX_8X8_4BIT], + code+namcond1_gfxbank*0x10000, + color, + flipx,flipy, + sx,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + // redraw with wrap-around + if( sx > 512-8 ) + drawgfx( bitmap, machine->gfx[GFX_8X8_4BIT], + code+namcond1_gfxbank*0x10000, + color, + flipx,flipy, + sx-512,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + if( sy > 512-8 ) + drawgfx( bitmap, machine->gfx[GFX_8X8_4BIT], + code+namcond1_gfxbank*0x10000, + color, + flipx,flipy, + sx,sy-512, + &spriteClip,TRANSPARENCY_PEN,0x00); + // really should draw again for both wrapped! + // - ignore until someone thinks it's required + break; + + case SZ_16X16 : + code = ( ( (int)ygv608.regs.s.sba & 0xfc ) << 6 ) | (int)sa->sn; + if (spf != 0) + color = ( code >> (spf * 2) ) & 0x0f; + if( code >= layout_total(GFX_16X16_4BIT) ) { + logerror( "SZ_8X8: sprite=%d\n", code ); + code = 0; + } + drawgfx( bitmap, machine->gfx[GFX_16X16_4BIT], + code+namcond1_gfxbank*0x4000, + color, + flipx,flipy, + sx,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + // redraw with wrap-around + if( sx > 512-16 ) + drawgfx( bitmap, machine->gfx[GFX_16X16_4BIT], + code+namcond1_gfxbank*0x4000, + color, + flipx,flipy, + sx-512,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + if( sy > 512-16 ) + drawgfx( bitmap, machine->gfx[GFX_16X16_4BIT], + code+namcond1_gfxbank*0x4000, + color, + flipx,flipy, + sx,sy-512, + &spriteClip,TRANSPARENCY_PEN,0x00); + // really should draw again for both wrapped! + // - ignore until someone thinks it's required + break; + + case SZ_32X32 : + code = ( ( (int)ygv608.regs.s.sba & 0xf0 ) << 4 ) | (int)sa->sn; + if (spf != 0) + color = ( code >> ( (spf + 1) * 2 ) ) & 0x0f; + if( code >= layout_total(GFX_32X32_4BIT) ) { + logerror( "SZ_32X32: sprite=%d\n", code ); + code = 0; + } + drawgfx( bitmap, machine->gfx[GFX_32X32_4BIT], + code+namcond1_gfxbank*0x1000, + color, + flipx,flipy, + sx,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + // redraw with wrap-around + if( sx > 512-32 ) + drawgfx( bitmap, machine->gfx[GFX_32X32_4BIT], + code+namcond1_gfxbank*0x1000, + color, + flipx,flipy, + sx-512,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + if( sy > 512-32 ) + drawgfx( bitmap, machine->gfx[GFX_32X32_4BIT], + code+namcond1_gfxbank*0x1000, + color, + flipx,flipy, + sx,sy-512, + &spriteClip,TRANSPARENCY_PEN,0x00); + // really should draw again for both wrapped! + // - ignore until someone thinks it's required + break; + + case SZ_64X64 : + code = ( ( (int)ygv608.regs.s.sba & 0xc0 ) << 2 ) | (int)sa->sn; + if (spf != 0) + color = ( code >> ( (spf + 1) * 2 ) ) & 0x0f; + if( code >= layout_total(GFX_64X64_4BIT) ) { + logerror( "SZ_64X64: sprite=%d\n", code ); + code = 0; + } + drawgfx( bitmap, machine->gfx[GFX_64X64_4BIT], + code+namcond1_gfxbank*0x400, + color, + flipx,flipy, + sx,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + // redraw with wrap-around + if( sx > 512-64 ) + drawgfx( bitmap, machine->gfx[GFX_64X64_4BIT], + code+namcond1_gfxbank*0x400, + color, + flipx,flipy, + sx-512,sy, + &spriteClip,TRANSPARENCY_PEN,0x00); + if( sy > 512-64 ) + drawgfx( bitmap, machine->gfx[GFX_64X64_4BIT], + code+namcond1_gfxbank*0x400, + color, + flipx,flipy, + sx,sy-512, + &spriteClip,TRANSPARENCY_PEN,0x00); + // really should draw again for both wrapped! + // - ignore until someone thinks it's required + break; + + default : + break; + } + } + +#endif +} + +#ifdef _SHOW_VIDEO_DEBUG +static char *mode[] = { "2PLANE_8BIT", + "2PLANE_16BIT", + "1PLANE_16COLORS", + "1PLANE_256COLORS" }; + +static char *psize[] = { "8x8", "16x16", "32x32", "64x64" }; +#endif + +VIDEO_UPDATE( ygv608 ) +{ +#ifdef _SHOW_VIDEO_DEBUG + char buffer[64]; +#endif + int col; +#ifdef _ENABLE_ROTATE_ZOOM + int xc, yc; + double r, alpha, sin_theta, cos_theta; +#endif + rectangle finalclip; + + // clip to the current bitmap + finalclip.min_x = 0; + finalclip.max_x = machine->screen[0].width - 1; + finalclip.min_y = 0; + finalclip.max_y = machine->screen[0].height - 1; + sect_rect(&finalclip, cliprect); + cliprect = &finalclip; + + // punt if not initialized + if (ygv608.page_x == 0 || ygv608.page_y == 0) + { + fillbitmap(bitmap, 0, cliprect); + return 0; + } + + if( ygv608.screen_resize ) + { +#ifdef _ENABLE_SCREEN_RESIZE + // hdw should be scaled by 16, not 8 + // - is it something to do with double dot-clocks??? + video_screen_set_visarea(0, 0, ((int)(ygv608.regs.s.hdw)<<3/*4*/)-1, + 0, ((int)(ygv608.regs.s.vdw)<<3)-1 ); +#endif + + if( work_bitmap ) + bitmap_free( work_bitmap ); + work_bitmap = bitmap_alloc( machine->screen[0].width, + machine->screen[0].height, machine->screen[0].format ); + + // reset resize flag + ygv608.screen_resize = 0; + } + + if( ygv608.tilemap_resize ) + { + int index; + + /* based on the page sizes, pick an index */ + if (ygv608.page_x == 64) + index = 1; + else if (ygv608.page_y == 64) + index = 2; + else + index = 0; + + if ((ygv608.regs.s.r9 & r9_pts) == PTS_8X8 ) + tilemap_A = tilemap_A_cache_8[index]; + else + tilemap_A = tilemap_A_cache_16[index]; + tilemap_mark_all_tiles_dirty(tilemap_A); + + tilemap_set_transparent_pen( tilemap_A, 0 ); + // for NCV1 it's sufficient to scroll only columns + tilemap_set_scroll_cols( tilemap_A, ygv608.page_x ); + + if ((ygv608.regs.s.r9 & r9_pts) == PTS_8X8 ) + tilemap_B = tilemap_B_cache_8[index]; + else + tilemap_B = tilemap_B_cache_16[index]; + tilemap_mark_all_tiles_dirty(tilemap_B); + + // for NCV1 it's sufficient to scroll only columns + tilemap_set_scroll_cols( tilemap_B, ygv608.page_x ); + + // now clear the screen in case we change to 1-plane mode + fillbitmap( work_bitmap, machine->pens[0], cliprect ); + + // reset resize flag + ygv608.tilemap_resize = 0; + } + +#ifdef _ENABLE_SCROLLY + + for( col=0; col<ygv608.page_x; col++ ) + { + tilemap_set_scrolly( tilemap_B, col, + ( (int)ygv608.scroll_data_table[1][(col>>ygv608.col_shift)<<1] + + ( (int)ygv608.scroll_data_table[1][((col>>ygv608.col_shift)<<1)+1] << 8 ) ) ); + + tilemap_set_scrolly( tilemap_A, col, + ( (int)ygv608.scroll_data_table[0][(col>>ygv608.col_shift)<<1] + + ( (int)ygv608.scroll_data_table[0][((col>>ygv608.col_shift)<<1)+1] << 8 ) ) ); + } + +#endif + +#ifdef _ENABLE_SCROLLX + + tilemap_set_scrollx( tilemap_B, 0, + ( (int)ygv608.scroll_data_table[1][0x80] + + ( (int)ygv608.scroll_data_table[1][0x81] << 8 ) ) ); + + tilemap_set_scrollx( tilemap_A, 0, + ( (int)ygv608.scroll_data_table[0][0x80] + + ( (int)ygv608.scroll_data_table[0][0x81] << 8 ) ) ); + +#endif + + tilemap_set_enable( tilemap_A, ygv608.regs.s.r7 & r7_dspe); + if((ygv608.regs.s.r7 & r7_md) & MD_1PLANE ) + tilemap_set_enable( tilemap_B, 0 ); + else + tilemap_set_enable( tilemap_B, ygv608.regs.s.r7 & r7_dspe); + + tilemap_mark_all_tiles_dirty( tilemap_A ); + tilemap_mark_all_tiles_dirty( tilemap_B ); + + + /* + * now we can render the screen + */ + +#if 1 + // LBO - need to implement proper pen marking for sprites as well as set aside a non-transparent + // pen to be used for background fills when plane B is disabled. + if ((ygv608.regs.s.r7 & r7_md) & MD_1PLANE) + { + // If the background tilemap is disabled, we need to clear the bitmap to black + fillbitmap (work_bitmap,machine->pens[0],cliprect); +// fillbitmap (work_bitmap,1,&machine->screen[0].visarea); + } + else +#endif + tilemap_draw( work_bitmap,cliprect, tilemap_B, 0, 0 ); + +#ifdef _ENABLE_ROTATE_ZOOM + + /* + * fudge - translate ax,ay to startx, starty each time + */ + + xc = ygv608.ax >> 16; + yc = ygv608.ay >> 16; + r = sqrt( (double)( xc * xc + yc * yc ) ); + alpha = atan( (double)xc / (double)yc ); + sin_theta = (double)ygv608.dyx / (double)0x10000; + cos_theta = (double)ygv608.dx / (double)0x10000; + + if( ygv608.regs.s.zron ) + copyrozbitmap( bitmap, work_bitmap, + ( machine->screen[0].visarea.min_x << 16 ) + + ygv608.ax + 0x10000 * r * + ( -sin( alpha ) * cos_theta + cos( alpha ) * sin_theta ), + ( machine->screen[0].visarea.min_y << 16 ) + + ygv608.ay + 0x10000 * r * + ( cos( alpha ) * cos_theta + sin( alpha ) * sin_theta ), + ygv608.dx, ygv608.dxy, ygv608.dyx, ygv608.dy, 0, + cliprect, + TRANSPARENCY_NONE, 0, 0 ); + else +#endif + copybitmap( bitmap, work_bitmap, 0, 0, 0, 0, + cliprect, + TRANSPARENCY_NONE, 0 ); + + // for some reason we can't use an opaque tilemap_A + // so use a transparent but clear the work bitmap first + // - look at why this is the case?!? + fillbitmap( work_bitmap, + machine->pens[0], + &machine->screen[0].visarea ); + + if ((ygv608.regs.s.r11 & r11_prm) == PRM_ASBDEX || + (ygv608.regs.s.r11 & r11_prm) == PRM_ASEBDX ) + draw_sprites(machine, bitmap,cliprect ); + + tilemap_draw( work_bitmap,cliprect, tilemap_A, 0, 0 ); + +#ifdef _ENABLE_ROTATE_ZOOM + if( ygv608.regs.s.zron ) + copyrozbitmap( bitmap, work_bitmap, + ygv608.ax, // + ( machine->screen[0].visarea.min_x << 16 ), + ygv608.ay, // + ( machine->screen[0].visarea.min_y << 16 ), + ygv608.dx, ygv608.dxy, ygv608.dyx, ygv608.dy, 0, + cliprect, + TRANSPARENCY_PEN, machine->pens[0], 0 ); + else +#endif + copybitmap( bitmap, work_bitmap, 0, 0, 0, 0, + cliprect, + TRANSPARENCY_PEN, machine->pens[0] ); + + if ((ygv608.regs.s.r11 & r11_prm) == PRM_SABDEX || + (ygv608.regs.s.r11 & r11_prm) == PRM_SEABDX) + draw_sprites(machine, bitmap,cliprect ); + + +#ifdef _SHOW_VIDEO_DEBUG + /* show screen control information */ + ui_draw_text( mode[(ygv608.regs.s.r7 & r7_md) >> 1], 0, 0 ); + sprintf( buffer, "%02ux%02u", ygv608.page_x, ygv608.page_y ); + ui_draw_text( buffer, 0, 16 ); + ui_draw_text( psize[(ygv608.regs.s.r9 & r9_pts) >> 6], 0, 32 ); + sprintf( buffer, "A: SX:%d SY:%d", + (int)ygv608.scroll_data_table[0][0x80] + + ( ( (int)ygv608.scroll_data_table[0][0x81] & 0x0f ) << 8 ), + (int)ygv608.scroll_data_table[0][0x00] + + ( ( (int)ygv608.scroll_data_table[0][0x01] & 0x0f ) << 8 ) ); + ui_draw_text( buffer, 0, 48 ); + sprintf( buffer, "B: SX:%d SY:%d", + (int)ygv608.scroll_data_table[1][0x80] + + ( ( (int)ygv608.scroll_data_table[1][0x81] & 0x0f ) << 8 ), + (int)ygv608.scroll_data_table[1][0x00] + + ( ( (int)ygv608.scroll_data_table[1][0x01] & 0x0f ) << 8 ) ); + ui_draw_text( buffer, 0, 64 ); +#endif + return 0; +} + +READ16_HANDLER( ygv608_r ) +{ + static int p0_state = 0; + static int p3_state = 0; + static int pattern_name_base = 0; /* pattern name table base address */ + int pn=0; + UINT16 data = 0; + + switch (offset) + { + case 0x00: /* P#0 - pattern name table data port */ + { + UINT8 xTile = ygv608.regs.s.r1 & r1_pnx; + UINT8 yTile = ygv608.regs.s.r0 & r0_pny; + + switch (p0_state) + { + case 0: + /* Are we reading from plane B? */ + if (!((ygv608.regs.s.r7 & r7_md) & MD_1PLANE) && (ygv608.regs.s.r0 & r0_b_a)) + pattern_name_base = ((ygv608.page_y << ygv608.pny_shift) << ygv608.bits16); + + /* read character from ram */ + pn = pattern_name_base + (((yTile << ygv608.pny_shift) + xTile) << ygv608.bits16); + break; + + case 1: + /* read character from ram */ + pn = pattern_name_base + (((yTile << ygv608.pny_shift) + xTile) << ygv608.bits16) + 1; + break; + } + + if (pn > 4095) + { + logerror( "attempt (%d) to read pattern name %d\n" + "mode = %d, pgs = %d (%dx%d)\n" + "pattern_name_base = %d\n" + "pnx = %d, pny = %d, pny_shift = %d, bits16 = %d\n", + p0_state, + pn, ygv608.regs.s.r7 & r7_md, ygv608.regs.s.r8 & r8_pgs, + ygv608.page_x, ygv608.page_y, + pattern_name_base, + xTile, yTile, ygv608.pny_shift, + ygv608.bits16 ); + pn = 0; + } + data = ygv608.pattern_name_table[pn]; + + p0_state++; + if ((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_8BIT ) + p0_state++; + + if (p0_state == 2) + { + if (ygv608.regs.s.r0 & r0_pnya) + { + if (yTile++ == (ygv608.page_y - 1)) + { + yTile = 0; + if (xTile++ == (ygv608.page_x - 1)) + { + xTile = 0; + // we're now off this tile plane, toggle planes + ygv608.regs.s.r0 ^= r0_b_a; + } + } + ygv608.regs.s.r0 &= ~r0_pny; + ygv608.regs.s.r0 |= yTile; + ygv608.regs.s.r1 &= ~r1_pnx; + ygv608.regs.s.r1 |= xTile; + } + else if (ygv608.regs.s.r1 & r1_pnxa) + { + if (xTile++ == (ygv608.page_x - 1)) + { + xTile = 0; + if (yTile++ == (ygv608.page_y - 1)) + { + yTile = 0; + // we're now off this tile plane, toggle planes + ygv608.regs.s.r0 ^= r0_b_a; + } + } + ygv608.regs.s.r0 &= ~r0_pny; + ygv608.regs.s.r0 |= yTile; + ygv608.regs.s.r1 &= ~r1_pnx; + ygv608.regs.s.r1 |= xTile; + } + p0_state = 0; + pattern_name_base = 0; + } + return (data << 8); + } + break; + + case 0x01: /* P#1 - sprite data port */ + data = ygv608.sprite_attribute_table.b[ygv608.regs.s.saa]; + if (ygv608.regs.s.r2 & r2_saar) + ygv608.regs.s.saa++; + return (data << 8); + break; + + case 0x02: /* P#2 - scroll data port */ + data = ygv608.scroll_data_table[(ygv608.regs.s.r2 & r2_b_a) >> 4][ygv608.regs.s.sca]; + if (ygv608.regs.s.r2 & r2_scar) + { + ygv608.regs.s.sca++; + /* handle wrap to next plane */ + if (ygv608.regs.s.sca == 0) + ygv608.regs.s.r2 ^= r2_b_a; + } + return( data << 8 ); + break; + + case 0x03: /* P#3 - color palette data port */ + data = ygv608.colour_palette[ygv608.regs.s.cc][p3_state]; + if( ++p3_state == 3 ) + { + p3_state = 0; + if( ygv608.regs.s.r2 & r2_cpar) + ygv608.regs.s.cc++; + } + return( data << 8 ); + break; + + case 0x04: /* P#4 - register data port */ + { + UINT8 regNum = (ygv608.ports.s.p5) & p5_rn; + data = ygv608.regs.b[regNum]; + if (ygv608.ports.s.p5 & p5_rrai) + { + regNum ++; + if (regNum == 50) + { + regNum = 0; + logerror( "warning: rn=50 after read increment\n" ); + } + ygv608.ports.s.p5 &= ~p5_rn; + ygv608.ports.s.p5 |= regNum; + } + return (data << 8); + } + break; + + case 0x05: + break; + + case 0x06: + case 0x07: + return( (UINT16)(ygv608.ports.b[offset]) << 8 ); + + default : + logerror( "unknown ygv608 register (%d)\n", offset ); + break; + } + + return( 0 ); +} + +WRITE16_HANDLER( ygv608_w ) +{ + static int p0_state = 0; + static int p3_state = 0; + static int pattern_name_base = 0; /* pattern name table base address */ + int pn=0; + + data = ( data >> 8 ) & 0xff; + + switch (offset) + { + case 0x00: /* P#0 - pattern name table data port */ + { + UINT8 xTile = ygv608.regs.s.r1 & r1_pnx; + UINT8 yTile = ygv608.regs.s.r0 & r0_pny; + + switch (p0_state) + { + case 0: + /* Are we reading from plane B? */ + if (!((ygv608.regs.s.r7 & r7_md) & MD_1PLANE) && (ygv608.regs.s.r0 & r0_b_a)) + pattern_name_base = ((ygv608.page_y << ygv608.pny_shift) << ygv608.bits16); + + /* read character from ram */ + pn = pattern_name_base + (((yTile << ygv608.pny_shift) + xTile) << ygv608.bits16); + break; + + case 1: + /* read character from ram */ + pn = pattern_name_base + (((yTile << ygv608.pny_shift) + xTile) << ygv608.bits16) + 1; + break; + } + + if (pn > 4095) + { + logerror( "attempt (%d) to read pattern name %d\n" + "mode = %d, pgs = %d (%dx%d)\n" + "pattern_name_base = %d\n" + "pnx = %d, pny = %d, pny_shift = %d, bits16 = %d\n", + p0_state, + pn, ygv608.regs.s.r7 & r7_md, ygv608.regs.s.r8 & r8_pgs, + ygv608.page_x, ygv608.page_y, + pattern_name_base, + xTile, yTile, ygv608.pny_shift, + ygv608.bits16 ); + pn = 0; + } + ygv608.pattern_name_table[pn] = data; + + p0_state++; + if ((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_8BIT ) + p0_state++; + + if (p0_state == 2) + { + if (ygv608.regs.s.r0 & r0_pnya) + { + if (yTile++ == (ygv608.page_y - 1)) + { + yTile = 0; + if (xTile++ == (ygv608.page_x - 1)) + { + xTile = 0; + ygv608.regs.s.r0 ^= r0_b_a; + } + } + ygv608.regs.s.r0 &= ~r0_pny; + ygv608.regs.s.r0 |= yTile; + ygv608.regs.s.r1 &= ~r1_pnx; + ygv608.regs.s.r1 |= xTile; + } + else if (ygv608.regs.s.r1 & r1_pnxa) + { + if (xTile++ == (ygv608.page_x - 1)) + { + xTile = 0; + if (yTile++ == (ygv608.page_y - 1)) + { + yTile = 0; + ygv608.regs.s.r0 ^= r0_b_a; + } + } + ygv608.regs.s.r0 &= ~r0_pny; + ygv608.regs.s.r0 |= yTile; + ygv608.regs.s.r1 &= ~r1_pnx; + ygv608.regs.s.r1 |= xTile; + } + p0_state = 0; + pattern_name_base = 0; + } + } + break; + + case 0x01: /* P#1 - sprite data port */ + ygv608.sprite_attribute_table.b[ygv608.regs.s.saa] = data; + if( ygv608.regs.s.r2 & r2_saaw) + ygv608.regs.s.saa++; + break; + + case 0x02: /* P#2 - scroll data port */ + ygv608.scroll_data_table[(ygv608.regs.s.r2 & r2_b_a) >> 4][ygv608.regs.s.sca] = data; + if (ygv608.regs.s.r2 & r2_scaw) + { + ygv608.regs.s.sca++; + /* handle wrap to next plane */ + if (ygv608.regs.s.sca == 0) + ygv608.regs.s.r2 ^= r2_b_a; + } + break; + + case 0x03: /* P#3 - colour palette data port */ + ygv608.colour_palette[ygv608.regs.s.cc][p3_state] = data; + if (++p3_state == 3) + { + p3_state = 0; + palette_set_color_rgb(Machine,ygv608.regs.s.cc, + pal6bit(ygv608.colour_palette[ygv608.regs.s.cc][0]), + pal6bit(ygv608.colour_palette[ygv608.regs.s.cc][1]), + pal6bit(ygv608.colour_palette[ygv608.regs.s.cc][2]) ); + if (ygv608.regs.s.r2 & r2_cpaw) + ygv608.regs.s.cc++; + } + break; + + case 0x04: /* P#4 - register data port */ + { + UINT8 regNum = (ygv608.ports.s.p5) & p5_rn; +#if 0 + logerror( "R#%d = $%02X\n", regNum, data ); +#endif + SetPreShortcuts (regNum, data); + ygv608.regs.b[regNum] = data; + SetPostShortcuts (regNum); + if (ygv608.ports.s.p5 & p5_rwai) + { + regNum ++; + if (regNum == 50) + { + regNum = 0; + logerror( "warning: rn=50 after write increment\n" ); + } + ygv608.ports.s.p5 &= ~p5_rn; + ygv608.ports.s.p5 |= regNum; + } + } + break; + + case 0x05: /* P#5 - register select port */ + ygv608.ports.b[5] = data; + break; + + case 0x06: /* P#6 - status port */ + /* writing a '1' resets that bit */ + ygv608.ports.b[6] &= ~data; + break; + + case 0x07: /* P#7 - system control port */ + ygv608.ports.b[7] = data; + if (ygv608.ports.b[7] & 0x3e) + HandleRomTransfers(); + if (ygv608.ports.b[7] & 0x01) + HandleYGV608Reset(); + break; + + default: + logerror( "unknown ygv608 register (%d)\n", offset ); + break; + } +} + +static void HandleYGV608Reset( void ) +{ + int i; + + /* Clear ports #0-7 */ + memset( &ygv608.ports.b[0], 0, 8 ); + + /* Clear registers #0-38, #47-49 */ + memset( &ygv608.regs.b[0], 0, 39 ); + memset( &ygv608.regs.b[47], 0, 3 ); + + /* Clear internal ram */ + memset( ygv608.pattern_name_table, 0, 4096 ); + memset( ygv608.sprite_attribute_table.b, 0, + YGV608_SPRITE_ATTR_TABLE_SIZE ); + memset( ygv608.scroll_data_table, 0, 2*256 ); + memset( ygv608.colour_palette, 0, 256*3 ); + + /* should set shortcuts here too */ + for( i=0; i<50; i++ ) { + //SetPreShortcuts( i ); + SetPostShortcuts( i ); + } +} + +/* + The YGV608 has a function to block-move data from the rom into + internal tables. This function is not used in NCV1, but I used + it for testing trojan ROM software. + - So leave it in! + */ + +static void HandleRomTransfers(void) +{ +#if 0 + static UINT8 *sdt = (UINT8 *)ygv608.scroll_data_table; + static UINT8 *sat = (UINT8 *)ygv608.sprite_attribute_table.b; + + /* fudge copy from sprite data for now... */ + UINT8 *RAM = Machine->memory_region[0]; + int i; + + int src = ( ( (int)ygv608.regs.s.tb13 << 8 ) + + (int)ygv608.regs.s.tb5 ) << 5; + int bytes = (int)ygv608.regs.s.tn4 << 4; + + logerror( "Transferring data from rom...\n" ); + + /* pattern name table */ + if( ygv608.ports.s.tn ) { + } + + /* scroll table */ + if( ygv608.ports.s.tl ) { + + int dest = (int)ygv608.regs.s.sca; + if( ygv608.regs.s.p2_b_a ) + dest += 0x100; + + /* fudge a transfer for now... */ + for( i=0; i<bytes; i++ ) { + sdt[(dest+i)%512] = RAM[src+(i^0x01)]; + + } + + /* flag as finished */ + ygv608.ports.s.tl = 0; + } + + /* sprite attribute table */ + if( ygv608.ports.s.ts ) { + + int dest = (int)ygv608.regs.s.saa; + + /* fudge a transfer for now... */ + for( i=0; i<bytes; i++ ) { + sat[(dest+i)%256] = RAM[src+(i^0x01)]; + + } + + /* flag as finished */ + ygv608.ports.s.ts = 0; + } +#endif +} + +#if 0 +void nvsram( offs_t offset, UINT16 data ) +{ + static int i = 0; + + data = ( data >> 8 ) & 0xff; + + if( 1 ) { + static char ascii[16]; + if( i%16 == 0 ) + logerror( "%04X: ", offset ); + logerror( "%02X ", data ); + ascii[i%16] = ( isprint( data ) ? data : '.' ); + if( i%16 == 15 ) + logerror( "| %-16.16s\n", ascii ); + } + + i++; +} +#endif + +// Set any "short-cut" variables before we update the YGV608 registers +// - these are used only in optimisation of the emulation + +static void SetPreShortcuts( int reg, int data ) +{ + switch( reg ) { + + case 7 : + if( ( ( data >> MD_SHIFT ) & MD_MASK ) != (ygv608.regs.s.r7 & r7_md)) + ygv608.tilemap_resize = 1; + break; + + case 8 : + if( ( ( data >> PGS_SHIFT ) & PGS_MASK ) != (ygv608.regs.s.r8 & r8_pgs)) + ygv608.tilemap_resize = 1; + break; + + case 9 : + if( ( ( data >> PTS_SHIFT ) & PTS_MASK ) != (ygv608.regs.s.r9 & r9_pts)) + ygv608.tilemap_resize= 1; + break; + + case 40 : + if( ( ( data >> HDW_SHIFT ) & HDW_MASK ) != (ygv608.regs.s.r40 & r40_hdw)) + ygv608.screen_resize = 1; + break; + + case 44 : + if( ( ( data >> VDW_SHIFT ) & VDW_MASK ) != (ygv608.regs.s.r44 & r44_vdw)) + ygv608.screen_resize = 1; + break; + } +} + +// Set any "short-cut" variables after we have updated the YGV608 registers +// - these are used only in optimisation of the emulation + +static void SetPostShortcuts( int reg ) +{ + int plane, addr; + + switch (reg) + { + case 0: + { + UINT8 yTile = ygv608.regs.s.r0 & r0_pny; + + if (yTile >= ygv608.page_y) + logerror ("setting pny(%d) >= page_y(%d) @ $%X\n", + yTile, ygv608.page_y, activecpu_get_pc() ); + yTile &= (ygv608.page_y - 1); + ygv608.regs.s.r0 &= ~r0_pny; + ygv608.regs.s.r0 |= yTile; + } + break; + + case 1: + { + UINT8 xTile = ygv608.regs.s.r1 & r1_pnx; + + if (xTile >= ygv608.page_x) + logerror ("setting pnx(%d) >= page_x(%d) @ $%X\n", + xTile, ygv608.page_x, activecpu_get_pc() ); + xTile &= (ygv608.page_x - 1); + ygv608.regs.s.r1 &= ~r1_pnx; + ygv608.regs.s.r1 |= xTile; + } + break; + + case 6: +#if 0 + logerror( "SBA = $%08X\n", (int)ygv608.regs.s.sba << 13 ); +#endif + break; + + case 7: + ygv608.na8_mask = ((ygv608.regs.s.r7 & r7_flip) ? 0x03 : 0x0f ); + /* fall thru */ + + case 8 : + ygv608.bits16 = ((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_8BIT ? 0 : 1 ); + if((ygv608.regs.s.r7 & r7_md) == MD_2PLANE_16BIT ) + ygv608.page_x = ygv608.page_y = 32; + else { + if ((ygv608.regs.s.r8 & r8_pgs) == 0 ) { + ygv608.page_x = 64; + ygv608.page_y = 32; + } + else { + ygv608.page_x = 32; + ygv608.page_y = 64; + } + } + ygv608.pny_shift = ( ygv608.page_x == 32 ? 5 : 6 ); + + /* bits to shift pattern y coordinate to extract base */ + ygv608.base_y_shift = ( ygv608.page_y == 32 ? 2 : 3 ); + + break; + + case 9 : + switch (ygv608.regs.s.r9 & r9_slv) + { + case SLV_SCREEN : + // always use scoll table entry #1 + ygv608.col_shift = 8; + break; + default : + if ((ygv608.regs.s.r9 & r9_pts) == PTS_8X8 ) + ygv608.col_shift = (ygv608.regs.s.r9 & r9_slv) - 4; + else + ygv608.col_shift = (ygv608.regs.s.r9 & r9_slv) - 5; + if( ygv608.col_shift < 0 ) + { + // we can't handle certain conditions + logerror( "Unhandled slv condition (pts=$%X,slv=$%X)\n", + ygv608.regs.s.r9 & r9_pts, ygv608.regs.s.r9 & r9_slv); + ygv608.col_shift = 8; + } + break; + } + + //if( ygv608.regs.s.slh != SLH_SCREEN ) + // logerror( "SLH = %1X\n", ygv608.regs.s.slh ); + break; + + case 11 : + //ShowYGV608Registers(); + break; + + case 17 : case 18 : case 19 : case 20 : + case 21 : case 22 : case 23 : case 24 : + plane = (reg-17) >> 2; + addr = ( (reg-17) << 1 ) & 0x07; + ygv608.base_addr[plane][addr] = ygv608.regs.b[reg] & 0x0f; + ygv608.base_addr[plane][addr+1] = ygv608.regs.b[reg] >> 4; + break; + + case 25 : case 26 : case 27 : + ygv608.ax = (int)(ygv608.regs.s.ax16 & 0x1f) << 16 | + (int)ygv608.regs.s.ax8 << 8 | + (int)ygv608.regs.s.ax0; + ygv608.ax <<= 7; + if( ygv608.ax & 0x08000000 ) ygv608.ax |= 0xf8000000; // 2s complement + //logerror( "ygv608.ax = $%X\n", ygv608.ax ); + break; + + case 28 : case 29 : + ygv608.dx = (int)(ygv608.regs.s.dx8 & 0x1f) << 8 | (int)ygv608.regs.s.dx0; + ygv608.dx <<= 7; + if( ygv608.dx & 0x00080000 ) ygv608.dx |= 0xfff80000; // 2s complement + break; + + case 30 : case 31 : + ygv608.dxy = (int)(ygv608.regs.s.dxy8 & 0x1f) << 8 | (int)ygv608.regs.s.dxy0; + ygv608.dxy <<= 7; + if( ygv608.dxy & 0x00080000 ) ygv608.dxy |= 0xfff80000; // 2s complement + break; + + case 32 : case 33 : case 34 : + ygv608.ay = (int)(ygv608.regs.s.ay16 & 0x1f) << 16 | + (int)ygv608.regs.s.ay8 << 8 | + (int)ygv608.regs.s.ay0; + ygv608.ay <<= 7; + if( ygv608.ay & 0x08000000 ) ygv608.ay |= 0xf8000000; // 2s complement + //logerror( "ygv608.ay = $%X\n", ygv608.ay ); + break; + + case 35 : case 36 : + ygv608.dy = (int)(ygv608.regs.s.dy8 & 0x1f) << 8 | (int)ygv608.regs.s.dy0; + ygv608.dy <<= 7; + if( ygv608.dy & 0x00080000 ) ygv608.dy |= 0xfff80000; // 2s complement + break; + + case 37 : case 38 : + ygv608.dyx = (int)(ygv608.regs.s.dyx8 & 0x1f) << 8 | (int)ygv608.regs.s.dyx0; + ygv608.dyx <<= 7; + if( ygv608.dyx & 0x00080000 ) ygv608.dyx |= 0xfff80000; // 2s complement + break; + + case 40 : case 41 : case 42 : + //ShowYGV608Registers(); + break; + + } + +} + +/* + * The rest of this stuff is for debugging only! + */ + +#ifdef MAME_DEBUG + +#define nSHOW_SOURCE_MODE + +#if 0 +void dump_block( char *name, UINT8 *block, int len ) +{ + int i; + + logerror( "UINT8 %s[] = {\n", name ); + for( i=0; i<len; i++ ) { + if( i%8 == 0 ) + logerror( " " ); + logerror( "0x%02X, ", block[i] ); + if( i%8 == 7 ) + logerror( "\n" ); + } + logerror( "};\n" ); +} +#endif +READ16_HANDLER( ygv608_debug_trigger ) +{ + static int oneshot = 0; + + int i; + char ascii[16]; + + if( oneshot ) + return( 0 ); + oneshot = 1; + + ShowYGV608Registers(); + +#ifdef SHOW_SOURCE_MODE +#if 0 + dump_block( "ygv608_regs", + (UINT8 *)ygv608.regs.b, + 64 ); + dump_block( "ygv608_pnt", + (UINT8 *)ygv608.pattern_name_table, + 4096 ); + dump_block( "ygv608_sat", + (UINT8 *)ygv608.sprite_attribute_table.b, + 256 ); + dump_block( "ygv608_sdt", + (UINT8 *)ygv608.scroll_data_table, + 512 ); + dump_block( "ygv608_cp", + (UINT8 *)ygv608.colour_palette, + 768 ); +#endif + +#else + + /* + * Dump pattern name table ram + */ +#if 1 + logerror( "Pattern Name Table\n" ); + for( i=0; i<4096; i++ ) { + if( i % 16 == 0 ) + logerror( "$%04X : ", i ); + logerror( "%02X ", ygv608.pattern_name_table[i] ); + if( isprint( ygv608.pattern_name_table[i] ) ) + ascii[i%16] = ygv608.pattern_name_table[i]; + else + ascii[i%16] = '.'; + if( i % 16 == 15 ) + logerror( " | %-16.16s\n", ascii ); + } + logerror( "\n" ); +#endif + + /* + * Dump scroll table ram + */ + + logerror( "Scroll Table\n" ); + for( i=0; i<512; i++ ) { + if( i % 16 == 0 ) + logerror( "$%04X : ", i ); + logerror( "%02X ", ygv608.scroll_data_table[0][i] ); + if( isprint( ygv608.scroll_data_table[0][i] ) ) + ascii[i%16] = ygv608.scroll_data_table[0][i]; + else + ascii[i%16] = '.'; + if( i % 16 == 15 ) + logerror( " | %-16.16s\n", ascii ); + } + logerror( "\n" ); + +#endif + + return( 0 ); +} + +void ShowYGV608Registers( void ) +{ + int p, b; + + logerror( "YGV608 Registers\n" ); + logerror( + "\tR#00: $%02X : PNYA(%d),B/A(%c),PNY(%d)\n", + ygv608.regs.b[0], + ygv608.regs.s.r0 & r0_pnya, + ((ygv608.regs.s.r0 & r0_b_a) ? 'B' : 'A' ), + ygv608.regs.s.r0 & r0_pny); + + logerror( + "\tR#01: $%02X : PNXA(%d),PNX(%d)\n", + ygv608.regs.b[1], + ygv608.regs.s.r1 & r1_pnxa, + ygv608.regs.s.r1 & r1_pnx); + + logerror( + "\tR#02: $%02X : CPAW(%d),CPAR(%d),B/A(%d),SCAW(%d),SCAR(%d),SAAW(%d),SAAR(%d)\n", + ygv608.regs.b[2], + ygv608.regs.s.r2 & r2_cpaw, + ygv608.regs.s.r2 & r2_cpar, + ygv608.regs.s.r2 & r2_b_a, + ygv608.regs.s.r2 & r2_scaw, + ygv608.regs.s.r2 & r2_scar, + ygv608.regs.s.r2 & r2_saaw, + ygv608.regs.s.r2 & r2_saar); + + logerror( + "\tR#03: $%02X : SAA($%02X)\n", + ygv608.regs.b[3], + ygv608.regs.s.saa ); + + logerror( + "\tR#04: $%02X : SCA($%02X)\n", + ygv608.regs.b[4], + ygv608.regs.s.sca ); + + logerror( + "\tR#05: $%02X : CC($%02X)\n", + ygv608.regs.b[5], + ygv608.regs.s.cc ); + + logerror( + "\tR#06: $%02X : SBA($%02X)\n", + ygv608.regs.b[6], + ygv608.regs.s.sba ); + + logerror( + "\tR#07: $%02X : DSPE(%d),MD(%d),ZRON(%d),FLIP(%d),DCKM(%d)\n", + ygv608.regs.b[7], + ygv608.regs.s.r7 & r7_dspe, + ygv608.regs.s.r7 & r7_md, + ygv608.regs.s.r7 & r7_zron, + ygv608.regs.s.r7 & r7_flip, + ygv608.regs.s.r7 & r7_dckm); + + logerror( + "\tR#08: $%02X : HDS(%d),VDS(%d),RLRT(%d),RLSC(%d),PGS(%d)\n", + ygv608.regs.b[8], + ygv608.regs.s.r8 & r8_hds, + ygv608.regs.s.r8 & r8_vds, + ygv608.regs.s.r8 & r8_rlrt, + ygv608.regs.s.r8 & r8_rlsc, + ygv608.regs.s.r8 & r8_pgs); + + logerror( + "\tR#11: $%02X : CTPA(%d),CTPB(%d),PRM(%d),CBDR(%d),YSE(%d),SCM(%d)\n", + ygv608.regs.b[11], + ygv608.regs.s.r11 & r11_ctpa, + ygv608.regs.s.r11 & r11_ctpb, + ygv608.regs.s.r11 & r11_prm, + ygv608.regs.s.r11 & r11_cbdr, + ygv608.regs.s.r11 & r11_yse, + ygv608.regs.s.r11 & r11_scm); + + logerror( + "\tR#40: $%02X : HTL9:8($%02X)=$%06X,HDW(%d)\n", + ygv608.regs.b[40], + ygv608.regs.s.r40 & r40_htl89, (int)(ygv608.regs.s.r40 & r40_htl89) << 8, + ygv608.regs.s.r40 & r40_hdw); + + logerror( + "\tR#41: $%02X : HDSP($%02X)\n", + ygv608.regs.b[41], + ygv608.regs.s.hdsp ); + + logerror( + "\tR#42: $%02X : HTL7:0($%02X)\n", + ygv608.regs.b[42], + ygv608.regs.s.htl ); + + logerror( + "\t HTL=$%03X\n", + ( (int)(ygv608.regs.s.r40 & r40_htl89) << 8 ) | + ( (int)ygv608.regs.s.htl ) ); + + logerror( + "\tR#47: $%02X : TB12:5($%02X) = $%06X\n", + ygv608.regs.b[47], + ygv608.regs.s.tb5, (int)ygv608.regs.s.tb5 << 5 ); + + logerror( + "\tR#48: $%02X : TB20:13($%02X) = $%06X\n", + ygv608.regs.b[48], + ygv608.regs.s.tb13, (int)ygv608.regs.s.tb13 << 13 ); + + logerror( + "\t TB=$%06X\n", + ( (int)ygv608.regs.s.tb13 << 13 ) | + ( (int)ygv608.regs.s.tb5 << 5 ) ); + + logerror( + "\tR#49: $%02X : TN11:4($%02X) = $%04X\n", + ygv608.regs.b[49], + ygv608.regs.s.tn4, (int)ygv608.regs.s.tn4 << 4 ); + + logerror( + "ShortCuts:\n" ); + + for( p=0; p<2; p++ ) { + logerror( "\t" ); + for( b=0; b<8; b++ ) { + logerror( "%02X ", ygv608.base_addr[p][b] ); + } + logerror( "\n" ); + } +} + +#endif // MAME_DEBUG |