// license:BSD-3-Clause
// copyright-holders:hap, Sean Riddle
/***************************************************************************
** subclass of hh_sm510_state (includes/hh_sm510.h, drivers/hh_sm510.cpp) **
Tiger R-Zone driver
This is a backwards console, the heart of the machine is the cartridge.
The console houses the controller, speaker, power, backlight, and a
polarizer filter for the screen. The cartridge has the MCU, optional
sound ROM, and the LCD screen in a translucent window.
Console family:
1995: R-Zone HeadGear: Wearable headset, controller is separate,
red-on-black screen is reflected in front of the right eye.
1996: R-Zone SuperScreen: Handheld console, inverted filter(aka black
LCD segments), optional background sheet as with standalone handhelds.
1997: R-Zone X.P.G - Xtreme Pocket Game: Handheld version of HeadGear.
1997: R-Zone DataZone: PDA with a built-in SuperScreen.
TODO:
- support for SuperScreen. SVG colors will need to be inverted, or maybe
with artwork or HLSL?
- add DataZone, will get its own driver
***************************************************************************/
#include "emu.h"
#include "includes/hh_sm510.h"
#include "cpu/sm510/sm510.h"
#include "screen.h"
#include "speaker.h"
// internal artwork
#include "rzone.lh"
class rzone_state : public hh_sm510_state
{
public:
rzone_state(const machine_config &mconfig, device_type type, const char *tag)
: hh_sm510_state(mconfig, type, tag),
m_led_out(*this, "led"),
m_led_off(*this, "led_off")
{ }
output_finder<> m_led_out;
required_device<timer_device> m_led_off;
int m_led_pin;
int m_sctrl;
int m_sclock;
TIMER_DEVICE_CALLBACK_MEMBER(led_off_callback) { m_led_out = m_led_pin ? 1 : 0; }
DECLARE_WRITE_LINE_MEMBER(led_w);
DECLARE_WRITE_LINE_MEMBER(audio_w);
DECLARE_WRITE_LINE_MEMBER(sctrl_w);
DECLARE_WRITE_LINE_MEMBER(sclock_w);
DECLARE_READ_LINE_MEMBER(sdata_r);
DECLARE_WRITE8_MEMBER(t1_write_r);
DECLARE_WRITE8_MEMBER(t1_write_s);
virtual DECLARE_READ8_MEMBER(input_r) override;
void t2_update_audio();
DECLARE_WRITE8_MEMBER(t2_write_r);
DECLARE_WRITE8_MEMBER(t2_write_s);
void rzbatfor(machine_config &config);
void rzindy500(machine_config &config);
protected:
virtual void machine_start() override;
};
// machine start
void rzone_state::machine_start()
{
hh_sm510_state::machine_start();
// resolve handlers
m_led_out.resolve();
// zerofill
m_led_pin = 0;
m_sctrl = 0;
m_sclock = 0;
// register for savestates
save_item(NAME(m_led_pin));
save_item(NAME(m_sctrl));
save_item(NAME(m_sclock));
}
/***************************************************************************
I/O
***************************************************************************/
// console
WRITE_LINE_MEMBER(rzone_state::led_w)
{
// LED: enable backlight
if (state)
m_led_out = 1;
// delay led off to prevent flickering
if (!state && m_led_pin)
m_led_off->adjust(attotime::from_msec(30));
m_led_pin = state;
}
WRITE_LINE_MEMBER(rzone_state::audio_w)
{
// Audio: speaker out
m_speaker->level_w(state ? 1 : 0);
}
WRITE_LINE_MEMBER(rzone_state::sctrl_w)
{
// SCTRL: 74165 SH/LD: reload inputs while low
if (!state || !m_sctrl)
m_inp_mux = m_inp_matrix[0]->read();
m_sctrl = state;
}
WRITE_LINE_MEMBER(rzone_state::sclock_w)
{
// SCLOCK: 74165 CLK: shift inputs on rising edge when 74165 SH/LD is high
if (m_sctrl && !m_sclock && state)
m_inp_mux >>= 1;
m_sclock = state;
}
READ_LINE_MEMBER(rzone_state::sdata_r)
{
// SDATA: 74165 Q
sctrl_w(m_sctrl); // reload inputs if needed
return m_inp_mux & 1;
}
// cartridge type 1: simple SM510
WRITE8_MEMBER(rzone_state::t1_write_r)
{
// R1: Audio
audio_w(data & 1);
// R2: SCTRL
sctrl_w(data >> 1 & 1);
}
WRITE8_MEMBER(rzone_state::t1_write_s)
{
// S1: LED
led_w(data & 1);
// S2: SCLOCK
sclock_w(data >> 1 & 1);
}
READ8_MEMBER(rzone_state::input_r)
{
// K1: SDATA
return sdata_r();
}
// cartridge type 2: simple SM512, 2 audio lines
void rzone_state::t2_update_audio()
{
audio_w((m_s >> 2 & 1) | (m_r & 1));
}
WRITE8_MEMBER(rzone_state::t2_write_r)
{
// R: Audio
m_r = data;
t2_update_audio();
}
WRITE8_MEMBER(rzone_state::t2_write_s)
{
// S1: SCTRL
sctrl_w(data & 1);
// S2: SCLOCK
sclock_w(data >> 1 & 1);
// S3: Audio
m_s = data;
t2_update_audio();
// S4: LED
led_w(data >> 3 & 1);
}
/***************************************************************************
Inputs
***************************************************************************/
static INPUT_PORTS_START( rzone )
PORT_START("IN.0")
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_CHANGED_MEMBER(DEVICE_SELF, hh_sm510_state, input_changed, nullptr)
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP )
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON1 ) // A
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) // B
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_BUTTON3 ) // C
PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON4 ) // D
PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_VOLUME_DOWN ) PORT_NAME("Sound")
PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_SELECT )
PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_POWER_OFF )
PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("Pause")
PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_START )
INPUT_PORTS_END
/***************************************************************************
Machine Config
***************************************************************************/
MACHINE_CONFIG_START(rzone_state::rzindy500)
/* basic machine hardware */
MCFG_DEVICE_ADD("maincpu", SM510) // no external XTAL
MCFG_SM510_R_MASK_OPTION(SM510_R_CONTROL_OUTPUT) // confirmed
MCFG_SM510_WRITE_SEGS_CB(WRITE16(*this, hh_sm510_state, sm510_lcd_segment_w))
MCFG_SM510_READ_K_CB(READ8(*this, rzone_state, input_r))
MCFG_SM510_WRITE_S_CB(WRITE8(*this, rzone_state, t1_write_s))
MCFG_SM510_WRITE_R_CB(WRITE8(*this, rzone_state, t1_write_r))
/* video hardware */
MCFG_SCREEN_SVG_ADD("screen", "svg")
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_SIZE(1425, 1080)
MCFG_SCREEN_VISIBLE_AREA(0, 1425-1, 0, 1080-1)
MCFG_TIMER_DRIVER_ADD("led_off", rzone_state, led_off_callback)
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_sm510_state, display_decay_tick, attotime::from_msec(1))
MCFG_DEFAULT_LAYOUT(layout_rzone)
/* sound hardware */
SPEAKER(config, "mono").front_center();
MCFG_DEVICE_ADD("speaker", SPEAKER_SOUND)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MACHINE_CONFIG_END
MACHINE_CONFIG_START(rzone_state::rzbatfor)
/* basic machine hardware */
MCFG_DEVICE_ADD("maincpu", SM512) // no external XTAL
MCFG_SM510_WRITE_SEGS_CB(WRITE16(*this, hh_sm510_state, sm510_lcd_segment_w))
MCFG_SM510_READ_K_CB(READ8(*this, rzone_state, input_r))
MCFG_SM510_WRITE_S_CB(WRITE8(*this, rzone_state, t2_write_s))
MCFG_SM510_WRITE_R_CB(WRITE8(*this, rzone_state, t2_write_r))
/* video hardware */
MCFG_SCREEN_SVG_ADD("screen", "svg")
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_SIZE(1368, 1080)
MCFG_SCREEN_VISIBLE_AREA(0, 1368-1, 0, 1080-1)
MCFG_TIMER_DRIVER_ADD("led_off", rzone_state, led_off_callback)
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_sm510_state, display_decay_tick, attotime::from_msec(1))
MCFG_DEFAULT_LAYOUT(layout_rzone)
/* sound hardware */
SPEAKER(config, "mono").front_center();
MCFG_DEVICE_ADD("speaker", SPEAKER_SOUND)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
MACHINE_CONFIG_END
/***************************************************************************
Game driver(s)
***************************************************************************/
ROM_START( rzindy500 )
ROM_REGION( 0x1000, "maincpu", 0 ) // SM510 under epoxy, KMS10 22
ROM_LOAD( "kms10_22", 0x0000, 0x1000, CRC(99a746d0) SHA1(64264499d45a566fa9a0801c20e7fa27eac18da6) )
ROM_REGION( 533411, "svg", 0)
ROM_LOAD( "rzindy500.svg", 0, 533411, CRC(cfc85677) SHA1(014b9123d81fba1488b4a22a6b6fd0c09e22c1ea) )
ROM_END
ROM_START( rzbatfor )
ROM_REGION( 0x1000, "maincpu", 0 ) // SM512 under epoxy, KMN1202 (not the same game as the standalone Tiger handheld)
ROM_LOAD( "kmn1202.program", 0x0000, 0x1000, CRC(27abdb52) SHA1(b356ff80b628244da588b4748404b78d7a57eccd) )
ROM_REGION( 0x100, "maincpu:melody", 0 )
ROM_LOAD( "kmn1202.melody", 0x000, 0x100, CRC(d794746c) SHA1(f0706c5100c090c65fcb2d768b5a5b4a55b29e04) )
ROM_REGION( 652556, "svg", 0)
ROM_LOAD( "rzbatfor.svg", 0, 652556, CRC(4d850489) SHA1(31a2a1e9209c0f77dbc268cddbfa4a67478734a7) )
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
CONS( 1995, rzindy500, 0, 0, rzindy500, rzone, rzone_state, empty_init, "Tiger Electronics (licensed from Sega)", "R-Zone: Indy 500", MACHINE_SUPPORTS_SAVE )
CONS( 1995, rzbatfor, 0, 0, rzbatfor, rzone, rzone_state, empty_init, "Tiger Electronics", "R-Zone: Batman Forever", MACHINE_SUPPORTS_SAVE )