/* * 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 #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; iattr >> 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.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> 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