// license:BSD-3-Clause // copyright-holders:Luca Elia /*************************************************************************** -= Unico Games =- driver by Luca Elia (l.elia@tin.it) Note: if MAME_DEBUG is defined, pressing Z with: Q / W / E Shows Layer 0 / 1 / 2 A Shows Sprites Keys can be used together! [ 3 Scrolling Layers ] Tile Size: 16 x 16 x 8 Layer Size (tiles): 64 x 64 [ 512 Sprites ] Sprites are made of 16 x 16 x 8 tiles. Size can vary from 1 to 16 tiles horizontally, while their height is always 1 tile. There seems to be 4 levels of priority (wrt layers) for each sprite, following this simple scheme: [if we denote the three layers with 0-3 (0 being the backmost) and the sprite with S] Sprite Priority Order (back -> front) 0 S 0 1 2 1 0 S 1 2 2 0 1 S 2 3 0 1 2 S ***************************************************************************/ #include "emu.h" #include "includes/unico.h" /*************************************************************************** Palette Byte: 0 1 2 3 Gun: R G B 0 6 Bits x Gun ***************************************************************************/ rgb_t unico_state::unico_R6G6B6X(uint32_t raw) { int const red = (raw >> 24) & 0xfc; int const green = (raw >> 16) & 0xfc; int const blue = (raw >> 8) & 0xfc; return rgb_t(red | (red >> 6), green | (green >> 6), blue | (blue >> 6)); } /*************************************************************************** Tilemaps Offset: Bits: Value: 0.w Code 2.w fedc ba98 7--- ---- ---- ---- -6-- ---- Flip Y ---- ---- --5- ---- Flip X ---- ---- ---4 3210 Color ***************************************************************************/ TILE_GET_INFO_MEMBER(unico_state::get_tile_info) { uint16_t *vram = (uint16_t *)tilemap.user_data(); uint16_t code = vram[2 * tile_index + 0 ]; uint16_t attr = vram[2 * tile_index + 1 ]; SET_TILE_INFO_MEMBER(1, code, attr & 0x1f, TILE_FLIPYX( attr >> 5 )); } READ16_MEMBER(unico_state::vram_r) { return m_vram[offset]; } WRITE16_MEMBER(unico_state::vram_w) { int tile = ((offset / 0x2000) + 1) % 3; COMBINE_DATA(&m_vram[offset]); m_tilemap[tile]->mark_tile_dirty((offset & 0x1fff)/2); } READ16_MEMBER(unico_state::scroll_r) { return m_scroll[offset]; } WRITE16_MEMBER(unico_state::scroll_w) { COMBINE_DATA(&m_scroll[offset]); } READ16_MEMBER(unico_state::spriteram_r) { return m_spriteram[offset]; } WRITE16_MEMBER(unico_state::spriteram_w) { COMBINE_DATA(&m_spriteram[offset]); } /*************************************************************************** Video Hardware Init ***************************************************************************/ void unico_state::video_start() { m_tilemap[0] = &machine().tilemap().create( *m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(unico_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16,16, 0x40, 0x40); m_tilemap[1] = &machine().tilemap().create( *m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(unico_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16,16, 0x40, 0x40); m_tilemap[2] = &machine().tilemap().create( *m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(unico_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16,16, 0x40, 0x40); m_tilemap[0]->set_user_data(&m_vram[0x8000/2]); m_tilemap[1]->set_user_data(&m_vram[0x0000/2]); m_tilemap[2]->set_user_data(&m_vram[0x4000/2]); m_sprites_scrolldx = -0x3f; m_sprites_scrolldy = -0x0e; m_tilemap[0]->set_scrolldx(-0x32,0); m_tilemap[1]->set_scrolldx(-0x30,0); m_tilemap[2]->set_scrolldx(-0x2e,0); m_tilemap[0]->set_scrolldy(-0x0f,0); m_tilemap[1]->set_scrolldy(-0x0f,0); m_tilemap[2]->set_scrolldy(-0x0f,0); m_tilemap[0]->set_transparent_pen(0x00); m_tilemap[1]->set_transparent_pen(0x00); m_tilemap[2]->set_transparent_pen(0x00); } /*************************************************************************** Sprites Drawing 0.w X 2.w Y 4.w Code 6.w fe-- ---- ---- ---- --dc ---- ---- ---- Priority ---- ba98 ---- ---- Number of tiles along X, minus 1 ---- ---- 7--- ---- ---- ---- -6-- ---- Flip Y? ---- ---- --5- ---- Flip X ---- ---- ---4 3210 Color ***************************************************************************/ void unico_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,const rectangle &cliprect) { int offs; /* Draw them backwards, for pdrawgfx */ for ( offs = (0x800-8)/2; offs >= 0 ; offs -= 8/2 ) { int x, startx, endx, incx; int sx = m_spriteram[ offs + 0 ]; int sy = m_spriteram[ offs + 1 ]; int code = m_spriteram[ offs + 2 ]; int attr = m_spriteram[ offs + 3 ]; int flipx = attr & 0x020; int flipy = attr & 0x040; // not sure int dimx = ((attr >> 8) & 0xf) + 1; int priority = ((attr >> 12) & 0x3); int pri_mask; switch( priority ) { case 0: pri_mask = 0xfe; break; // below all case 1: pri_mask = 0xf0; break; // above layer 0 case 2: pri_mask = 0xfc; break; // above layer 1 default: case 3: pri_mask = 0x00; // above all } sx += m_sprites_scrolldx; sy += m_sprites_scrolldy; sx = (sx & 0x1ff) - (sx & 0x200); sy = (sy & 0x1ff) - (sy & 0x200); if (flipx) { startx = sx+(dimx-1)*16; endx = sx-16; incx = -16; } else { startx = sx; endx = sx+dimx*16; incx = +16; } for (x = startx ; x != endx ; x += incx) { m_gfxdecode->gfx(0)->prio_transpen(bitmap,cliprect, code++, attr & 0x1f, flipx, flipy, x, sy, screen.priority(), pri_mask,0x00 ); } } } /*************************************************************************** Screen Drawing ***************************************************************************/ uint32_t unico_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int layers_ctrl = -1; m_tilemap[0]->set_scrollx(0, m_scroll[0x00]); m_tilemap[0]->set_scrolly(0, m_scroll[0x01]); m_tilemap[1]->set_scrollx(0, m_scroll[0x05]); m_tilemap[1]->set_scrolly(0, m_scroll[0x0a]); m_tilemap[2]->set_scrollx(0, m_scroll[0x04]); m_tilemap[2]->set_scrolly(0, m_scroll[0x02]); #ifdef MAME_DEBUG if ( machine().input().code_pressed(KEYCODE_Z) || machine().input().code_pressed(KEYCODE_X) ) { int msk = 0; if (machine().input().code_pressed(KEYCODE_Q)) msk |= 1; if (machine().input().code_pressed(KEYCODE_W)) msk |= 2; if (machine().input().code_pressed(KEYCODE_E)) msk |= 4; if (machine().input().code_pressed(KEYCODE_A)) msk |= 8; if (msk != 0) layers_ctrl &= msk; } #endif /* The background color is the first of the last palette */ bitmap.fill(0x1f00, cliprect); screen.priority().fill(0, cliprect); if (layers_ctrl & 1) m_tilemap[0]->draw(screen, bitmap, cliprect, 0,1); if (layers_ctrl & 2) m_tilemap[1]->draw(screen, bitmap, cliprect, 0,2); if (layers_ctrl & 4) m_tilemap[2]->draw(screen, bitmap, cliprect, 0,4); /* Sprites are drawn last, using pdrawgfx */ if (layers_ctrl & 8) draw_sprites(screen,bitmap,cliprect); return 0; }