From 22fd521abc969a2b4caeaea528d9febe402bd72c Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Mon, 22 Nov 2021 13:02:24 +0000 Subject: CG-1V/GAE1 video/audio fixes (#8859) * CG-1V/GAE1 video/audio fixes - support y scroll in rowscroll mode - prevent shadow sprites from corrupting previously drawn shadow sprites - fix cases of samples not being played where the 2nd chunk addresses are written first - remove old hack to work around ancient MAME number of colour limits * Misc Gaelco improvements - fixed thoop, squash priorities - added IRQ acks - set Maniac Square prototype to 1992, and de-cloned it. I'm told this was an earlier project that was redone from scratch for the released game - demoted Thunder Hoop to NOT WORKING due to the stage 4 crash --- src/devices/sound/gaelco.cpp | 62 ++++++++++------- src/mame/drivers/gaelco.cpp | 47 +++++++++---- src/mame/drivers/gaelco2.cpp | 22 +++---- src/mame/includes/gaelco.h | 10 ++- src/mame/includes/gaelco2.h | 3 +- src/mame/video/gaelco.cpp | 72 +++++++++++++++++++- src/mame/video/gaelco2.cpp | 154 ++++++++++++++++++++++++++++++++++++++----- 7 files changed, 301 insertions(+), 69 deletions(-) diff --git a/src/devices/sound/gaelco.cpp b/src/devices/sound/gaelco.cpp index 31d294ee948..2fd45bfe6f9 100644 --- a/src/devices/sound/gaelco.cpp +++ b/src/devices/sound/gaelco.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Manuel Abadia +// copyright-holders:Manuel Abadia, David Haywood /*************************************************************************** Gaelco Sound Hardware @@ -215,35 +215,53 @@ void gaelco_gae1_device::gaelcosnd_w(offs_t offset, uint16_t data, uint16_t mem_ COMBINE_DATA(&m_sndregs[offset]); - switch(offset & 0x07) + switch (offset & 0x07) { - case 0x03: - /* trigger sound */ - if ((m_sndregs[offset - 1] != 0) && (data != 0)) + case 0x03: + // if sample end position isn't 0, and length isn't 0 + if ((m_sndregs[offset - 1] != 0) && (data != 0)) + { + LOG_SOUND(("(GAE1) Playing or Queuing 1st chunk in channel: %02d, type: %02x, bank: %02x, end: %08x, Length: %04x\n", offset >> 3, (m_sndregs[offset - 2] >> 4) & 0x0f, m_sndregs[offset - 2] & 0x03, m_sndregs[offset - 1] << 8, data)); + + channel->loop = 1; + + if (!channel->active) { - if (!channel->active) - { - channel->active = 1; - channel->chunkNum = 0; - channel->loop = 0; - LOG_SOUND(("(GAE1) Playing sample channel: %02d, type: %02x, bank: %02x, end: %08x, Length: %04x\n", offset >> 3, (m_sndregs[offset - 2] >> 4) & 0x0f, m_sndregs[offset - 2] & 0x03, m_sndregs[offset - 1] << 8, data)); - } + channel->chunkNum = 0; } - else - channel->active = 0; - break; + channel->active = 1; + } + else + { + //channel->loop = 0; + channel->active = 0; + } + + break; + + case 0x07: + // if sample end position isn't 0, and length isn't 0 + if ((m_sndregs[offset - 1] != 0) && (data != 0)) + { + LOG_SOUND(("(GAE1) Playing or Queuing 2nd chunk in channel: %02d, type: %02x, bank: %02x, end: %08x, Length: %04x\n", offset >> 3, (m_sndregs[offset - 2] >> 4) & 0x0f, m_sndregs[offset - 2] & 0x03, m_sndregs[offset - 1] << 8, data)); + + channel->loop = 1; - case 0x07: /* enable/disable looping */ - if ((m_sndregs[offset - 1] != 0) && (data != 0)) + if (!channel->active) { - LOG_SOUND(("(GAE1) Looping in channel: %02d, type: %02x, bank: %02x, end: %08x, Length: %04x\n", offset >> 3, (m_sndregs[offset - 2] >> 4) & 0x0f, m_sndregs[offset - 2] & 0x03, m_sndregs[offset - 1] << 8, data)); - channel->loop = 1; + channel->chunkNum = 1; } - else - channel->loop = 0; - break; + channel->active = 1; + } + else + { + channel->loop = 0; + // channel->active = 0; + } + + break; } } diff --git a/src/mame/drivers/gaelco.cpp b/src/mame/drivers/gaelco.cpp index d9aa3437ae4..68eeae20a7f 100644 --- a/src/mame/drivers/gaelco.cpp +++ b/src/mame/drivers/gaelco.cpp @@ -16,6 +16,19 @@ Year Game PCB NOTES 1995 Biomechanical Toy REF 922804/2 Unprotected 1996 Maniac Square REF 922804/2 Prototype +TODO: Figure out why Thunder Hoop crashes if you die on Level 4 + This can be bypassed by killing yourself at the same time as + the Level 3 boss dies, suggesting the end stage animation is + somehow corrupting the game state. Could this be a bug in + the supported revision of the game? It doesn't depend on + CPU clock, vblank timing, there are no unmapped reads or + writes of significance. Could it be related to a dipswitch + setting? + + Priorities for all games - the games don't make extensive + enough use of the priority scheme to properly draw any + conclusions. + ***************************************************************************/ #include "emu.h" @@ -64,6 +77,12 @@ void gaelco_state::oki_bankswitch_w(uint8_t data) m_okibank->set_entry(data & 0x0f); } +void gaelco_state::irqack_w(uint16_t data) +{ + // INT 6 ACK or Watchdog timer - written at the end of an IRQ + m_maincpu->set_input_line(6, CLEAR_LINE); +} + /*********** Squash Encryption Related Code ******************/ void gaelco_state::vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask) @@ -109,7 +128,7 @@ void gaelco_state::bigkarnk_map(address_map &map) map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::vram_w)).share("videoram"); // Video RAM map(0x102000, 0x103fff).ram(); // Screen RAM map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers -// map(0x10800c, 0x10800d).w("watchdog", FUNC(watchdog_timer_device::reset16_w)); // INT 6 ACK/Watchdog timer + map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette map(0x440000, 0x440fff).ram().share("spriteram"); // Sprite RAM map(0x700000, 0x700001).portr("DSW1"); @@ -138,7 +157,7 @@ void gaelco_state::maniacsq_map(address_map &map) map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::vram_w)).share("videoram"); // Video RAM map(0x102000, 0x103fff).ram(); // Screen RAM map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers -// map(0x10800c, 0x10800d).w("watchdog", FUNC(watchdog_timer_device::reset16_w)); // INT 6 ACK/Watchdog timer + map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette map(0x440000, 0x440fff).ram().share("spriteram"); // Sprite RAM map(0x700000, 0x700001).portr("DSW2"); @@ -156,7 +175,7 @@ void gaelco_state::squash_map(address_map &map) map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::vram_encrypted_w)).share("videoram"); // Video RAM map(0x102000, 0x103fff).ram().w(FUNC(gaelco_state::encrypted_w)).share("screenram"); // Screen RAM map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers -// map(0x10800c, 0x10800d).w("watchdog", FUNC(watchdog_timer_device::reset16_w)); // INT 6 ACK/Watchdog timer + map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette map(0x440000, 0x440fff).ram().share("spriteram"); // Sprite RAM map(0x700000, 0x700001).portr("DSW2"); @@ -175,7 +194,7 @@ void gaelco_state::thoop_map(address_map &map) map(0x100000, 0x101fff).ram().w(FUNC(gaelco_state::thoop_vram_encrypted_w)).share("videoram"); // Video RAM map(0x102000, 0x103fff).ram().w(FUNC(gaelco_state::thoop_encrypted_w)).share("screenram"); // Screen RAM map(0x108000, 0x108007).writeonly().share("vregs"); // Video Registers -// map(0x10800c, 0x10800d).w("watchdog", FUNC(watchdog_timer_device::reset16_w)); // INT 6 ACK/Watchdog timer + map(0x10800c, 0x10800d).w(FUNC(gaelco_state::irqack_w)); // INT 6 ACK/Watchdog timer map(0x200000, 0x2007ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette"); // Palette map(0x440000, 0x440fff).ram().share("spriteram"); // Sprite RAM map(0x700000, 0x700001).portr("DSW2"); @@ -641,7 +660,7 @@ void gaelco_state::bigkarnk(machine_config &config) // Basic machine hardware M68000(config, m_maincpu, XTAL(24'000'000)/2); // MC68000P10, 12 MHz? m_maincpu->set_addrmap(AS_PROGRAM, &gaelco_state::bigkarnk_map); - m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_hold)); + m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_assert)); MC6809E(config, m_audiocpu, XTAL(8'000'000)/4); // 68B09EP, 2 MHz? m_audiocpu->set_addrmap(AS_PROGRAM, &gaelco_state::bigkarnk_snd_map); @@ -684,7 +703,7 @@ void gaelco_state::maniacsq(machine_config &config) // Basic machine hardware M68000(config, m_maincpu, XTAL(24'000'000)/2); /* verified on pcb */ m_maincpu->set_addrmap(AS_PROGRAM, &gaelco_state::maniacsq_map); - m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_hold)); + m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_assert)); // Video hardware screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); @@ -713,7 +732,7 @@ void gaelco_state::squash(machine_config &config) // Basic machine hardware M68000(config, m_maincpu, XTAL(20'000'000)/2); // Verified on PCB m_maincpu->set_addrmap(AS_PROGRAM, &gaelco_state::squash_map); - m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_hold)); + m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_assert)); config.set_maximum_quantum(attotime::from_hz(600)); @@ -730,13 +749,13 @@ void gaelco_state::squash(machine_config &config) screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); screen.set_size(32*16, 32*16); screen.set_visarea(0, 320-1, 16, 256-1); - screen.set_screen_update(FUNC(gaelco_state::screen_update_maniacsq)); + screen.set_screen_update(FUNC(gaelco_state::screen_update_thoop)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco); PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 1024); - MCFG_VIDEO_START_OVERRIDE(gaelco_state,maniacsq) + MCFG_VIDEO_START_OVERRIDE(gaelco_state,squash) // Sound hardware SPEAKER(config, "mono").front_center(); @@ -751,7 +770,7 @@ void gaelco_state::thoop(machine_config &config) // Basic machine hardware M68000(config, m_maincpu, XTAL(24'000'000)/2); // Verified on PCB m_maincpu->set_addrmap(AS_PROGRAM, &gaelco_state::thoop_map); - m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_hold)); + m_maincpu->set_vblank_int("screen", FUNC(gaelco_state::irq6_line_assert)); config.set_maximum_quantum(attotime::from_hz(600)); @@ -768,13 +787,13 @@ void gaelco_state::thoop(machine_config &config) screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); screen.set_size(32*16, 32*16); screen.set_visarea(0, 320-1, 16, 256-1); - screen.set_screen_update(FUNC(gaelco_state::screen_update_maniacsq)); + screen.set_screen_update(FUNC(gaelco_state::screen_update_thoop)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco); PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 1024); - MCFG_VIDEO_START_OVERRIDE(gaelco_state,maniacsq) + MCFG_VIDEO_START_OVERRIDE(gaelco_state,bigkarnk) // Sound hardware SPEAKER(config, "mono").front_center(); @@ -1164,7 +1183,7 @@ GAME( 1995, biomtoya, biomtoy, maniacsq, biomtoy, gaelco_state, empty_init, RO GAME( 1995, biomtoyb, biomtoy, maniacsq, biomtoy, gaelco_state, empty_init, ROT0, "Gaelco", "Biomechanical Toy (Ver. 1.0.1878)", MACHINE_SUPPORTS_SAVE ) GAME( 1994, biomtoyc, biomtoy, maniacsq, biomtoyc, gaelco_state, empty_init, ROT0, "Gaelco", "Biomechanical Toy (Ver. 1.0.1870)", MACHINE_SUPPORTS_SAVE ) GAME( 1994, bioplayc, biomtoy, maniacsq, bioplayc, gaelco_state, empty_init, ROT0, "Gaelco", "Bioplaything Cop (Ver. 1.0.1823, prototype)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND ) // copyright based on Ver. 1.0.1870 -GAME( 1996, maniacsp, maniacsq, maniacsq, maniacsq, gaelco_state, empty_init, ROT0, "Gaelco", "Maniac Square (prototype)", MACHINE_SUPPORTS_SAVE ) // sometimes listed as a 1992 proto? +GAME( 1992, maniacsp, 0, maniacsq, maniacsq, gaelco_state, empty_init, ROT0, "Gaelco", "Maniac Square (prototype)", MACHINE_SUPPORTS_SAVE ) // The prototype version was an earlier project, said to be from 1992, game was rewritten in 1996 GAME( 1995, lastkm, 0, maniacsq, lastkm, gaelco_state, empty_init, ROT0, "Gaelco", "Last KM (Ver 1.0.0275)", MACHINE_SUPPORTS_SAVE ) // used on 'Salter' exercise bikes GAME( 1992, squash, 0, squash, squash, gaelco_state, empty_init, ROT0, "Gaelco", "Squash (Ver. 1.0)", MACHINE_SUPPORTS_SAVE ) -GAME( 1992, thoop, 0, thoop, thoop, gaelco_state, empty_init, ROT0, "Gaelco", "Thunder Hoop (Ver. 1, Checksum 02A09F7D)", MACHINE_SUPPORTS_SAVE ) // could be other versions, still Ver. 1 but different checksum listed on boot +GAME( 1992, thoop, 0, thoop, thoop, gaelco_state, empty_init, ROT0, "Gaelco", "Thunder Hoop (Ver. 1, Checksum 02A09F7D)", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING ) // could be other versions, still Ver. 1 but different checksum listed on boot diff --git a/src/mame/drivers/gaelco2.cpp b/src/mame/drivers/gaelco2.cpp index 21c9dbc28da..c0b17c8a2c5 100644 --- a/src/mame/drivers/gaelco2.cpp +++ b/src/mame/drivers/gaelco2.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Manuel Abadia +// copyright-holders:Manuel Abadia, David Haywood /*************************************************************************** Gaelco CG-1V/GAE1 based games @@ -194,7 +194,7 @@ void gaelco2_state::maniacsq(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -478,7 +478,7 @@ void gaelco2_state::saltcrdi(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -1010,7 +1010,7 @@ void gaelco2_state::play2000(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -1049,7 +1049,7 @@ void gaelco2_state::srollnd(machine_config& config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -1154,7 +1154,7 @@ void bang_state::bang(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -1399,7 +1399,7 @@ void gaelco2_state::alighunt(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -1750,7 +1750,7 @@ void gaelco2_state::touchgo(machine_config &config) /* video hardware */ BUFFERED_SPRITERAM16(config, m_spriteram); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); config.set_default_layout(layout_dualhsxs); screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER)); @@ -2069,7 +2069,7 @@ void gaelco2_state::snowboar(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -2113,7 +2113,7 @@ void gaelco2_state::maniacsqs(machine_config &config) screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); MCFG_VIDEO_START_OVERRIDE(gaelco2_state,gaelco2) @@ -2394,7 +2394,7 @@ void wrally2_state::wrally2(machine_config &config) /* video hardware */ BUFFERED_SPRITERAM16(config, m_spriteram); GFXDECODE(config, m_gfxdecode, m_palette, gfx_gaelco2); - PALETTE(config, m_palette).set_entries(4096*16 - 16); /* game's palette is 4096 but we allocate 15 more for shadows & highlights */ + PALETTE(config, m_palette).set_entries(0x10000); config.set_default_layout(layout_dualhsxs); screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER)); diff --git a/src/mame/includes/gaelco.h b/src/mame/includes/gaelco.h index 9dc3c9208de..487188b671a 100644 --- a/src/mame/includes/gaelco.h +++ b/src/mame/includes/gaelco.h @@ -26,7 +26,9 @@ public: m_videoram(*this, "videoram"), m_vregs(*this, "vregs"), m_spriteram(*this, "spriteram"), - m_screenram(*this, "screenram") { } + m_screenram(*this, "screenram"), + m_sprite_palette_force_high(0x38) + { } void bigkarnk(machine_config &config); void thoop(machine_config &config); @@ -62,15 +64,18 @@ private: void thoop_vram_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); void thoop_encrypted_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); void vram_w(offs_t offset, u16 data, u16 mem_mask); + void irqack_w(uint16_t data); template TILE_GET_INFO_MEMBER(get_tile_info); virtual void machine_start() override; DECLARE_VIDEO_START(bigkarnk); DECLARE_VIDEO_START(maniacsq); + DECLARE_VIDEO_START(squash); uint32_t screen_update_bigkarnk(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_maniacsq(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + uint32_t screen_update_thoop(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect ); void bigkarnk_map(address_map &map); @@ -79,4 +84,7 @@ private: void oki_map(address_map &map); void squash_map(address_map &map); void thoop_map(address_map &map); + + /* per-game configuration */ + uint8_t m_sprite_palette_force_high; }; diff --git a/src/mame/includes/gaelco2.h b/src/mame/includes/gaelco2.h index 7a8f8015b05..6a0d9a91285 100644 --- a/src/mame/includes/gaelco2.h +++ b/src/mame/includes/gaelco2.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Manuel Abadia +// copyright-holders:Manuel Abadia, David Haywood #include "cpu/m68000/m68000.h" #include "video/bufsprite.h" #include "machine/74259.h" @@ -81,6 +81,7 @@ private: void snowboar_protection_w(offs_t offset, u16 data, u16 mem_mask = ~0); template TILE_GET_INFO_MEMBER(get_tile_info); template TILE_GET_INFO_MEMBER(get_tile_info_dual); + int get_rowscrollmode_yscroll(bool first_screen); void draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int mask); u32 dual_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int index); void ROM16_split_gfx(const char *src_reg, const char *dst_reg, int start, int length, int dest1, int dest2); diff --git a/src/mame/video/gaelco.cpp b/src/mame/video/gaelco.cpp index 25ed14e98c2..4db6543e04e 100644 --- a/src/mame/video/gaelco.cpp +++ b/src/mame/video/gaelco.cpp @@ -6,6 +6,11 @@ Functions to emulate the video hardware of the machine + TODO: + verify priority implementations + understand bad sprites in Squash after the continue screen, these do not + occur on real hardware. + ***************************************************************************/ #include "emu.h" @@ -75,11 +80,23 @@ VIDEO_START_MEMBER(gaelco_state,bigkarnk) m_tilemap[1]->set_transmask(0, 0xff01, 0x00ff); // pens 1-7 opaque, pens 0, 8-15 transparent } +VIDEO_START_MEMBER(gaelco_state,squash) +{ + m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaelco_state::get_tile_info<0>)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); + m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaelco_state::get_tile_info<1>)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); + + m_tilemap[0]->set_transmask(0, 0xff01, 0x00ff); // pens 1-7 opaque, pens 0, 8-15 transparent + m_tilemap[1]->set_transmask(0, 0xff01, 0x00ff); // pens 1-7 opaque, pens 0, 8-15 transparent + + m_sprite_palette_force_high = 0x3c; +} + VIDEO_START_MEMBER(gaelco_state,maniacsq) { m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaelco_state::get_tile_info<0>)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gaelco_state::get_tile_info<1>)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); + // it is possible Maniac Square hardware also has more complex priority handling, but does not use it m_tilemap[0]->set_transparent_pen(0); m_tilemap[1]->set_transparent_pen(0); } @@ -131,13 +148,18 @@ void gaelco_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, co int yflip = attr & 0x40; int spr_size, pri_mask; - /* palettes 0x38-0x3f are used for high priority sprites in Big Karnak */ - if (color >= 0x38) + /* palettes 0x38-0x3f are used for high priority sprites in Big Karnak + the same logic in Squash causes player sprites to be drawn over the + pixels that form the glass play area. + + Is this accurate, or just exposing a different flaw in the priority + handling? */ + if (color >= m_sprite_palette_force_high) priority = 4; switch (priority) { - case 0: pri_mask = 0xff00; break; + case 0: pri_mask = 0xff00; break; // above everything? case 1: pri_mask = 0xff00 | 0xf0f0; break; case 2: pri_mask = 0xff00 | 0xf0f0 | 0xcccc; break; case 3: pri_mask = 0xff00 | 0xf0f0 | 0xcccc | 0xaaaa; break; @@ -202,6 +224,50 @@ uint32_t gaelco_state::screen_update_maniacsq(screen_device &screen, bitmap_ind1 return 0; } +uint32_t gaelco_state::screen_update_thoop(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + /* set scroll registers */ + m_tilemap[0]->set_scrolly(0, m_vregs[0]); + m_tilemap[0]->set_scrollx(0, m_vregs[1] + 4); + m_tilemap[1]->set_scrolly(0, m_vregs[2]); + m_tilemap[1]->set_scrollx(0, m_vregs[3]); + + screen.priority().fill(0, cliprect); + bitmap.fill(0, cliprect); + + // the priority handling differs from Big Karnak (or the Big Karnak implementation isn't correct) + // the games only make minimal use of the priority features. + + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 3, 0); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 3, 0); + + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 3, 0); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 3, 0); + + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 2, 1); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 2, 1); + + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 2, 1); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 2, 1); + + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 1, 2); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 1, 2); + + // sprites are sandwiched in here + + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 1, 4); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 1, 4); + + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 0, 8); + m_tilemap[1]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 0, 8); + + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1 | 0, 8); + m_tilemap[0]->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0 | 0, 8); + + draw_sprites(screen, bitmap, cliprect); + return 0; +} + uint32_t gaelco_state::screen_update_bigkarnk(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { /* set scroll registers */ diff --git a/src/mame/video/gaelco2.cpp b/src/mame/video/gaelco2.cpp index 26d8902f2cb..4f0cb75a76a 100644 --- a/src/mame/video/gaelco2.cpp +++ b/src/mame/video/gaelco2.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Manuel Abadia +// copyright-holders:Manuel Abadia, David Haywood /*************************************************************************** Gaelco Type CG-1V/GAE1 Video Hardware @@ -235,10 +235,6 @@ void gaelco2_state::palette_w(offs_t offset, u16 data, u16 mem_mask) /* update shadow/highlight palettes */ for (int i = 1; i < 16; i++) { - /* because the last palette entry is reserved for shadows and highlights, we - don't use it and that way we save some colors so the UI looks fine ;-) */ - if ((offset >= 0xff0) && (offset <= 0xfff)) return; - const u8 auxr = ADJUST_COLOR(r + pen_color_adjust[i]); const u8 auxg = ADJUST_COLOR(g + pen_color_adjust[i]); const u8 auxb = ADJUST_COLOR(b + pen_color_adjust[i]); @@ -393,18 +389,17 @@ void gaelco2_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, co { /* get a pointer to the current line in the screen bitmap */ const int ypos = ((sy + ey * 16 + py) & 0x1ff); - u16 *const srcy = &bitmap.pix(ypos); - - const int gfx_py = yflip ? (gfx->height() - 1 - py) : py; if ((ypos < cliprect.min_y) || (ypos > cliprect.max_y)) continue; + const int gfx_py = yflip ? (gfx->height() - 1 - py) : py; + u16 *const srcy = &bitmap.pix(ypos); + for (int px = 0; px < gfx->width(); px++) { /* get current pixel */ const int xpos = (((sx + ex * 16 + px) & 0x3ff) + spr_x_adjust) & 0x3ff; - u16 *const pixel = srcy + xpos; - const u16 src_color = *pixel; + if ((xpos < cliprect.min_x) || (xpos > cliprect.max_x)) continue; const int gfx_px = xflip ? (gfx->width() - 1 - px) : px; @@ -413,10 +408,11 @@ void gaelco2_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, co if ((gfx_pen == 0) || (gfx_pen >= 16)) continue; - if ((xpos < cliprect.min_x) || (xpos > cliprect.max_x)) continue; + u16 *const pixel = srcy + xpos; + const u16 src_color = *pixel; /* make background color darker or brighter */ - *pixel = src_color + 4096*gfx_pen; + *pixel = (src_color & 0xfff) | 0x1000*gfx_pen; } } } @@ -449,6 +445,7 @@ u32 gaelco2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co m_pant[0]->set_scrolly(0, scroll0y & 0x1ff); m_pant[1]->set_scrolly(0, scroll1y & 0x1ff); + /* set x linescroll registers */ for (int i = 0; i < 512; i++) { @@ -465,6 +462,132 @@ u32 gaelco2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co return 0; } + /* + The Y-scroll value in rowscroll mode has a very unusual implementation + the scroll value seems come from a 0x1000 bit being set in one of the + 512 rowscroll table entries. + + Only the bit representing the largest value is used? + + The ordering of the bits does not appear to be immediatley obvious. + + This is used in Touch & Go for the 'Super Spike' but we only scroll + 32 possible values, the entries used for the other scroll values + are unknown unless a pattern can be derived, or figured out from + the game code. + + _______________________________________ entry number + 1111 1111 1111 1111 + 0123 4567 89ab cdef 0123 4567 89ab cdef + _______________________________________ offset into linescroll ram + 0000 0000 0000 1111 1111 1111 1111 1111 + 6677 7888 8999 0001 1112 2233 3444 4555 + 5814 7036 9258 1470 3692 5814 7036 9258 + _______________________________________ + scr = expected scroll value if bit 0x1000 at offset is set + + scr (entry from above) + --x- ---- ---- ---- ---- ---- ---- ---- 32 (02) + ---- ---- ---- --x- ---- ---- ---- ---- 31 (0e) + ---- ---- --x- ---- ---- ---- ---- ---- 30 (0a) + ---- ---- ---- ---- ---- ---- ---x ---- 29 (1b) + ---- ---- ---- ---- ---- -x-- ---- ---- 28 (15) + ---- ---- ---- ---- ---x ---- ---- ---- 27 (13) + ---- x--- ---- ---- ---- ---- ---- ---- 26 (04) + ---- ---- ---- ---- ---- ---- -x-- ---- 25 (19) + ---- ---- ---- x--- ---- ---- ---- ---- 24 (0c) + ---- ---- ---- ---- ---- ---- ---- ---x 23 (1f) + ---- ---- x--- ---- ---- ---- ---- ---- 22 (08) + ---- ---- ---- ---- ---- ---- ---- -x-- 21 (1d) + ---- ---- ---- ---- -x-- ---- ---- ---- 20 (11) + ---- --x- ---- ---- ---- ---- ---- ---- 19 (06) + ---- ---- ---- ---- ---- ---x ---- ---- 18 (17) + ---- ---- ---- ---- x--- ---- ---- ---- 17 (10) + -x-- ---- ---- ---- ---- ---- ---- ---- 16 (01) + ---- ---- ---- -x-- ---- ---- ---- ---- 15 (0d) + ---- ---- ---- ---- ---- --x- ---- ---- 14 (16) + ---- ---- -x-- ---- ---- ---- ---- ---- 13 (09) + ---- ---- ---- ---- ---- ---- --x- ---- 12 (1a) + ---- -x-- ---- ---- ---- ---- ---- ---- 11 (05) + ---- ---- ---- ---- ---- ---- ---- --x- 10 (1e) + x--- ---- ---- ---- ---- ---- ---- ---- 9 (00) + ---- ---- ---- ---- --x- ---- ---- ---- 8 (12) + ---- ---- ---x ---- ---- ---- ---- ---- 7 (0b) + ---- ---- ---- ---- ---- x--- ---- ---- 6 (14) + ---x ---- ---- ---- ---- ---- ---- ---- 5 (03) + ---- ---- ---- ---- ---- ---- ---- x--- 4 (1c) + ---- ---- ---- ---- ---- ---- x--- ---- 3 (18) + ---- ---x ---- ---- ---- ---- ---- ---- 2 (07) + ---- ---- ---- ---x ---- ---- ---- ---- 1 (0f) + + ================================================== sorted list for reference + + x--- ---- ---- ---- ---- ---- ---- ---- 9 + -x-- ---- ---- ---- ---- ---- ---- ---- 16 + --x- ---- ---- ---- ---- ---- ---- ---- 32 + ---x ---- ---- ---- ---- ---- ---- ---- 5 + + ---- x--- ---- ---- ---- ---- ---- ---- 26 + ---- -x-- ---- ---- ---- ---- ---- ---- 11 + ---- --x- ---- ---- ---- ---- ---- ---- 19 + ---- ---x ---- ---- ---- ---- ---- ---- 2 + + ---- ---- x--- ---- ---- ---- ---- ---- 22 + ---- ---- -x-- ---- ---- ---- ---- ---- 13 + ---- ---- --x- ---- ---- ---- ---- ---- 30 + ---- ---- ---x ---- ---- ---- ---- ---- 7 + + ---- ---- ---- x--- ---- ---- ---- ---- 24 + ---- ---- ---- -x-- ---- ---- ---- ---- 15 + ---- ---- ---- --x- ---- ---- ---- ---- 31 + ---- ---- ---- ---x ---- ---- ---- ---- 1 + + ---- ---- ---- ---- x--- ---- ---- ---- 17 + ---- ---- ---- ---- -x-- ---- ---- ---- 20 + ---- ---- ---- ---- --x- ---- ---- ---- 8 + ---- ---- ---- ---- ---x ---- ---- ---- 27 + + ---- ---- ---- ---- ---- x--- ---- ---- 6 + ---- ---- ---- ---- ---- -x-- ---- ---- 28 + ---- ---- ---- ---- ---- --x- ---- ---- 14 + ---- ---- ---- ---- ---- ---x ---- ---- 18 + + ---- ---- ---- ---- ---- ---- x--- ---- 3 + ---- ---- ---- ---- ---- ---- -x-- ---- 25 + ---- ---- ---- ---- ---- ---- --x- ---- 12 + ---- ---- ---- ---- ---- ---- ---x ---- 29 + + ---- ---- ---- ---- ---- ---- ---- x--- 4 + ---- ---- ---- ---- ---- ---- ---- -x-- 21 + ---- ---- ---- ---- ---- ---- ---- --x- 10 + ---- ---- ---- ---- ---- ---- ---- ---x 23 + +*/ + +int gaelco2_state::get_rowscrollmode_yscroll(bool first_screen) +{ + uint16_t base = first_screen ? 0x2000 / 2 : 0x2400 / 2; + + uint8_t checkoffsets[32] = { + 0x02, 0x0e, 0x0a, 0x1b, 0x15, 0x13, 0x04, 0x19, + 0x0c, 0x1f, 0x08, 0x1d, 0x11, 0x06, 0x17, 0x10, + 0x01, 0x0d, 0x16, 0x09, 0x1a, 0x05, 0x1e, 0x00, + 0x12, 0x0b, 0x14, 0x03, 0x1c, 0x18, 0x07, 0x0f }; + + int usescroll = 0; + for (int i = 31; i >= 0; i--) + { + int checkoffset = (0x80 / 2) + ((checkoffsets[i] * 3) + 1); + + if (m_videoram[(base)+checkoffset] & 0x1000) + { + usescroll = 31 - i; + } + } + + return usescroll; +} + u32 gaelco2_state::dual_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int index) { int xoff0 = 0x14; // intro scenes align better with 0x13, but test screen is definitely 0x14 @@ -478,17 +601,14 @@ u32 gaelco2_state::dual_update(screen_device &screen, bitmap_ind16 &bitmap, cons int scroll0y = m_videoram[0x2800 / 2] + yoff0; int scroll1y = m_videoram[0x2804 / 2] + yoff1; - // if linescroll is enabled y-scroll handling changes too? - // touchgo uses 0x1f0 / 0x1ef between game and intro screens but actual scroll position needs to be different - // this aligns the crowd with the advertising boards if (m_vregs[0] & 0x8000) { - scroll0y += 32; + scroll0y += get_rowscrollmode_yscroll(true); } if (m_vregs[1] & 0x8000) { - scroll1y += 32; + scroll1y += get_rowscrollmode_yscroll(false); } /* set y scroll registers */ -- cgit v1.2.3