// license:BSD-3-Clause // copyright-holders:Olivier Galibert #include "emu.h" #include "includes/taito_l.h" #include "screen.h" #include /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ template TILE_GET_INFO_MEMBER(taitol_state::get_tile_info) { int attr = m_vram[2 * tile_index + Offset + 1]; int code = m_vram[2 * tile_index + Offset] | ((attr & 0x03) << 8) | ((m_bankc[(attr & 0xc) >> 2]) << 10) | (m_horshoes_gfxbank << 12); SET_TILE_INFO_MEMBER(0, code, (attr & 0xf0) >> 4, 0); } TILE_GET_INFO_MEMBER(taitol_state::get_tx_tile_info) { int attr = m_vram[2 * tile_index + 0xa000 + 1]; int code = m_vram[2 * tile_index + 0xa000] | ((attr & 0x07) << 8); SET_TILE_INFO_MEMBER(2, code, (attr & 0xf0) >> 4, 0); } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ void taitol_state::video_start() { m_buff_spriteram = make_unique_clear(SPRITERAM_SIZE); m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(taitol_state::get_tile_info<0x8000>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(taitol_state::get_tile_info<0x9000>)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(taitol_state::get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_bg_tilemap[0]->set_transparent_pen(0); m_tx_tilemap->set_transparent_pen(0); m_tx_tilemap->set_scrolldx(-8, -8); m_bg_tilemap[0]->set_scrolldx(28, -11); m_bg_tilemap[1]->set_scrolldx(38, -21); save_pointer(NAME(m_buff_spriteram), SPRITERAM_SIZE); } /*************************************************************************** Memory handlers ***************************************************************************/ WRITE8_MEMBER(horshoes_state::bankg_w) { if (m_horshoes_gfxbank != data) { m_horshoes_gfxbank = data; for (int i = 0; i < 2; i++) m_bg_tilemap[i]->mark_all_dirty(); } } WRITE8_MEMBER(taitol_state::taitol_bankc_w) { if (m_bankc[offset] != data) { m_bankc[offset] = data; // logerror("Bankc %d, %02x (%s)\n", offset, data, m_maincpu->pc()); for (int i = 0; i < 2; i++) m_bg_tilemap[i]->mark_all_dirty(); } } READ8_MEMBER(taitol_state::taitol_bankc_r) { return m_bankc[offset]; } WRITE8_MEMBER(taitol_state::taitol_control_w) { // logerror("Control Write %02x (%s)\n", data, m_maincpu->pc()); m_cur_ctrl = data; //popmessage("%02x",data); /* bit 0 unknown */ /* bit 1 unknown */ /* bit 3 controls sprite/tile priority - handled in vh_screenrefresh() */ /* bit 4 flip screen */ m_flipscreen = data & 0x10; machine().tilemap().set_flip_all(m_flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0); /* bit 5 display enable - handled in vh_screenrefresh() */ } READ8_MEMBER(taitol_state::taitol_control_r) { // logerror("Control Read %02x (%s)\n", cur_ctrl, m_maincpu->pc()); return m_cur_ctrl; } WRITE8_MEMBER(taitol_state::vram_w) { // TODO : 0x10000-0x13fff Unused? if ((offset & 0xc000) == 0) return; if((m_vram[offset] & mem_mask) == (data & mem_mask)) return; COMBINE_DATA(&m_vram[offset]); m_gfxdecode->gfx(2)->mark_dirty(offset / 32); switch (offset & 0xf000) { case 0x8000: case 0x9000: m_bg_tilemap[(offset >> 12) & 1]->mark_tile_dirty((offset & 0xfff) / 2); break; case 0xa000: m_tx_tilemap->mark_tile_dirty((offset & 0xfff) / 2); break; } } /*************************************************************************** Display refresh ***************************************************************************/ /* Sprite format: 00: xxxxxxxx tile number (low) 01: xxxxxxxx tile number (high) 02: ----xxxx color ----x--- priority 03: -------x flip x ------x- flip y 04: xxxxxxxx x position (low) 05: -------x x position (high) 06: xxxxxxxx y position 07: xxxxxxxx unknown / ignored? Seems just garbage in many cases, e.g plgirs2 bullets and raimais big bosses. */ void taitol_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect ) { int offs; /* at spriteram + 0x3f0 and 03f8 are the tilemap control registers; spriteram + 0x3e8 seems to be unused */ for (offs = 0; offs < SPRITERAM_SIZE - 3 * 8; offs += 8) { int code, color, sx, sy, flipx, flipy; color = m_buff_spriteram[offs + 2] & 0x0f; code = m_buff_spriteram[offs] | (m_buff_spriteram[offs + 1] << 8); code |= (m_horshoes_gfxbank & 0x03) << 10; sx = m_buff_spriteram[offs + 4] | ((m_buff_spriteram[offs + 5] & 1) << 8); sy = m_buff_spriteram[offs + 6]; if (sx >= 320) sx -= 512; flipx = m_buff_spriteram[offs + 3] & 0x01; flipy = m_buff_spriteram[offs + 3] & 0x02; if (m_flipscreen) { sx = 304 - sx; sy = 240 - sy; flipx = !flipx; flipy = !flipy; } m_gfxdecode->gfx(1)->prio_transpen(bitmap,cliprect, code, color, flipx,flipy, sx,sy, screen.priority(), (color & 0x08) ? 0xaa : 0x00,0); } } uint32_t taitol_state::screen_update_taitol(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int dx, dy; dx = m_vram[0xb3f4] | (m_vram[0xb3f5] << 8); if (m_flipscreen) dx = ((dx & 0xfffc) | ((dx - 3) & 0x0003)) ^ 0xf; dy = m_vram[0xb3f6]; m_bg_tilemap[0]->set_scrollx(0, -dx); m_bg_tilemap[0]->set_scrolly(0, -dy); dx = m_vram[0xb3fc] | (m_vram[0xb3fd] << 8); if (m_flipscreen) dx = ((dx & 0xfffc) | ((dx - 3) & 0x0003)) ^ 0xf; dy = m_vram[0xb3fe]; m_bg_tilemap[1]->set_scrollx(0, -dx); m_bg_tilemap[1]->set_scrolly(0, -dy); if (m_cur_ctrl & 0x20) /* display enable */ { screen.priority().fill(0, cliprect); m_bg_tilemap[1]->draw(screen, bitmap, cliprect, 0, 0); if (m_cur_ctrl & 0x08) /* sprites always over BG1 */ m_bg_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0); else /* split priority */ m_bg_tilemap[0]->draw(screen, bitmap, cliprect, 0,1); draw_sprites(screen, bitmap, cliprect); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); } else bitmap.fill(m_palette->pen(0), cliprect); return 0; } WRITE_LINE_MEMBER(taitol_state::screen_vblank_taitol) { // rising edge if (state) { std::copy(&m_vram[0xb000], &m_vram[0xb000+SPRITERAM_SIZE], &m_buff_spriteram[0]); } }