excellent/excellent_spr.cpp: Fix sprite delay and cleaned up code: (#13213)

* Implemented sprite RAM DMA triggered by vertical blanking.
* Use internal graphics decoding layout.
* Removed unused variables, reduced duplication and corrected comments.
* excellent/gcpinbal.cpp: Fixed background tilemap bank switching, simplified ROM loading, cleaned up code.
* excellent/aquarium.cpp: Cleaned up code.
This commit is contained in:
cam900 2025-01-20 00:11:07 +09:00 committed by GitHub
parent 60caa30360
commit 98e21bb678
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 119 additions and 94 deletions

View File

@ -243,7 +243,7 @@ uint32_t aquarium_state::screen_update(screen_device &screen, bitmap_ind16 &bitm
m_txt_tilemap->draw(screen, bitmap, cliprect, 1, 4);
m_bak_tilemap->draw(screen, bitmap, cliprect, 1, 8);
m_sprgen->aquarium_draw_sprites(screen, bitmap, cliprect, 16);
m_sprgen->aquarium_draw_sprites(screen, bitmap, cliprect);
m_mid_tilemap->draw(screen, bitmap, cliprect, 1, 0);
m_txt_tilemap->draw(screen, bitmap, cliprect, 0, 0);
@ -432,6 +432,7 @@ void aquarium_state::aquarium(machine_config &config)
m_screen->set_size(64*8, 64*8);
m_screen->set_visarea(2*8, 42*8-1, 2*8, 34*8-1);
m_screen->set_screen_update(FUNC(aquarium_state::screen_update));
m_screen->screen_vblank().set(m_sprgen, FUNC(excellent_spr_device::vblank));
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_aquarium);

View File

@ -19,15 +19,33 @@
#include "excellent_spr.h"
#include "screen.h"
#include <algorithm>
// 16x16x4
static gfx_layout layout_16x16x4 =
{
16,16, // 16*16 sprites
RGN_FRAC(1,1),
4, // 4 bits per pixel
// { 16, 48, 0, 32 },
{ 48, 16, 32, 0 },
{ STEP16(0,1) },
{ STEP16(0,16*4) },
16*16*4 // every sprite takes 128 consecutive bytes
};
GFXDECODE_MEMBER(excellent_spr_device::gfxinfo)
GFXDECODE_DEVICE(DEVICE_SELF, 0, layout_16x16x4, 0, 16)
GFXDECODE_END
DEFINE_DEVICE_TYPE(EXCELLENT_SPRITE, excellent_spr_device, "excellent_spr", "Excellent 8-bit Sprite")
excellent_spr_device::excellent_spr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, EXCELLENT_SPRITE, tag, owner, clock)
, device_gfx_interface(mconfig, *this, nullptr)
, device_gfx_interface(mconfig, *this)
, device_video_interface(mconfig, *this)
, m_colpri_cb(*this)
, m_gfx_region(*this, DEVICE_SELF)
, m_colbase(0)
{
}
@ -35,26 +53,15 @@ excellent_spr_device::excellent_spr_device(const machine_config &mconfig, const
void excellent_spr_device::device_start()
{
/* 16x16x4 */
gfx_layout layout_16x16x4 =
{
16,16, /* 16*16 sprites */
0,
4, /* 4 bits per pixel */
// { 16, 48, 0, 32 },
{ 48, 16, 32, 0 },
{ STEP16(0,1) },
{ STEP16(0,16*4) },
16*16*4 /* every sprite takes 128 consecutive bytes */
};
layout_16x16x4.total = m_gfx_region->bytes() / ((16*16*4) / 8);
decode_gfx(gfxinfo);
gfx(0)->set_colorbase(m_colbase);
m_colpri_cb.resolve();
m_ram = make_unique_clear<u8[]>(0x1000);
m_ram_buffered = make_unique_clear<u8[]>(0x1000);
save_pointer(NAME(m_ram), 0x1000);
set_gfx(0, std::make_unique<gfx_element>(&palette(), layout_16x16x4, m_gfx_region->base(), 0, 0x10, m_colbase));
save_pointer(NAME(m_ram_buffered), 0x1000);
}
@ -72,29 +79,35 @@ void excellent_spr_device::device_reset()
{
}
void excellent_spr_device::vblank(int state)
{
if (state)
std::copy_n(&m_ram[0], 0x1000, &m_ram_buffered[0]);
}
/****************************************************************
SPRITE DRAW ROUTINE
(8-bit)
Word | Bit(s) | Use
-----+-----------------+-----------------
0 | xxxxxxxx| X lo
1 | xxxxxxxx| X hi
2 | xxxxxxxx| Y lo
3 | xxxxxxxx| Y hi
4 | x.......| Disable
4 | ...x....| Flip Y
4 | ....x...| 1 = Y chain, 0 = X chain
4 | .....xxx| Chain size
5 | ??xxxxxx| Tile (low)
6 | xxxxxxxx| Tile (high)
7 | ....xxxx| Color Bank
Word | Bit(s) | Use
-----+----------+---------------------------
0 | xxxxxxxx | X lo
1 | xxxxxxxx | X hi
2 | xxxxxxxx | Y lo
3 | xxxxxxxx | Y hi
4 | x....... | Disable
4 | ..x..... | Flip X (aquarium)
4 | ...x.... | Flip Y
4 | ....x... | 1 = Y chain, 0 = X chain
4 | .....xxx | Chain size
5 | ??xxxxxx | Tile (low)
6 | xxxxxxxx | Tile (high)
7 | ....xxxx | Color Bank
****************************************************************/
void excellent_spr_device::aquarium_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int y_offs)
void excellent_spr_device::aquarium_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
const bool priority = !m_colpri_cb.isnull();
@ -104,33 +117,34 @@ void excellent_spr_device::aquarium_draw_sprites(screen_device &screen, bitmap_i
for (int offs = start; offs != end; offs += inc)
{
u32 code = ((m_ram[offs + 5]) & 0xff) + (((m_ram[offs + 6]) & 0xff) << 8);
code &= 0x3fff;
if (!(m_ram[offs + 4] & 0x80)) /* active sprite ? */
if (BIT(~m_ram_buffered[offs + 4], 7)) /* active sprite ? */
{
int x = ((m_ram[offs + 0]) & 0xff) + (((m_ram[offs + 1]) & 0xff) << 8);
int y = ((m_ram[offs + 2]) & 0xff) + (((m_ram[offs + 3]) & 0xff) << 8);
u32 code = ((m_ram_buffered[offs + 5]) & 0xff) + (((m_ram_buffered[offs + 6]) & 0xff) << 8);
code &= 0x3fff;
int x = ((m_ram_buffered[offs + 0]) & 0xff) + (((m_ram_buffered[offs + 1]) & 0xff) << 8);
int y = ((m_ram_buffered[offs + 2]) & 0xff) + (((m_ram_buffered[offs + 3]) & 0xff) << 8);
/* Treat coords as signed */
if (x & 0x8000) x -= 0x10000;
if (y & 0x8000) y -= 0x10000;
u32 pri_mask = 0;
u32 colour = ((m_ram[offs + 7]) & 0x0f);
const u8 chain = (m_ram[offs + 4]) & 0x07;
const bool flipy = (m_ram[offs + 4]) & 0x10;
const bool flipx = (m_ram[offs + 4]) & 0x20;
u32 colour = ((m_ram_buffered[offs + 7]) & 0x0f);
const u8 chain = (m_ram_buffered[offs + 4]) & 0x07;
const bool chaindir = BIT(m_ram_buffered[offs + 4], 3);
const bool flipy = BIT(m_ram_buffered[offs + 4], 4);
const bool flipx = BIT(m_ram_buffered[offs + 4], 5);
if (priority)
m_colpri_cb(colour, pri_mask);
int curx = x;
int cury = y;
if (((m_ram[offs + 4]) & 0x08) && flipy)
if (chaindir && flipy)
cury += (chain * 16);
if (!(((m_ram[offs + 4]) & 0x08)) && flipx)
if ((!chaindir) && flipx)
curx += (chain * 16);
for (int chain_pos = chain; chain_pos >= 0; chain_pos--)
@ -158,19 +172,21 @@ void excellent_spr_device::aquarium_draw_sprites(screen_device &screen, bitmap_i
code,
colour,
flipx, flipy,
curx,cury,0);
curx,cury,
0);
/* wrap around y */
gfx(0)->transpen(bitmap,cliprect,
code,
colour,
flipx, flipy,
curx,cury + 256,0);
curx,cury + 256,
0);
}
code++;
if ((m_ram[offs + 4]) & 0x08) /* Y chain */
if (chaindir) /* Y chain */
{
if (flipy)
cury -= 16;
@ -189,7 +205,7 @@ void excellent_spr_device::aquarium_draw_sprites(screen_device &screen, bitmap_i
}
}
void excellent_spr_device::gcpinbal_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int y_offs)
void excellent_spr_device::gcpinbal_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
const bool priority = !m_colpri_cb.isnull();
@ -199,22 +215,23 @@ void excellent_spr_device::gcpinbal_draw_sprites(screen_device &screen, bitmap_i
for (int offs = start; offs != end; offs += inc)
{
u32 code = ((m_ram[offs + 5]) & 0xff) + (((m_ram[offs + 6]) & 0xff) << 8);
code &= 0x3fff;
if (!(m_ram[offs + 4] & 0x80)) /* active sprite ? */
if (BIT(~m_ram_buffered[offs + 4], 7)) /* active sprite ? */
{
int x = ((m_ram[offs + 0]) & 0xff) + (((m_ram[offs + 1]) & 0xff) << 8);
int y = ((m_ram[offs + 2]) & 0xff) + (((m_ram[offs + 3]) & 0xff) << 8);
u32 code = ((m_ram_buffered[offs + 5]) & 0xff) + (((m_ram_buffered[offs + 6]) & 0xff) << 8);
code &= 0x3fff;
int x = ((m_ram_buffered[offs + 0]) & 0xff) + (((m_ram_buffered[offs + 1]) & 0xff) << 8);
int y = ((m_ram_buffered[offs + 2]) & 0xff) + (((m_ram_buffered[offs + 3]) & 0xff) << 8);
/* Treat coords as signed */
if (x & 0x8000) x -= 0x10000;
if (y & 0x8000) y -= 0x10000;
u32 pri_mask = 0;
u32 colour = ((m_ram[offs + 7]) & 0x0f);
const u8 chain = (m_ram[offs + 4]) & 0x07;
const bool flipy = (m_ram[offs + 4]) & 0x10;
u32 colour = ((m_ram_buffered[offs + 7]) & 0x0f);
const u8 chain = (m_ram_buffered[offs + 4]) & 0x07;
const bool chaindir = BIT(m_ram_buffered[offs + 4], 3);
const bool flipy = BIT(m_ram_buffered[offs + 4], 4);
const bool flipx = 0;
if (priority)
m_colpri_cb(colour, pri_mask);
@ -222,7 +239,7 @@ void excellent_spr_device::gcpinbal_draw_sprites(screen_device &screen, bitmap_i
int curx = x;
int cury = y;
if (((m_ram[offs + 4]) & 0x08) && flipy)
if (chaindir && flipy)
cury += (chain * 16);
for (int chain_pos = chain; chain_pos >= 0; chain_pos--)
@ -248,10 +265,12 @@ void excellent_spr_device::gcpinbal_draw_sprites(screen_device &screen, bitmap_i
code++;
if ((m_ram[offs + 4]) & 0x08) /* Y chain */
if (chaindir) /* Y chain */
{
if (flipy) cury -= 16;
else cury += 16;
if (flipy)
cury -= 16;
else
cury += 16;
}
else /* X chain */
{

View File

@ -18,19 +18,23 @@ public:
u8 read(offs_t offset);
void write(offs_t offset, u8 data);
void aquarium_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int y_offs);
void gcpinbal_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int y_offs);
void aquarium_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void gcpinbal_draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void vblank(int state);
protected:
std::unique_ptr<u8[]> m_ram;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
colpri_cb_delegate m_colpri_cb;
required_memory_region m_gfx_region;
u16 m_colbase;
std::unique_ptr<u8[]> m_ram;
std::unique_ptr<u8[]> m_ram_buffered;
// decoding info
DECLARE_GFXDECODE_MEMBER(gfxinfo);
};
DECLARE_DEVICE_TYPE(EXCELLENT_SPRITE, excellent_spr_device)

View File

@ -116,9 +116,6 @@ class gcpinbal_state : public driver_device
public:
gcpinbal_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_tilemapram(*this, "tilemapram")
, m_d80010_ram(*this, "d80010")
, m_d80060_ram(*this, "d80060")
, m_maincpu(*this, "maincpu")
, m_eeprom(*this, "eeprom")
, m_watchdog(*this, "watchdog")
@ -128,6 +125,9 @@ public:
, m_screen(*this, "screen")
, m_gfxdecode(*this, "gfxdecode")
, m_palette(*this, "palette")
, m_tilemapram(*this, "tilemapram")
, m_d80010_ram(*this, "d80010")
, m_d80060_ram(*this, "d80060")
{ }
void gcpinbal(machine_config &config);
@ -138,6 +138,17 @@ protected:
virtual void video_start() override ATTR_COLD;
private:
// devices
required_device<cpu_device> m_maincpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<mb3773_device> m_watchdog;
required_device<okim6295_device> m_oki;
required_device<es8712_device> m_essnd;
required_device<excellent_spr_device> m_sprgen;
required_device<screen_device> m_screen;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
// memory pointers
required_shared_ptr<u16> m_tilemapram;
required_shared_ptr<u16> m_d80010_ram;
@ -155,17 +166,6 @@ private:
// sound-related
u8 m_msm_bank = 0U;
// devices
required_device<cpu_device> m_maincpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<mb3773_device> m_watchdog;
required_device<okim6295_device> m_oki;
required_device<es8712_device> m_essnd;
required_device<excellent_spr_device> m_sprgen;
required_device<screen_device> m_screen;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
void d80010_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void d80040_w(offs_t offset, u8 data);
void d80060_w(offs_t offset, u16 data, u16 mem_mask = ~0);
@ -326,7 +326,7 @@ uint32_t gcpinbal_state::screen_update(screen_device &screen, bitmap_ind16 &bitm
#endif
m_tilemap[layer[2]]->draw(screen, bitmap, cliprect, 0, 4);
m_sprgen->gcpinbal_draw_sprites(screen, bitmap, cliprect, 16);
m_sprgen->gcpinbal_draw_sprites(screen, bitmap, cliprect);
return 0;
}
@ -373,34 +373,34 @@ void gcpinbal_state::d80060_w(offs_t offset, u16 data, u16 mem_mask)
void gcpinbal_state::bank_w(u8 data)
{
// MSM6585 bank, coin LEDs, maybe others?
if (m_msm_bank != ((data & 0x10) >> 4))
if (m_msm_bank != BIT(data, 4))
{
m_msm_bank = ((data & 0x10) >> 4);
m_msm_bank = BIT(data, 4);
m_essnd->set_rom_bank(m_msm_bank);
LOGESBANKSW("Bankswitching ES8712 ROM %02x\n", m_msm_bank);
}
m_oki->set_rom_bank((data & 0x20) >> 5);
m_oki->set_rom_bank(BIT(data, 5));
u32 old = m_bg_gfxset[0];
u32 newbank = (data & 0x04) ? 0x1000 : 0;
u32 newbank = BIT(data, 2) ? 0x1000 : 0;
if (old != newbank)
{
m_bg_gfxset[0] = (data & 0x04) ? 0x1000 : 0;
m_bg_gfxset[0] = BIT(data, 2) ? 0x1000 : 0;
m_tilemap[0]->mark_all_dirty();
}
old = m_bg_gfxset[1];
newbank = (data & 0x08) ? 0x1000 : 0;
newbank = BIT(data, 3) ? 0x1000 : 0;
if (old != newbank)
{
m_bg_gfxset[1] = (data & 0x04) ? 0x1000 : 0;
m_bg_gfxset[1] = BIT(data, 3) ? 0x1000 : 0;
m_tilemap[1]->mark_all_dirty();
}
m_watchdog->write_line_ck(BIT(data, 7));
// machine().bookkeeping().coin_lockout_w(0, ~data & 0x01);
// machine().bookkeeping().coin_lockout_w(1, ~data & 0x02);
// machine().bookkeeping().coin_lockout_w(0, BIT(~data, 0));
// machine().bookkeeping().coin_lockout_w(1, BIT(~data, 1));
}
void gcpinbal_state::eeprom_w(u8 data)
@ -589,6 +589,7 @@ void gcpinbal_state::gcpinbal(machine_config &config)
m_screen->set_size(40*8, 32*8);
m_screen->set_visarea(0*8, 40*8-1, 2*8, 30*8-1);
m_screen->set_screen_update(FUNC(gcpinbal_state::screen_update));
m_screen->screen_vblank().set(m_sprgen, FUNC(excellent_spr_device::vblank));
m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_gcpinbal);
@ -622,9 +623,9 @@ void gcpinbal_state::gcpinbal(machine_config &config)
***************************************************************************/
ROM_START( pwrflip ) // Updated version of Grand Cross Pinball or semi-sequel?
ROM_REGION( 0x200000, "maincpu", 0 ) // 68000
ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASE00 ) // 68000
ROM_LOAD16_WORD_SWAP( "p.f_1.33.u43", 0x000000, 0x80000, CRC(d760c987) SHA1(9200604377542193afc866c84733f2d3b5aa1c80) ) // hand written labels on genuine EXCELLENT labels
ROM_FILL ( 0x80000, 0x080000, 0x00 ) // unpopulated 27C4096 socket at U44
// unpopulated 27C4096 socket at U44
ROM_LOAD16_WORD_SWAP( "p.f.u45", 0x100000, 0x80000, CRC(6ad1a457) SHA1(8746c38efa05e3318e9b1a371470d149803fb6bb) )
ROM_LOAD16_WORD_SWAP( "p.f.u46", 0x180000, 0x80000, CRC(e0f3a1b4) SHA1(761dddf374a92c1a1e4a211ead215d5be461a082) )
@ -650,9 +651,9 @@ ROM_START( pwrflip ) // Updated version of Grand Cross Pinball or semi-sequel?
ROM_END
ROM_START( gcpinbal )
ROM_REGION( 0x200000, "maincpu", 0 ) // 68000
ROM_REGION( 0x200000, "maincpu", ROMREGION_ERASE00 ) // 68000
ROM_LOAD16_WORD_SWAP( "2_excellent.u43", 0x000000, 0x80000, CRC(d174bd7f) SHA1(0e6c17265e1400de941e3e2ca3be835aaaff6695) ) // Red line across label
ROM_FILL ( 0x80000, 0x080000, 0x00 ) // unpopulated 27C4096 socket at U44
// unpopulated 27C4096 socket at U44
ROM_LOAD16_WORD_SWAP( "3_excellent.u45", 0x100000, 0x80000, CRC(0511ad56) SHA1(e0602ece514126ce719ebc9de6649ebe907be904) )
ROM_LOAD16_WORD_SWAP( "4_excellent.u46", 0x180000, 0x80000, CRC(e0f3a1b4) SHA1(761dddf374a92c1a1e4a211ead215d5be461a082) )