mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
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.
This commit is contained in:
parent
2c18661843
commit
ff09956265
@ -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));
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<class BitmapClass>
|
||||
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);
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
draw_sprites_common(bitmap, cliprect, spriteram, bytes);
|
||||
}
|
||||
|
||||
|
||||
void toaplan_scu_device::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, u16* spriteram, u32 bytes)
|
||||
{
|
||||
draw_sprites_common(bitmap, cliprect, spriteram, bytes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<void (u8 priority, u32 &pri_mask)> pri_cb_delegate;
|
||||
|
||||
// configuration
|
||||
void set_xoffsets(int xoffs, int xoffs_flipped)
|
||||
{
|
||||
m_xoffs = xoffs;
|
||||
m_xoffs_flipped = xoffs_flipped;
|
||||
}
|
||||
template <typename... T> void set_pri_callback(T &&... args) { m_pri_cb.set(std::forward<T>(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<class BitmapClass> 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;
|
||||
};
|
||||
|
@ -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,37 +362,47 @@ void twincobr_state::log_vram()
|
||||
}
|
||||
|
||||
|
||||
void twincobr_state::pri_cb(u8 priority, u32 &pri_mask)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
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();
|
||||
|
||||
u16 *buffered_spriteram16;
|
||||
u32 bytes;
|
||||
if (m_spriteram16 != nullptr)
|
||||
{
|
||||
buffered_spriteram16 = m_spriteram16->buffer();
|
||||
bytes = m_spriteram16->bytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffered_spriteram16 = reinterpret_cast<u16 *>(m_spriteram8->buffer());
|
||||
bytes = m_spriteram8->bytes();
|
||||
}
|
||||
|
||||
if (!m_display_on)
|
||||
{
|
||||
bitmap.fill(rgb_t::black(), cliprect);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_spritegen->draw_sprites_to_tempbitmap(cliprect, buffered_spriteram16, bytes);
|
||||
screen.priority().fill(0, cliprect);
|
||||
|
||||
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);
|
||||
u16 *buffered_spriteram16;
|
||||
u32 bytes;
|
||||
if (m_spriteram16 != nullptr)
|
||||
{
|
||||
buffered_spriteram16 = m_spriteram16->buffer();
|
||||
bytes = m_spriteram16->bytes();
|
||||
}
|
||||
else
|
||||
{
|
||||
buffered_spriteram16 = reinterpret_cast<u16 *>(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;
|
||||
|
Loading…
Reference in New Issue
Block a user