From ff099562655d1d98bbe98f110d3352f64d5a21f6 Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 2 Sep 2021 16:37:31 +0900 Subject: video/toaplan_scu.cpp: Use single-pass priority drawing for sprites. (#8521) * Use single pass pdrawgfx for sprite vs tilemap priority. * Use device-specific delegate for priority mask. * Use device_video_interface to find screen. --- src/mame/drivers/toaplan1.cpp | 2 ++ src/mame/drivers/twincobr.cpp | 2 ++ src/mame/drivers/wardner.cpp | 2 ++ src/mame/includes/toaplan1.h | 1 + src/mame/includes/twincobr.h | 1 + src/mame/video/toaplan1.cpp | 35 +++++++++++++++--------- src/mame/video/toaplan_scu.cpp | 62 +++++++++++++++--------------------------- src/mame/video/toaplan_scu.h | 15 ++++++---- src/mame/video/twincobr.cpp | 54 ++++++++++++++++++++---------------- 9 files changed, 92 insertions(+), 82 deletions(-) diff --git a/src/mame/drivers/toaplan1.cpp b/src/mame/drivers/toaplan1.cpp index 0b34dbd6184..83a57dd7294 100644 --- a/src/mame/drivers/toaplan1.cpp +++ b/src/mame/drivers/toaplan1.cpp @@ -1969,8 +1969,10 @@ void toaplan1_rallybik_state::rallybik(machine_config &config) m_screen->screen_vblank().set(FUNC(toaplan1_rallybik_state::screen_vblank)); TOAPLAN_SCU(config, m_spritegen, 0); + m_spritegen->set_screen(m_screen); m_spritegen->set_palette(m_palette); m_spritegen->set_xoffsets(31, 15); + m_spritegen->set_pri_callback(FUNC(toaplan1_rallybik_state::pri_cb)); GFXDECODE(config, m_gfxdecode, m_palette, gfx_rallybik); PALETTE(config, m_palette).set_format(palette_device::xBGR_555, (64*16)+(64*16)); diff --git a/src/mame/drivers/twincobr.cpp b/src/mame/drivers/twincobr.cpp index 40f2d998445..17b2a24557f 100644 --- a/src/mame/drivers/twincobr.cpp +++ b/src/mame/drivers/twincobr.cpp @@ -688,8 +688,10 @@ void twincobr_state::twincobr(machine_config &config) crtc.set_char_width(2); TOAPLAN_SCU(config, m_spritegen, 0); + m_spritegen->set_screen(m_screen); m_spritegen->set_palette(m_palette); m_spritegen->set_xoffsets(31, 15); + m_spritegen->set_pri_callback(FUNC(twincobr_state::pri_cb)); BUFFERED_SPRITERAM16(config, m_spriteram16); diff --git a/src/mame/drivers/wardner.cpp b/src/mame/drivers/wardner.cpp index 8862a2c11ba..f40ae26dbd7 100644 --- a/src/mame/drivers/wardner.cpp +++ b/src/mame/drivers/wardner.cpp @@ -433,8 +433,10 @@ void wardner_state::wardner(machine_config &config) crtc.set_char_width(2); TOAPLAN_SCU(config, m_spritegen, 0); + m_spritegen->set_screen(m_screen); m_spritegen->set_palette(m_palette); m_spritegen->set_xoffsets(32, 14); + m_spritegen->set_pri_callback(FUNC(wardner_state::pri_cb)); BUFFERED_SPRITERAM8(config, m_spriteram8); diff --git a/src/mame/includes/toaplan1.h b/src/mame/includes/toaplan1.h index 69939380a22..c1092f814ef 100644 --- a/src/mame/includes/toaplan1.h +++ b/src/mame/includes/toaplan1.h @@ -178,6 +178,7 @@ private: DECLARE_WRITE_LINE_MEMBER(coin_lockout_1_w); DECLARE_WRITE_LINE_MEMBER(coin_lockout_2_w); u16 tileram_r(offs_t offset); + void pri_cb(u8 priority, u32 &pri_mask); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_WRITE_LINE_MEMBER(screen_vblank); diff --git a/src/mame/includes/twincobr.h b/src/mame/includes/twincobr.h index 7785d92d0c5..208281b9408 100644 --- a/src/mame/includes/twincobr.h +++ b/src/mame/includes/twincobr.h @@ -121,6 +121,7 @@ protected: void wardner_videoram_w(offs_t offset, u8 data); u8 wardner_sprite_r(offs_t offset); void wardner_sprite_w(offs_t offset, u8 data); + void pri_cb(u8 priority, u32 &pri_mask); TILE_GET_INFO_MEMBER(get_bg_tile_info); TILE_GET_INFO_MEMBER(get_fg_tile_info); TILE_GET_INFO_MEMBER(get_tx_tile_info); diff --git a/src/mame/video/toaplan1.cpp b/src/mame/video/toaplan1.cpp index a3ce5ddc52e..47d00a00064 100644 --- a/src/mame/video/toaplan1.cpp +++ b/src/mame/video/toaplan1.cpp @@ -229,7 +229,6 @@ void toaplan1_state::register_common() void toaplan1_rallybik_state::video_start() { - m_spritegen->alloc_sprite_bitmap(*m_screen); m_spritegen->gfx(0)->set_colorbase(64*16); create_tilemaps(); @@ -671,6 +670,18 @@ void toaplan1_state::log_vram() Sprite Handlers ***************************************************************************/ +void toaplan1_rallybik_state::pri_cb(u8 priority, u32 &pri_mask) +{ + switch (priority) + { + case 0: pri_mask = GFX_PMASK_1|GFX_PMASK_2|GFX_PMASK_4|GFX_PMASK_8; break; // disable? + case 1: pri_mask = GFX_PMASK_2|GFX_PMASK_4|GFX_PMASK_8; break; // over tilemap priority ~0x4, under tilemap priority 0x5~ + case 2: pri_mask = GFX_PMASK_4|GFX_PMASK_8; break; // over tilemap priority ~0x8, under tilemap priority 0x9~ + case 3: pri_mask = GFX_PMASK_8; break; // over tilemap priority ~0xc, under tilemap priority 0xd~ + } +} + + void toaplan1_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { u16 *source = (u16 *)m_buffered_spriteram.get(); @@ -744,26 +755,24 @@ u32 toaplan1_rallybik_state::screen_update(screen_device &screen, bitmap_rgb32 & { log_vram(); - m_spritegen->draw_sprites_to_tempbitmap(cliprect, m_buffered_spriteram.get(), m_spriteram.bytes()); + screen.priority().fill(0, cliprect); // first draw everything, including "disabled" tiles and priority 0 - m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 1); // then draw the higher priority layers in order for (int priority = 1; priority < 16; priority++) { - m_tilemap[3]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), 0); - m_tilemap[2]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), 0); - m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), 0); - m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), 0); - - //if (pririoty==0x00) m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,0); - if (priority==0x04) m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,1); - if (priority==0x08) m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,2); - if (priority==0x0c) m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,3); - + // get priority mask + // value: 0x1 (tilemap priority 0x0~0x4), 0x2 (tilemap priority 0x5~0x8), 0x4 (tilemap priority 0x9~0xc), 0x8 (tilemap priority 0xd~) + int primask = 1 << (((priority - 1) >> 2)); + m_tilemap[3]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), primask); + m_tilemap[2]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), primask); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), primask); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_CATEGORY(priority), primask); } + m_spritegen->draw_sprites(bitmap, cliprect, m_buffered_spriteram.get(), m_spriteram.bytes()); return 0; } diff --git a/src/mame/video/toaplan_scu.cpp b/src/mame/video/toaplan_scu.cpp index a7bb72c6e3b..815e8fc99aa 100644 --- a/src/mame/video/toaplan_scu.cpp +++ b/src/mame/video/toaplan_scu.cpp @@ -1,8 +1,8 @@ // license:BSD-3-Clause // copyright-holders:Quench /* Toaplan Sprite Controller 'SCU' - used by video/twincobr.c (including wardner) - and rallybik in toaplan1.c + used by video/twincobr.cpp (including wardner) + and rallybik in toaplan1.cpp */ @@ -32,31 +32,28 @@ GFXDECODE_END toaplan_scu_device::toaplan_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, TOAPLAN_SCU, tag, owner, clock) , device_gfx_interface(mconfig, *this, gfxinfo) + , device_video_interface(mconfig, *this) + , m_pri_cb(*this) { } void toaplan_scu_device::device_start() { + m_pri_cb.resolve(); } void toaplan_scu_device::device_reset() { } -void toaplan_scu_device::alloc_sprite_bitmap(screen_device &screen) -{ - screen.register_screen_bitmap(m_temp_spritebitmap); -} - /*************************************************************************** Sprite Handlers ***************************************************************************/ -void toaplan_scu_device::draw_sprites_to_tempbitmap(const rectangle &cliprect, u16* spriteram, u32 bytes) +template +void toaplan_scu_device::draw_sprites_common(BitmapClass &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes) { - m_temp_spritebitmap.fill(0, cliprect); - - for (int offs = 0; offs < bytes / 2; offs += 4) + for (int offs = (bytes / 2) - 4; offs >= 0; offs -= 4) { const u16 attribute = spriteram[offs + 1]; const int priority = (attribute & 0x0c00) >> 10; @@ -69,49 +66,34 @@ void toaplan_scu_device::draw_sprites_to_tempbitmap(const rectangle &cliprect, u { const u32 sprite = spriteram[offs] & 0x7ff; u32 color = attribute & 0x3f; - color |= priority << 6; // encode colour + u32 pri_mask = 0; // priority mask + if (!m_pri_cb.isnull()) + m_pri_cb(priority, pri_mask); int sx = spriteram[offs + 2] >> 7; const int flipx = attribute & 0x100; if (flipx) sx -= m_xoffs_flipped; const int flipy = attribute & 0x200; - gfx(0)->transpen_raw(m_temp_spritebitmap, cliprect, + gfx(0)->prio_transpen(bitmap, cliprect, sprite, - color << 4 /* << 4 because using _raw */ , + color, flipx, flipy, - sx - m_xoffs, sy - 16, 0); + sx - m_xoffs, sy - 16, screen().priority(), pri_mask, 0); } } - } -/*************************************************************************** - Draw the game screen in the given bitmap. -***************************************************************************/ - -void toaplan_scu_device::copy_sprites_from_tempbitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, int priority) +void toaplan_scu_device::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes) { - pen_t const *const pens = &palette().pen(gfx(0)->colorbase()); - - for (int y = cliprect.min_y; y <= cliprect.max_y; y++) - { - u16 const *const srcline = &m_temp_spritebitmap.pix(y); - u32 *const dstline = &bitmap.pix(y); + draw_sprites_common(bitmap, cliprect, spriteram, bytes); +} - for (int x = cliprect.min_x; x <= cliprect.max_x; x++) - { - const u16 pix = srcline[x]; - - if ((pix >> (4 + 6)) == priority) - { - if (pix & 0xf) - { - dstline[x] = pens[pix & 0x3ff]; - } - } - } - } +void toaplan_scu_device::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes) +{ + draw_sprites_common(bitmap, cliprect, spriteram, bytes); } + + diff --git a/src/mame/video/toaplan_scu.h b/src/mame/video/toaplan_scu.h index 4844f239af7..cbd9b0e9832 100644 --- a/src/mame/video/toaplan_scu.h +++ b/src/mame/video/toaplan_scu.h @@ -6,32 +6,35 @@ #pragma once - -class toaplan_scu_device : public device_t, public device_gfx_interface +class toaplan_scu_device : public device_t, public device_gfx_interface, public device_video_interface { public: toaplan_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + typedef device_delegate pri_cb_delegate; + // configuration void set_xoffsets(int xoffs, int xoffs_flipped) { m_xoffs = xoffs; m_xoffs_flipped = xoffs_flipped; } + template void set_pri_callback(T &&... args) { m_pri_cb.set(std::forward(args)...); } - void draw_sprites_to_tempbitmap(const rectangle &cliprect, u16* spriteram, u32 bytes); - void copy_sprites_from_tempbitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, int priority); - void alloc_sprite_bitmap(screen_device &screen); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes); + void draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes); protected: virtual void device_start() override; virtual void device_reset() override; private: + template void draw_sprites_common(BitmapClass &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes); + static const gfx_layout spritelayout; DECLARE_GFXDECODE_MEMBER(gfxinfo); - bitmap_ind16 m_temp_spritebitmap; + pri_cb_delegate m_pri_cb; int m_xoffs; int m_xoffs_flipped; }; diff --git a/src/mame/video/twincobr.cpp b/src/mame/video/twincobr.cpp index d6432cc3643..4159174a534 100644 --- a/src/mame/video/twincobr.cpp +++ b/src/mame/video/twincobr.cpp @@ -78,8 +78,6 @@ void twincobr_state::twincobr_create_tilemaps() void twincobr_state::video_start() { - m_spritegen->alloc_sprite_bitmap(*m_screen); - /* the video RAM is accessed via ports, it's not memory mapped */ m_txvideoram_size = 0x0800; m_bgvideoram_size = 0x2000; /* banked two times 0x1000 */ @@ -364,22 +362,21 @@ void twincobr_state::log_vram() } -u32 twincobr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +void twincobr_state::pri_cb(u8 priority, u32 &pri_mask) { - log_vram(); - - u16 *buffered_spriteram16; - u32 bytes; - if (m_spriteram16 != nullptr) - { - buffered_spriteram16 = m_spriteram16->buffer(); - bytes = m_spriteram16->bytes(); - } - else + switch (priority) { - buffered_spriteram16 = reinterpret_cast(m_spriteram8->buffer()); - bytes = m_spriteram8->bytes(); + case 0: pri_mask = GFX_PMASK_1|GFX_PMASK_2|GFX_PMASK_4; break; // disable? + case 1: pri_mask = GFX_PMASK_2|GFX_PMASK_4; break; // over background, under foreground/text + case 2: pri_mask = GFX_PMASK_4; break; // over background/foreground, under text + case 3: pri_mask = 0; break; // over everything } +} + + +u32 twincobr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + log_vram(); if (!m_display_on) { @@ -387,14 +384,25 @@ u32 twincobr_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, c } else { - m_spritegen->draw_sprites_to_tempbitmap(cliprect, buffered_spriteram16, bytes); - - m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE,0); - m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,1); - m_fg_tilemap->draw(screen, bitmap, cliprect, 0,0); - m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,2); - m_tx_tilemap->draw(screen, bitmap, cliprect, 0,0); - m_spritegen->copy_sprites_from_tempbitmap(bitmap,cliprect,3); + screen.priority().fill(0, cliprect); + + u16 *buffered_spriteram16; + u32 bytes; + if (m_spriteram16 != nullptr) + { + buffered_spriteram16 = m_spriteram16->buffer(); + bytes = m_spriteram16->bytes(); + } + else + { + buffered_spriteram16 = reinterpret_cast(m_spriteram8->buffer()); + bytes = m_spriteram8->bytes(); + } + + m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE,1); + m_fg_tilemap->draw(screen, bitmap, cliprect, 0,2); + m_tx_tilemap->draw(screen, bitmap, cliprect, 0,4); + m_spritegen->draw_sprites(bitmap, cliprect, buffered_spriteram16, bytes); } return 0; -- cgit v1.2.3