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
This commit is contained in:
David Haywood 2021-11-22 13:02:24 +00:00 committed by GitHub
parent 73b6d39404
commit 22fd521abc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 301 additions and 69 deletions

View File

@ -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;
}
case 0x07: /* enable/disable looping */
if ((m_sndregs[offset - 1] != 0) && (data != 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;
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;
}
}

View File

@ -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

View File

@ -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));

View File

@ -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;
};

View File

@ -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);

View File

@ -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 */

View File

@ -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 */