/*************************************************************************** Video Hardware for some Technos games: Double Dragon, Double Dragon bootleg, Double Dragon II and China Gate Two Tile layers. Background layer is 512x512 , tiles are 16x16 Top layer is 256x256 , tiles are 8x8 Sprites are 16x16, 16x32, 32x16, or 32x32 (attribute bits set dimension) BG Tile Layout 0 1 ---- -xxx xxxx xxxx = Tile number --xx x--- ---- ---- = Color -x-- ---- ---- ---- = X Flip x--- ---- ---- ---- = Y Flip Top Tile layout. 0 1 ---- xxxx xxxx xxxx = Tile number xxxx ---- ---- ---- = Color (China Gate) xxx- ---- ---- ---- = Color (Double Dragon) Sprite layout. 0 1 2 3 4 ---- ---- ---- ---- ---- xxxx xxxx xxxx ---- ---- = Sprite number ---- ---- ---- ---- -xxx ---- ---- ---- ---- ---- = Color xxxx xxxx ---- ---- ---- ---- ---- ---- ---- ---- = Y position ---- ---- ---- ---x ---- ---- ---- ---- ---- ---- = Y MSb position ??? ---- ---- ---- ---- ---- ---- ---- ---- xxxx xxxx = X position ---- ---- ---- --x- ---- ---- ---- ---- ---- ---- = X MSb position ??? ---- ---- ---- -x-- ---- ---- ---- ---- ---- ---- = Y Flip ---- ---- ---- x--- ---- ---- ---- ---- ---- ---- = X Flip ---- ---- --xx ---- ---- ---- ---- ---- ---- ---- = Sprite Dimension ---- ---- x--- ---- ---- ---- ---- ---- ---- ---- = Visible ***************************************************************************/ #include "driver.h" UINT8 *ddragon_bgvideoram,*ddragon_fgvideoram; int ddragon_scrollx_hi, ddragon_scrolly_hi; UINT8 *ddragon_scrollx_lo; UINT8 *ddragon_scrolly_lo; UINT8 *ddragon_spriteram; int technos_video_hw; static tilemap *fg_tilemap,*bg_tilemap; /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ static TILEMAP_MAPPER( background_scan ) { /* logical (col,row) -> memory offset */ return (col & 0x0f) + ((row & 0x0f) << 4) + ((col & 0x10) << 4) + ((row & 0x10) << 5); } static TILE_GET_INFO( get_bg_tile_info ) { UINT8 attr = ddragon_bgvideoram[2*tile_index]; SET_TILE_INFO( 2, ddragon_bgvideoram[2*tile_index+1] + ((attr & 0x07) << 8), (attr >> 3) & 0x07, TILE_FLIPYX((attr & 0xc0) >> 6)); } static TILE_GET_INFO( get_fg_tile_info ) { UINT8 attr = ddragon_fgvideoram[2*tile_index]; SET_TILE_INFO( 0, ddragon_fgvideoram[2*tile_index+1] + ((attr & 0x07) << 8), attr >> 5, 0); } static TILE_GET_INFO( get_fg_16color_tile_info ) { UINT8 attr = ddragon_fgvideoram[2*tile_index]; SET_TILE_INFO( 0, ddragon_fgvideoram[2*tile_index+1] + ((attr & 0x0f) << 8), attr >> 4, 0); } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ VIDEO_START( ddragon ) { bg_tilemap = tilemap_create(get_bg_tile_info,background_scan, TILEMAP_TYPE_PEN, 16,16,32,32); fg_tilemap = tilemap_create(get_fg_tile_info,tilemap_scan_rows,TILEMAP_TYPE_PEN, 8, 8,32,32); tilemap_set_transparent_pen(fg_tilemap,0); } VIDEO_START( chinagat ) { bg_tilemap = tilemap_create(get_bg_tile_info,background_scan, TILEMAP_TYPE_PEN, 16,16,32,32); fg_tilemap = tilemap_create(get_fg_16color_tile_info,tilemap_scan_rows,TILEMAP_TYPE_PEN, 8, 8,32,32); tilemap_set_transparent_pen(fg_tilemap,0); } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE8_HANDLER( ddragon_bgvideoram_w ) { ddragon_bgvideoram[offset] = data; tilemap_mark_tile_dirty(bg_tilemap,offset/2); } WRITE8_HANDLER( ddragon_fgvideoram_w ) { ddragon_fgvideoram[offset] = data; tilemap_mark_tile_dirty(fg_tilemap,offset/2); } /*************************************************************************** Display refresh ***************************************************************************/ #define DRAW_SPRITE( order, sx, sy ) drawgfx( bitmap, gfx, \ (which+order),color,flipx,flipy,sx,sy, \ cliprect,TRANSPARENCY_PEN,0); static void draw_sprites(running_machine* machine, mame_bitmap *bitmap,const rectangle *cliprect) { const gfx_element *gfx = machine->gfx[1]; UINT8 *src; int i; if ( technos_video_hw == 1 ) { /* China Gate Sprite RAM */ src = (UINT8 *) (spriteram); } else { src = (UINT8 *) (&( ddragon_spriteram[0x800] )); } for( i = 0; i < ( 64 * 5 ); i += 5 ) { int attr = src[i+1]; if ( attr & 0x80 ) { /* visible */ int sx = 240 - src[i+4] + ( ( attr & 2 ) << 7 ); int sy = 240 - src[i+0] + ( ( attr & 1 ) << 8 ); int size = ( attr & 0x30 ) >> 4; int flipx = ( attr & 8 ); int flipy = ( attr & 4 ); int dx = -16,dy = -16; int which; int color; if ( technos_video_hw == 2 ) /* Double Dragon 2 */ { color = ( src[i+2] >> 5 ); which = src[i+3] + ( ( src[i+2] & 0x1f ) << 8 ); } else { if ( technos_video_hw == 1 ) /* China Gate */ { if ((sx < -7) && (sx > -16)) sx += 256; /* fix sprite clip */ if ((sy < -7) && (sy > -16)) sy += 256; /* fix sprite clip */ } color = ( src[i+2] >> 4 ) & 0x07; which = src[i+3] + ( ( src[i+2] & 0x0f ) << 8 ); } if (flip_screen) { sx = 240 - sx; sy = 240 - sy; flipx = !flipx; flipy = !flipy; dx = -dx; dy = -dy; } which &= ~size; switch ( size ) { case 0: /* normal */ DRAW_SPRITE( 0, sx, sy ); break; case 1: /* double y */ DRAW_SPRITE( 0, sx, sy + dy ); DRAW_SPRITE( 1, sx, sy ); break; case 2: /* double x */ DRAW_SPRITE( 0, sx + dx, sy ); DRAW_SPRITE( 2, sx, sy ); break; case 3: DRAW_SPRITE( 0, sx + dx, sy + dy ); DRAW_SPRITE( 1, sx + dx, sy ); DRAW_SPRITE( 2, sx, sy + dy ); DRAW_SPRITE( 3, sx, sy ); break; } } } } #undef DRAW_SPRITE VIDEO_UPDATE( ddragon ) { int scrollx = ddragon_scrollx_hi + *ddragon_scrollx_lo; int scrolly = ddragon_scrolly_hi + *ddragon_scrolly_lo; tilemap_set_scrollx(bg_tilemap,0,scrollx); tilemap_set_scrolly(bg_tilemap,0,scrolly); tilemap_draw(bitmap,cliprect,bg_tilemap,0,0); draw_sprites(machine, bitmap,cliprect); tilemap_draw(bitmap,cliprect,fg_tilemap,0,0); return 0; }