summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author David Haywood <28625134+DavidHaywood@users.noreply.github.com>2021-11-22 13:02:24 +0000
committer GitHub <noreply@github.com>2021-11-22 08:02:24 -0500
commit22fd521abc969a2b4caeaea528d9febe402bd72c (patch)
treeace41151c26587aa92619ab6374d0195838c2cf8
parent73b6d39404afefa0ec26c9c0f701cfdb20bd977d (diff)
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
-rw-r--r--src/devices/sound/gaelco.cpp62
-rw-r--r--src/mame/drivers/gaelco.cpp47
-rw-r--r--src/mame/drivers/gaelco2.cpp22
-rw-r--r--src/mame/includes/gaelco.h10
-rw-r--r--src/mame/includes/gaelco2.h3
-rw-r--r--src/mame/video/gaelco.cpp72
-rw-r--r--src/mame/video/gaelco2.cpp154
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<int Layer> 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<unsigned Layer> TILE_GET_INFO_MEMBER(get_tile_info);
template<unsigned Layer> 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 */