// license:BSD-3-Clause // copyright-holders:Luca Elia,Paul Priest /*************************************************************************** -= Fuuki 16 Bit Games (FG-2) =- driver by Luca Elia (l.elia@tin.it) c.f. Fuuki FG-3 [ 4 Scrolling Layers ] [ Layer 0 ] [ Layer 1 ] [ Layers 2&3 (double-buffered) ] Tile Size: 16 x 16 x 4 16 x 16 x 8 8 x 8 x 4 Layer Size (tiles): 64 x 32 64 x 32 64 x 32 [ 1024? Zooming Sprites ] Sprites are made of 16 x 16 x 4 tiles. Size can vary from 1 to 16 tiles both horizontally and vertically. There is zooming (from full size to half size) and 4 levels of priority (wrt layers) * Note: the game does hardware assisted raster effects * ***************************************************************************/ #include "emu.h" #include "includes/fuukifg2.h" /*************************************************************************** Tilemaps Offset: Bits: Value: 0.w Code 2.w fedc ba98 ---- ---- ---- ---- 7--- ---- Flip Y ---- ---- -6-- ---- Flip X ---- ---- --54 3210 Color ***************************************************************************/ template TILE_GET_INFO_MEMBER(fuuki16_state::get_tile_info) { uint16_t code = m_vram[Layer][2 * tile_index + 0]; uint16_t attr = m_vram[Layer][2 * tile_index + 1]; SET_TILE_INFO_MEMBER((Layer < 2) ? (1 + Layer) : 3, code, attr & 0x3f, TILE_FLIPYX((attr >> 6) & 3)); } /*************************************************************************** Video Hardware Init ***************************************************************************/ /* Not used atm, seems to be fine without clearing pens? */ #if 0 PALETTE_INIT_MEMBER(fuuki16_state,fuuki16) { const uint8_t *color_prom = memregion("proms")->base(); int pen; /* The game does not initialise the palette at startup. It should be totally black */ for (pen = 0; pen < palette.entries(); pen++) palette.set_pen_color(pen,rgb_t(0,0,0)); } #endif void fuuki16_state::video_start() { m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(fuuki16_state::get_tile_info<0>),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(fuuki16_state::get_tile_info<1>),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); m_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(fuuki16_state::get_tile_info<2>),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_tilemap[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(fuuki16_state::get_tile_info<3>),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_tilemap[0]->set_transparent_pen(0x0f); // 4 bits m_tilemap[1]->set_transparent_pen(0xff); // 8 bits m_tilemap[2]->set_transparent_pen(0x0f); // 4 bits m_tilemap[3]->set_transparent_pen(0x0f); // 4 bits m_gfxdecode->gfx(2)->set_granularity(16); /* 256 colour tiles with palette selectable on 16 colour boundaries */ } /*************************************************************************** Screen Drawing Video Registers (vregs): 00.w Layer 0 Scroll Y 02.w Layer 0 Scroll X 04.w Layer 1 Scroll Y 06.w Layer 1 Scroll X 08.w Layer 2 Scroll Y 0a.w Layer 2 Scroll X 0c.w Layers Y Offset 0e.w Layers X Offset 10-1a.w ? 0 1c.w Trigger a level 5 irq on this raster line 1e.w ? $3390/$3393 (Flip Screen Off/On), $0040 is buffer for tilemap 2 or 3 Priority Register (priority): fedc ba98 7654 3--- ---- ---- ---- -210 Layer Order Unknown Registers (unknown): 00.w ? $0200/$0201 (Flip Screen Off/On) 02.w ? $f300/$0330 ***************************************************************************/ /* Wrapper to handle bg and bg2 ttogether */ void fuuki16_state::draw_layer( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int i, int flag, int pri ) { int buffer = (m_vregs[0x1e / 2] & 0x40); switch( i ) { case 2: m_tilemap[2|buffer]->draw(screen, bitmap, cliprect, flag, pri); return; case 1: m_tilemap[1]->draw(screen, bitmap, cliprect, flag, pri); return; case 0: m_tilemap[0]->draw(screen, bitmap, cliprect, flag, pri); return; } } uint32_t fuuki16_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { uint16_t layer0_scrollx, layer0_scrolly; uint16_t layer1_scrollx, layer1_scrolly; uint16_t layer2_scrollx, layer2_scrolly; uint16_t scrollx_offs, scrolly_offs; /* It's not independent bits causing layers to switch, that wouldn't make sense with 3 bits. See fuukifg3 for more justification */ static const int pri_table[6][3] = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 }}; int tm_front = pri_table[m_priority[0] & 0x0f][0]; int tm_middle = pri_table[m_priority[0] & 0x0f][1]; int tm_back = pri_table[m_priority[0] & 0x0f][2]; flip_screen_set(m_vregs[0x1e / 2] & 1); /* Layers scrolling */ scrolly_offs = m_vregs[0xc / 2] - (flip_screen() ? 0x103 : 0x1f3); scrollx_offs = m_vregs[0xe / 2] - (flip_screen() ? 0x2a7 : 0x3f6); layer0_scrolly = m_vregs[0x0 / 2] + scrolly_offs; layer0_scrollx = m_vregs[0x2 / 2] + scrollx_offs; layer1_scrolly = m_vregs[0x4 / 2] + scrolly_offs; layer1_scrollx = m_vregs[0x6 / 2] + scrollx_offs; layer2_scrolly = m_vregs[0x8 / 2]; layer2_scrollx = m_vregs[0xa / 2]; m_tilemap[0]->set_scrollx(0, layer0_scrollx); m_tilemap[0]->set_scrolly(0, layer0_scrolly); m_tilemap[1]->set_scrollx(0, layer1_scrollx); m_tilemap[1]->set_scrolly(0, layer1_scrolly); m_tilemap[2]->set_scrollx(0, layer2_scrollx + 0x10); m_tilemap[2]->set_scrolly(0, layer2_scrolly /*+ 0x02*/); m_tilemap[3]->set_scrollx(0, layer2_scrollx + 0x10); m_tilemap[3]->set_scrolly(0, layer2_scrolly /*+ 0x02*/); /* The backmost tilemap decides the background color(s) but sprites can go below the opaque pixels of that tilemap. We thus need to mark the transparent pixels of this layer with a different priority value */ // draw_layer(screen, bitmap, cliprect, tm_back, TILEMAP_DRAW_OPAQUE, 0); /* Actually, bg colour is simply the last pen i.e. 0x1fff -pjp */ bitmap.fill((0x800 * 4) - 1, cliprect); screen.priority().fill(0, cliprect); draw_layer(screen, bitmap, cliprect, tm_back, 0, 1); draw_layer(screen, bitmap, cliprect, tm_middle, 0, 2); draw_layer(screen, bitmap, cliprect, tm_front, 0, 4); m_fuukivid->draw_sprites(screen, bitmap, cliprect, flip_screen(), nullptr); return 0; }