clshroad.cpp: various fixes (#8400)

* clshroad.cpp: Add tilemap color bank, fix lightning flashing and color cycling for Fire Battle;
clshroad.cpp: Hand-tuned all clock frequencies for clshroad and halved vblank irq rate, syncing video and sound timings in logical sense;
* wiping.cpp, wiping.cpp: Convert to Xtal and add tentative screen raw params;
* audio/wiping.cpp: Make custom audio to actually not divide internally by 2;
* clshroad.cpp: minor realign documentation
This commit is contained in:
Angelo Salese 2021-08-08 18:50:02 +02:00 committed by GitHub
parent 3da6dd410f
commit 8385a3dc85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 144 additions and 78 deletions

View File

@ -2,10 +2,16 @@
// copyright-holders:Allard van der Bas
/***************************************************************************
Wiping sound driver (quick hack of the Namco sound driver)
Wiping sound driver
Nichibutsu / Woodplace Inc. custom part?
used by wiping.cpp and clshroad.cpp
TODO:
- Identify actual part, sound device was originally based off
Namco customs (on which involvement seems pretty thin here);
***************************************************************************/
#include "emu.h"
@ -37,10 +43,10 @@ void wiping_sound_device::device_start()
wp_sound_channel *voice;
/* get stream channels */
m_stream = stream_alloc(0, 1, clock()/2);
m_stream = stream_alloc(0, 1, clock()); // 48000 Hz
/* allocate a buffer to mix into - 1 second's worth should be more than enough */
m_mixer_buffer.resize(clock()/2);
m_mixer_buffer.resize(clock());
/* extract globals from the interface */
m_num_voices = 8;

View File

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

View File

@ -9,6 +9,10 @@
Allard van der Bas (allard@mindless.com)
1 x Z80 CPU main game, 1 x Z80 with ???? sound hardware.
Given the similarities with clshroad.cpp this was probably developed by
Masao Suzuki, who later left Nichibutsu to form Woodplace Inc.
----------------------------------------------------------------------------
Main processor :
@ -45,6 +49,7 @@ dip: 6.7 7.7
#include "screen.h"
#include "speaker.h"
#define MASTER_CLOCK XTAL(18'432'000)
void wiping_state::machine_start()
{
@ -287,14 +292,16 @@ INTERRUPT_GEN_MEMBER(wiping_state::sound_timer_irq)
void wiping_state::wiping(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, 18432000/6); /* 3.072 MHz */
Z80(config, m_maincpu, MASTER_CLOCK / 6); /* 3.072 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &wiping_state::main_map);
m_maincpu->set_vblank_int("screen", FUNC(wiping_state::vblank_irq));
Z80(config, m_audiocpu, 18432000/6); /* 3.072 MHz */
Z80(config, m_audiocpu, MASTER_CLOCK / 6); /* 3.072 MHz */
m_audiocpu->set_addrmap(AS_PROGRAM, &wiping_state::sound_map);
m_audiocpu->set_periodic_int(FUNC(wiping_state::sound_timer_irq), attotime::from_hz(120)); /* periodic interrupt, don't know about the frequency */
config.set_maximum_quantum(attotime::from_hz(MASTER_CLOCK / 6 / 512)); // 6000 Hz
ls259_device &mainlatch(LS259(config, "mainlatch")); // 5A
mainlatch.q_out_cb<0>().set(FUNC(wiping_state::main_irq_mask_w)); // INT1
mainlatch.q_out_cb<1>().set(FUNC(wiping_state::sound_irq_mask_w)); // INT2
@ -305,10 +312,7 @@ void wiping_state::wiping(machine_config &config)
/* 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(36*8, 28*8);
screen.set_visarea(0*8, 36*8-1, 0*8, 28*8-1);
screen.set_raw(MASTER_CLOCK / 3, 384, 0, 288, 264, 0, 224); // unknown, single XTAL on PCB & 288x224 suggests 60.606060 Hz like Galaxian HW
screen.set_screen_update(FUNC(wiping_state::screen_update));
screen.set_palette(m_palette);
@ -318,7 +322,7 @@ void wiping_state::wiping(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
WIPING_CUSTOM(config, "wiping", 96000).add_route(ALL_OUTPUTS, "mono", 1.0);
WIPING_CUSTOM(config, "wiping", 96000 / 2).add_route(ALL_OUTPUTS, "mono", 1.0); // 48000 Hz?
}

View File

@ -6,25 +6,28 @@
#pragma once
#include "emupal.h"
#include "screen.h"
#include "tilemap.h"
class clshroad_state : public driver_device
{
public:
clshroad_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_spriteram(*this, "spriteram"),
m_vram_0(*this, "vram_0"),
m_vram_1(*this, "vram_1"),
m_vregs(*this, "vregs")
clshroad_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_audiocpu(*this, "audiocpu")
, m_screen(*this, "screen")
, m_gfxdecode(*this, "gfxdecode")
, m_palette(*this, "palette")
, m_spriteram(*this, "spriteram")
, m_vram_0(*this, "vram_0")
, m_vram_1(*this, "vram_1")
, m_vregs(*this, "vregs")
{ }
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_audiocpu;
required_device<screen_device> m_screen;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
@ -33,8 +36,10 @@ public:
required_shared_ptr<uint8_t> m_vram_1;
required_shared_ptr<uint8_t> m_vregs;
uint8_t m_main_irq_mask;
uint8_t m_sound_irq_mask;
u8 m_main_irq_mask;
u8 m_sound_irq_mask;
u8 m_color_bank;
u8 m_video_unk;
tilemap_t *m_tilemap_0a;
tilemap_t *m_tilemap_0b;
@ -54,15 +59,19 @@ public:
TILE_GET_INFO_MEMBER(get_tile_info_1);
void init_firebatl();
virtual void machine_start() override;
virtual void machine_reset() override;
DECLARE_VIDEO_START(firebatl);
void firebatl_palette(palette_device &palette) const;
DECLARE_VIDEO_START(clshroad);
void clshroad_palette(palette_device &palette) const;
void color_bank_w(offs_t offset, u8 data);
void video_unk_w(offs_t offset, u8 data);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(vblank_irq);
INTERRUPT_GEN_MEMBER(half_vblank_irq);
INTERRUPT_GEN_MEMBER(sound_timer_irq);
void firebatl(machine_config &config);
void clshroad(machine_config &config);

View File

@ -109,10 +109,12 @@ TILE_GET_INFO_MEMBER(clshroad_state::get_tile_info_0a)
tile_index = (tile_index & 0x1f) + (tile_index & ~0x1f)*2;
code = m_vram_0[ tile_index * 2 + 0x40 ];
// color = m_vram_0[ tile_index * 2 + 0x41 ];
tileinfo.set(1,
code,
0,
0);
tileinfo.set(
1,
code,
m_color_bank,
0
);
}
TILE_GET_INFO_MEMBER(clshroad_state::get_tile_info_0b)
@ -121,10 +123,12 @@ TILE_GET_INFO_MEMBER(clshroad_state::get_tile_info_0b)
tile_index = (tile_index & 0x1f) + (tile_index & ~0x1f)*2;
code = m_vram_0[ tile_index * 2 + 0x00 ];
// color = m_vram_0[ tile_index * 2 + 0x01 ];
tileinfo.set(1,
code,
0,
0);
tileinfo.set(
1,
code,
m_color_bank,
0
);
}
void clshroad_state::vram_0_w(offs_t offset, uint8_t data)
@ -198,6 +202,26 @@ void clshroad_state::vram_1_w(offs_t offset, uint8_t data)
m_tilemap_1->mark_tile_dirty(offset % 0x400);
}
void clshroad_state::color_bank_w(offs_t offset, u8 data)
{
// - Clash Road: always 9 during gameplay and 0 when title screen displays
// (further disabling it out)
// - Fire Battle: variable depending on what happens on screen
// (makes background to flash when lightning occurs, has additional color cycling effects)
m_color_bank = data & 0xf;
m_tilemap_0a->mark_all_dirty();
m_tilemap_0b->mark_all_dirty();
if (data & 0xf0)
logerror("%s: unknown vreg [2] write %02x\n", machine().describe_context(), data);
}
void clshroad_state::video_unk_w(offs_t offset, u8 data)
{
// Clash Road: inited to 0 at POST, never touched anywhere else
// Fire Battle: always bit 7 held, normally 0x80,
// increments bits 0-3 from 0x80 to 0x8f when lightning is about to strike and decrements back to 0x80
// after section has been passed, color gain control? sprite color bank (on unmapped color proms)?
}
VIDEO_START_MEMBER(clshroad_state,firebatl)
{