// license:BSD-3-Clause // copyright-holders:Nicola Salmoria, Pierpaolo Prazzoli, Quench #include "emu.h" #include "includes/playmark.h" #include "screen.h" /*************************************************************************** Callbacks for the TileMap code ***************************************************************************/ TILE_GET_INFO_MEMBER(playmark_state::bigtwin_get_tx_tile_info) { u16 code = m_txtvideoram[2 * tile_index]; u16 color = m_txtvideoram[2 * tile_index + 1]; tileinfo.set(2, code, color, 0); } TILE_GET_INFO_MEMBER(playmark_state::bigtwin_get_fg_tile_info) { u16 code = m_fgvideoram[2 * tile_index]; u16 color = m_fgvideoram[2 * tile_index + 1]; tileinfo.set(1, code, color, 0); } TILE_GET_INFO_MEMBER(playmark_state::wbeachvl_get_tx_tile_info) { u16 code = m_txtvideoram[2 * tile_index]; u16 color = m_txtvideoram[2 * tile_index + 1]; tileinfo.set(2, code, (color >> 2), 0); } TILE_GET_INFO_MEMBER(playmark_state::wbeachvl_get_fg_tile_info) { u16 code = m_fgvideoram[2 * tile_index]; u16 color = m_fgvideoram[2 * tile_index + 1]; tileinfo.set(1, (code & 0x7fff), (color >> 2) + 8, (code & 0x8000) ? TILE_FLIPX : 0); } TILE_GET_INFO_MEMBER(playmark_state::wbeachvl_get_bg_tile_info) { u16 code = m_bgvideoram[2 * tile_index]; u16 color = m_bgvideoram[2 * tile_index + 1]; tileinfo.set(1, (code & 0x7fff), (color >> 2), (code & 0x8000) ? TILE_FLIPX : 0); } TILE_GET_INFO_MEMBER(playmark_state::hrdtimes_get_tx_tile_info) { int code = m_txtvideoram[tile_index] & 0x0fff; int colr = m_txtvideoram[tile_index] & 0xe000; tileinfo.set(3, code, (colr >> 13), 0); } TILE_GET_INFO_MEMBER(playmark_state::hrdtimes_get_fg_tile_info) { int code = m_fgvideoram[tile_index] & 0x1fff; int colr = m_fgvideoram[tile_index] & 0xe000; tileinfo.set(2, code, (colr >> 13) + 8, 0); } TILE_GET_INFO_MEMBER(playmark_state::hrdtimes_get_bg_tile_info) { int code = m_bgvideoram[tile_index] & 0x1fff; int colr = m_bgvideoram[tile_index] & 0xe000; tileinfo.set(1, code, (colr >> 13), 0); } TILE_GET_INFO_MEMBER(playmark_state::bigtwinb_get_tx_tile_info) { int code = m_txtvideoram[tile_index] & 0x0fff; int colr = m_txtvideoram[tile_index] & 0xf000; tileinfo.set(3, code, (colr >> 12), 0); } /*************************************************************************** Start the video hardware emulation. ***************************************************************************/ VIDEO_START_MEMBER(playmark_state,bigtwin) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::bigtwin_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::bigtwin_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_xoffset = 0; m_yoffset = 0; m_pri_masks[0] = 0; m_pri_masks[1] = 0; m_pri_masks[2] = 0; } VIDEO_START_MEMBER(playmark_state,bigtwinb) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::bigtwinb_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_fg_tilemap->set_transparent_pen(0); m_bg_tilemap->set_scrolldx(-4, -4); m_xoffset = 1; m_yoffset = 0; m_pri_masks[0] = 0; m_pri_masks[1] = 0; m_pri_masks[2] = 0; } VIDEO_START_MEMBER(playmark_state,wbeachvl) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::wbeachvl_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::wbeachvl_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::wbeachvl_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); m_tx_tilemap->set_transparent_pen(0); m_fg_tilemap->set_transparent_pen(0); m_xoffset = 0; m_yoffset = 0; m_pri_masks[0] = 0xfff0; m_pri_masks[1] = 0xfffc; m_pri_masks[2] = 0; } VIDEO_START_MEMBER(playmark_state,excelsr) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::bigtwin_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::bigtwin_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_xoffset = 0; m_yoffset = 0; m_pri_masks[0] = 0; m_pri_masks[1] = 0xfffc; m_pri_masks[2] = 0xfff0; } VIDEO_START_MEMBER(playmark_state,hotmind) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_fg_tilemap->set_transparent_pen(0); m_tx_tilemap->set_scrolldx(-14, -14); m_fg_tilemap->set_scrolldx(-14, -14); m_bg_tilemap->set_scrolldx(-14, -14); m_xoffset = -9; m_yoffset = -8; m_pri_masks[0] = 0xfff0; m_pri_masks[1] = 0xfffc; m_pri_masks[2] = 0; } VIDEO_START_MEMBER(playmark_state,luckboomh) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_fg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_fg_tilemap->set_transparent_pen(0); m_tx_tilemap->set_scrolldx( -9, -9); m_fg_tilemap->set_scrolldx(-11, -11); m_bg_tilemap->set_scrolldx(-13, -13); m_xoffset = -9; m_yoffset = -8; m_pri_masks[0] = 0xfff0; m_pri_masks[1] = 0xfffc; m_pri_masks[2] = 0; } // Hard Times level 2-4 boss(truck) needs this.. or something similar. #define TILES_PER_PAGE_Y (0x20) #define TILES_PER_PAGE_X (0x20) #define PAGES_PER_TMAP_Y (0x1) #define PAGES_PER_TMAP_X (0x4) TILEMAP_MAPPER_MEMBER(playmark_state::playmark_tilemap_scan_pages) { return (col / TILES_PER_PAGE_X) * TILES_PER_PAGE_Y * TILES_PER_PAGE_X * PAGES_PER_TMAP_Y + (col % TILES_PER_PAGE_X) + (row / TILES_PER_PAGE_Y) * TILES_PER_PAGE_Y * TILES_PER_PAGE_X + (row % TILES_PER_PAGE_Y) * TILES_PER_PAGE_X; } // there's enough ram for 64*128 on each tilemap.. VIDEO_START_MEMBER(playmark_state,hrdtimes) { m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_tx_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64); m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_fg_tile_info)), tilemap_mapper_delegate(*this, FUNC(playmark_state::playmark_tilemap_scan_pages)), 16, 16, 128, 32); m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(playmark_state::hrdtimes_get_bg_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tx_tilemap->set_transparent_pen(0); m_fg_tilemap->set_transparent_pen(0); m_tx_tilemap->set_scrolldx(-14, -14); m_fg_tilemap->set_scrolldx(-10, -10); m_bg_tilemap->set_scrolldx(-12, -12); m_xoffset = -8; m_yoffset = -8; m_pri_masks[0] = 0xfff0; m_pri_masks[1] = 0xfffc; m_pri_masks[2] = 0; } /*************************************************************************** Memory handlers ***************************************************************************/ void playmark_state::wbeachvl_txvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_txtvideoram[offset]); m_tx_tilemap->mark_tile_dirty(offset / 2); } void playmark_state::wbeachvl_fgvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_fgvideoram[offset]); m_fg_tilemap->mark_tile_dirty(offset / 2); } void playmark_state::wbeachvl_bgvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_bgvideoram[offset]); m_bg_tilemap->mark_tile_dirty(offset / 2); } void playmark_state::hrdtimes_txvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_txtvideoram[offset]); m_tx_tilemap->mark_tile_dirty(offset); } void playmark_state::hrdtimes_fgvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_fgvideoram[offset]); m_fg_tilemap->mark_tile_dirty(offset); } void playmark_state::hrdtimes_bgvideoram_w(offs_t offset, u16 data, u16 mem_mask) { COMBINE_DATA(&m_bgvideoram[offset]); m_bg_tilemap->mark_tile_dirty(offset); } void playmark_state::bigtwin_scroll_w(offs_t offset, u16 data, u16 mem_mask) { data = COMBINE_DATA(&m_scroll[offset]); switch (offset) { case 0: m_tx_tilemap->set_scrollx(0, data + 2); break; case 1: m_tx_tilemap->set_scrolly(0, data); break; case 2: m_bgscrollx = -(data + 4); break; case 3: m_bgscrolly = (-data) & 0x1ff; m_bg_enable = BIT(data, 9); m_bg_full_size = BIT(data, 10); break; case 4: m_fg_tilemap->set_scrollx(0, data + 6); break; case 5: m_fg_tilemap->set_scrolly(0, data); break; } } void playmark_state::wbeachvl_scroll_w(offs_t offset, u16 data, u16 mem_mask) { data = COMBINE_DATA(&m_scroll[offset]); switch (offset) { case 0: m_tx_tilemap->set_scrollx(0, data + 2); break; case 1: m_tx_tilemap->set_scrolly(0, data); break; case 2: m_fgscrollx = data + 4; break; case 3: m_fg_tilemap->set_scrolly(0, data & 0x3ff); m_fg_rowscroll_enable = BIT(data, 11); break; case 4: m_bg_tilemap->set_scrollx(0, data + 6); break; case 5: m_bg_tilemap->set_scrolly(0, data); break; } } void playmark_state::excelsr_scroll_w(offs_t offset, u16 data, u16 mem_mask) { data = COMBINE_DATA(&m_scroll[offset]); switch (offset) { case 0: m_tx_tilemap->set_scrollx(0, data + 2); break; case 1: m_tx_tilemap->set_scrolly(0, data); break; case 2: m_bgscrollx = -data; break; case 3: m_bgscrolly = (-data + 2) & 0x1ff; m_bg_enable = BIT(data, 9); m_bg_full_size = BIT(data, 10); break; case 4: m_fg_tilemap->set_scrollx(0, data + 6); break; case 5: m_fg_tilemap->set_scrolly(0, data); break; } } void playmark_state::hrdtimes_scroll_w(offs_t offset, u16 data, u16 mem_mask) { data = COMBINE_DATA(&m_scroll[offset]); switch (offset) { case 0: m_tx_tilemap->set_scrollx(0, data); break; case 1: m_tx_tilemap->set_scrolly(0, data); break; case 2: m_fg_tilemap->set_scrollx(0, data); break; case 3: m_fg_tilemap->set_scrolly(0, data); break; case 4: m_bg_tilemap->set_scrollx(0, data); break; case 5: m_bg_tilemap->set_scrolly(0, data); break; } } /*************************************************************************** Display refresh ***************************************************************************/ void playmark_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int codeshift ) { int offs, start_offset = m_spriteram.bytes() / 2 - 4; int height = m_gfxdecode->gfx(0)->height(); int colordiv = m_gfxdecode->gfx(0)->granularity() / 16; // find the "end of list" to draw the sprites in reverse order for (offs = 4; offs < m_spriteram.bytes() / 2; offs += 4) { if (m_spriteram[offs + 3 - 4] == 0x2000) // end of list marker { start_offset = offs - 4; break; } } for (offs = start_offset; offs >= 4; offs -= 4) { int sy = m_spriteram[offs + 3 - 4]; // -4? what the... ??? int flipx = sy & 0x4000; int sx = (m_spriteram[offs + 1] & 0x01ff) - 16 - 7; sy = (256 - 8 - height - sy) & 0xff; int code = m_spriteram[offs + 2] >> codeshift; int color = ((m_spriteram[offs + 1] & 0x3e00) >> 9) / colordiv; int pri = (m_spriteram[offs + 1] & 0x8000) >> 15; if(!pri && (color & 0x0c) == 0x0c) pri = 2; m_gfxdecode->gfx(0)->prio_transpen(bitmap,cliprect, code, color, flipx,0, sx + m_xoffset,sy + m_yoffset, screen.priority(),m_pri_masks[pri],m_sprtranspen); } } void playmark_state::bigtwinb_draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int codeshift ) { int offs, start_offset = m_spriteram.bytes() / 2 - 4; int height = m_gfxdecode->gfx(0)->height(); // find the "end of list" to draw the sprites in reverse order for (offs = 4; offs < m_spriteram.bytes() / 2; offs += 4) { if (m_spriteram[offs + 3 - 4] == 0x2000) // end of list marker { start_offset = offs - 4; break; } } for (offs = start_offset; offs >= 4; offs -= 4) { int sy = m_spriteram[offs + 3 - 4]; // -4? what the... ??? int flipx = sy & 0x4000; int sx = (m_spriteram[offs + 1] & 0x01ff) - 16 - 7; sy = (256 - 8 - height - sy) & 0xff; int code = m_spriteram[offs + 2] >> codeshift; int color = ((m_spriteram[offs + 1] & 0xf000) >> 12); m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, code, color, flipx,0, sx + m_xoffset,sy + m_yoffset, m_sprtranspen); } } void playmark_state::draw_bitmap( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect ) { int count = 0; for (int y = 0; y < 512; y++) { for (int x = 0; x < 512; x++) { int const color = m_bgvideoram[count] & 0xff; if (color) { if (m_bg_full_size) { bitmap.pix((y + m_bgscrolly) & 0x1ff, (x + m_bgscrollx) & 0x1ff) = 0x100 + color; u8 *const pri = &screen.priority().pix((y + m_bgscrolly) & 0x1ff); pri[(x + m_bgscrollx) & 0x1ff] |= 2; } else { // 50% size if(!(x % 2) && !(y % 2)) { bitmap.pix((y / 2 + m_bgscrolly) & 0x1ff, (x / 2 + m_bgscrollx) & 0x1ff) = 0x100 + color; u8 *const pri = &screen.priority().pix((y / 2 + m_bgscrolly) & 0x1ff); pri[(x / 2 + m_bgscrollx) & 0x1ff] |= 2; } } } count++; } } } u32 playmark_state::screen_update_bigtwin(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { screen.priority().fill(0, cliprect); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); if (m_bg_enable) draw_bitmap(screen, bitmap, cliprect); draw_sprites(screen, bitmap, cliprect, 4); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); return 0; } u32 playmark_state::screen_update_bigtwinb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { // video enabled if (m_scroll[6] & 1) { m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0); bigtwinb_draw_sprites(screen, bitmap, cliprect, 4); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); } else bitmap.fill(m_palette->black_pen(), cliprect); return 0; } u32 playmark_state::screen_update_excelsr(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { screen.priority().fill(0, cliprect); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 1); if (m_bg_enable) draw_bitmap(screen, bitmap, cliprect); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 4); draw_sprites(screen, bitmap, cliprect, 2); return 0; } u32 playmark_state::screen_update_wbeachvl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { if (m_fg_rowscroll_enable) { m_fg_tilemap->set_scroll_rows(512); for (int i = 0; i < 256; i++) m_fg_tilemap->set_scrollx(i + 1, m_rowscroll[8 * i]); } else { m_fg_tilemap->set_scroll_rows(1); m_fg_tilemap->set_scrollx(0, m_fgscrollx); } screen.priority().fill(0, cliprect); m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2); draw_sprites(screen, bitmap, cliprect, 0); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); return 0; } u32 playmark_state::screen_update_hrdtimes(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { screen.priority().fill(0, cliprect); // video enabled if (m_scroll[6] & 1) { m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 1); m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 2); draw_sprites(screen, bitmap, cliprect, 2); m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); } else bitmap.fill(m_palette->black_pen(), cliprect); return 0; }