summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/clshroad.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/clshroad.cpp')
-rw-r--r--src/mame/drivers/clshroad.cpp119
1 files changed, 71 insertions, 48 deletions
diff --git a/src/mame/drivers/clshroad.cpp b/src/mame/drivers/clshroad.cpp
index e453e7e9044..596fca585df 100644
--- a/src/mame/drivers/clshroad.cpp
+++ b/src/mame/drivers/clshroad.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Luca Elia
-/***************************************************************************
+/******************************************************************************
-= Clash Road =-
@@ -12,26 +12,33 @@ Video Chips : ?
Sound CPU : Z80A (LH0080A)
-Sound Chips : Custom (NAMCO)
+Sound Chips : Custom (Nichibutsu?)
XTAL : 18.432 MHz
TODO:
-- few unused video registers (2 and 3);
-- clshroad: erratic gameplay speed;
+- clshroad: erratic gameplay/sound speed.
+ Being pretty logical that CPUs runs at master clock / 6 then we also need to
+ halve the vblank irq rate so that opponents won't pop up in the middle of the
+ screen. Main CPU would also overrun the sound CPU way too much otherwise.
+ We also need to hand tune the sound frequencies compared to the other games
+ so that it won't cut off BGMs abruptly during playback.
+ TL;DR needs verification of all clocks with a PCB;
- firebatl: video (https://tmblr.co/ZgJvzv2E2C_z-) shows transparency for the
- text layer is not correctly emulated, fixed by initializing VRAM to 0xf0? (that layer seems unused by this game);
-- firebatl: bad sprite colors;
+ text layer is not correctly emulated, fixed by initializing VRAM to 0xf0?
+ (that layer seems unused by this game);
+- firebatl: bad sprite colors, most notably player ship (should be way darker);
- firebatl: remove ROM patch;
-- firebatl: reads $6000-$6002 and $6100 at POST, and in the range $6100-$61ff before every start
- of gameplay/after player dies.
+- firebatl: reads $6000-$6002 and $6100 at POST, and in the range $6100-$61ff
+ before every start of gameplay/after player dies.
Currently 0-filled in ROM loading:
- $6100 is actually OR-ed with the coinage work RAM buffer setting at $8022;
- - $6124 is shifted right once at PC=0x5df and stored to $82e6, which is later checked at PC=0x187 and must
- be $01 otherwise game goes into an infinite loop after dying (without ROM patch);
+ - $6124 is shifted right once at PC=0x5df and stored to $82e6, which is later
+ checked at PC=0x187 and must be $01 otherwise game goes into an infinite
+ loop after dying (without ROM patch);
- (more ...)
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "includes/clshroad.h"
@@ -39,11 +46,16 @@ TODO:
#include "cpu/z80/z80.h"
#include "machine/74259.h"
-#include "screen.h"
#include "speaker.h"
-/* unknown divider, assume /5 */
-#define MAIN_CLOCK XTAL(18'432'000)/5
+#define MASTER_CLOCK XTAL(18'432'000)
+
+void clshroad_state::machine_start()
+{
+ save_item(NAME(m_main_irq_mask));
+ save_item(NAME(m_sound_irq_mask));
+ save_item(NAME(m_color_bank));
+}
void clshroad_state::machine_reset()
{
@@ -87,7 +99,9 @@ void clshroad_state::clshroad_map(address_map &map)
map(0xa000, 0xa007).w("mainlatch", FUNC(ls259_device::write_d0));
map(0xa100, 0xa107).r(FUNC(clshroad_state::input_r));
map(0xa800, 0xafff).ram().w(FUNC(clshroad_state::vram_1_w)).share("vram_1"); // Layer 1
- map(0xb000, 0xb003).writeonly().share("vregs"); // Scroll
+ map(0xb000, 0xb001).writeonly().share("vregs"); // Scroll
+ map(0xb002, 0xb002).w(FUNC(clshroad_state::color_bank_w));
+ map(0xb003, 0xb003).w(FUNC(clshroad_state::video_unk_w));
map(0xc000, 0xc7ff).ram().w(FUNC(clshroad_state::vram_0_w)).share("vram_0"); // Layer 0
}
@@ -110,7 +124,7 @@ static INPUT_PORTS_START( clshroad )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("P2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_COCKTAIL
@@ -257,14 +271,14 @@ static const gfx_layout layout_16x16x4 =
static GFXDECODE_START( gfx_firebatl )
GFXDECODE_ENTRY( "gfx1", 0, layout_16x16x4, 0, 16 ) // [0] Sprites
- GFXDECODE_ENTRY( "gfx2", 0, layout_16x16x4, 16, 1 ) // [1] Layer 0
+ GFXDECODE_ENTRY( "gfx2", 0, layout_16x16x4, 0, 16 ) // [1] Layer 0
GFXDECODE_ENTRY( "gfx3", 0, layout_8x8x2, 512, 64 ) // [2] Layer 1
GFXDECODE_END
static GFXDECODE_START( gfx_clshroad )
- GFXDECODE_ENTRY( "gfx1", 0, layout_16x16x4, 0, 16 ) // [0] Sprites
- GFXDECODE_ENTRY( "gfx2", 0, layout_16x16x4, 0x90, 1 ) // [1] Layer 0
- GFXDECODE_ENTRY( "gfx3", 0, layout_8x8x4, 0, 16 ) // [2] Layer 1
+ GFXDECODE_ENTRY( "gfx1", 0, layout_16x16x4, 0, 16 ) // [0] Sprites
+ GFXDECODE_ENTRY( "gfx2", 0, layout_16x16x4, 0, 16 ) // [1] Layer 0
+ GFXDECODE_ENTRY( "gfx3", 0, layout_8x8x4, 0, 16 ) // [2] Layer 1
GFXDECODE_END
@@ -275,6 +289,17 @@ INTERRUPT_GEN_MEMBER(clshroad_state::vblank_irq)
device.execute().set_input_line(0, HOLD_LINE);
}
+INTERRUPT_GEN_MEMBER(clshroad_state::half_vblank_irq)
+{
+ // without this then clshroad runs too fast & BGMs stops playing exactly halfway thru.
+ // it also otherwise make opponents to pop up in the middle of the screen
+ if (m_screen->frame_number() & 1)
+ return;
+
+ if(m_main_irq_mask)
+ device.execute().set_input_line(0, HOLD_LINE);
+}
+
INTERRUPT_GEN_MEMBER(clshroad_state::sound_timer_irq)
{
if(m_sound_irq_mask)
@@ -284,13 +309,15 @@ INTERRUPT_GEN_MEMBER(clshroad_state::sound_timer_irq)
void clshroad_state::firebatl(machine_config &config)
{
/* basic machine hardware */
- Z80(config, m_maincpu, MAIN_CLOCK); /* ? */
+ Z80(config, m_maincpu, MASTER_CLOCK / 6); // μPD780C running at 3.072 MHz? Overruns max frequency of 2.5 MHz ...
m_maincpu->set_addrmap(AS_PROGRAM, &clshroad_state::clshroad_map);
m_maincpu->set_vblank_int("screen", FUNC(clshroad_state::vblank_irq));
- Z80(config, m_audiocpu, MAIN_CLOCK); /* ? */
+ Z80(config, m_audiocpu, MASTER_CLOCK / 6); // μPD780C running at 3.072 MHz? Overruns max frequency of 2.5 MHz ...
m_audiocpu->set_addrmap(AS_PROGRAM, &clshroad_state::clshroad_sound_map);
- m_audiocpu->set_periodic_int(FUNC(clshroad_state::sound_timer_irq), attotime::from_hz(120)); /* periodic interrupt, don't know about the frequency */
+ m_audiocpu->set_periodic_int(FUNC(clshroad_state::sound_timer_irq), attotime::from_hz(120)); // periodic interrupt, exact frequency unknown
+
+ config.set_maximum_quantum(attotime::from_hz(MASTER_CLOCK / 6 / 512)); // 6000 Hz
ls259_device &mainlatch(LS259(config, "mainlatch"));
mainlatch.q_out_cb<0>().set_inputline(m_audiocpu, INPUT_LINE_RESET).invert();
@@ -299,13 +326,10 @@ void clshroad_state::firebatl(machine_config &config)
mainlatch.q_out_cb<4>().set(FUNC(clshroad_state::flipscreen_w));
/* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
- screen.set_size(0x120, 0x100);
- screen.set_visarea(0, 0x120-1, 0x0+16, 0x100-16-1);
- screen.set_screen_update(FUNC(clshroad_state::screen_update));
- screen.set_palette(m_palette);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(MASTER_CLOCK / 3, 384, 0, 288, 264, 16, 240); // unknown, single XTAL on PCB & 288x224 suggests 60.606060 Hz like Galaxian HW
+ m_screen->set_screen_update(FUNC(clshroad_state::screen_update));
+ m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_firebatl);
PALETTE(config, m_palette, FUNC(clshroad_state::firebatl_palette), 512+64*4, 256);
@@ -315,20 +339,22 @@ void clshroad_state::firebatl(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
- WIPING_CUSTOM(config, "custom", 96000).add_route(ALL_OUTPUTS, "mono", 1.0);
+ WIPING_CUSTOM(config, "custom", 96000 / 2).add_route(ALL_OUTPUTS, "mono", 1.0); // 48000 Hz?
}
void clshroad_state::clshroad(machine_config &config)
{
/* basic machine hardware */
- Z80(config, m_maincpu, MAIN_CLOCK); /* ? real speed unknown. 3MHz is too low and causes problems */
+ Z80(config, m_maincpu, MASTER_CLOCK / 6); // LH0080A running at 3.072 MHz? /5 is too fast, /6 matches wiping.cpp
m_maincpu->set_addrmap(AS_PROGRAM, &clshroad_state::clshroad_map);
- m_maincpu->set_vblank_int("screen", FUNC(clshroad_state::vblank_irq));
+ m_maincpu->set_vblank_int("screen", FUNC(clshroad_state::half_vblank_irq));
- Z80(config, m_audiocpu, MAIN_CLOCK); /* ? */
+ Z80(config, m_audiocpu, MASTER_CLOCK / 6); // LH0080A running at 3.072 MHz?
m_audiocpu->set_addrmap(AS_PROGRAM, &clshroad_state::clshroad_sound_map);
- //m_audiocpu->set_vblank_int("screen", FUNC(clshroad_state::irq0_line_hold)); /* IRQ, no NMI */
- m_audiocpu->set_periodic_int(FUNC(clshroad_state::sound_timer_irq), attotime::from_hz(60)); /* periodic interrupt, don't know about the frequency */
+ // TODO: by logic this should be MASTER_CLOCK / 3 / 65536 = 93.75 Hz, but it quite don't work right.
+ m_audiocpu->set_periodic_int(FUNC(clshroad_state::sound_timer_irq), attotime::from_hz(82.75)); // periodic interrupt, exact frequency unknown
+
+ config.set_maximum_quantum(attotime::from_hz(MASTER_CLOCK / 6 / 512)); // 6000 Hz
ls259_device &mainlatch(LS259(config, "mainlatch"));
mainlatch.q_out_cb<0>().set_nop(); // never writes here?
@@ -337,13 +363,10 @@ void clshroad_state::clshroad(machine_config &config)
mainlatch.q_out_cb<4>().set(FUNC(clshroad_state::flipscreen_w));
/* video hardware */
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_refresh_hz(60);
- screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
- screen.set_size(0x120, 0x100);
- screen.set_visarea(0, 0x120-1, 0x0+16, 0x100-16-1);
- screen.set_screen_update(FUNC(clshroad_state::screen_update));
- screen.set_palette(m_palette);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(MASTER_CLOCK / 3, 384, 0, 288, 264, 16, 240); // unknown, single XTAL on PCB & 288x224 suggests 60.606060 Hz like Galaxian HW
+ m_screen->set_screen_update(FUNC(clshroad_state::screen_update));
+ m_screen->set_palette(m_palette);
GFXDECODE(config, m_gfxdecode, m_palette, gfx_clshroad);
PALETTE(config, m_palette, FUNC(clshroad_state::clshroad_palette), 256);
@@ -353,7 +376,7 @@ void clshroad_state::clshroad(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
- WIPING_CUSTOM(config, "custom", 96000).add_route(ALL_OUTPUTS, "mono", 1.0);
+ WIPING_CUSTOM(config, "custom", MASTER_CLOCK / 3 / 256).add_route(ALL_OUTPUTS, "mono", 1.0); // 24000 Hz?
}
@@ -572,7 +595,7 @@ void clshroad_state::init_firebatl()
ROM[0x6124] = 0x02;
}
-GAME( 1984, firebatl, 0, firebatl, firebatl, clshroad_state, init_firebatl, ROT90, "Woodplace Inc. (Taito license)", "Fire Battle", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_GRAPHICS | MACHINE_UNEMULATED_PROTECTION )
-GAME( 1986, clshroad, 0, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc.", "Clash-Road", MACHINE_SUPPORTS_SAVE )
-GAME( 1986, clshroads, clshroad, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc. (Status Game Corp. license)", "Clash-Road (Status license)", MACHINE_SUPPORTS_SAVE )
-GAME( 1986, clshroadd, clshroad, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc. (Data East license)", "Clash-Road (Data East license)", MACHINE_SUPPORTS_SAVE )
+GAME( 1984, firebatl, 0, firebatl, firebatl, clshroad_state, init_firebatl, ROT90, "Woodplace Inc. (Taito license)", "Fire Battle", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_COLORS | MACHINE_UNEMULATED_PROTECTION ) // developed by Graphic Research
+GAME( 1986, clshroad, 0, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc.", "Clash-Road", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_TIMING )
+GAME( 1986, clshroads, clshroad, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc. (Status Game Corp. license)", "Clash-Road (Status license)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_TIMING )
+GAME( 1986, clshroadd, clshroad, clshroad, clshroad, clshroad_state, empty_init, ROT0, "Woodplace Inc. (Data East license)", "Clash-Road (Data East license)", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND | MACHINE_IMPERFECT_TIMING )