// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Sean Riddle
/***************************************************************************
National Semiconductor COP400 MCU handhelds or other simple devices,
mostly LED electronic games/toys.
TODO:
- why does h2hbaskbc(and clones) need a workaround on writing L pins?
- plus1: which sensor position is which colour?
- vidchal: Add screen and gun cursor with brightness detection callback,
and softwarelist for the video tapes. We'd also need a VHS player device.
The emulated lightgun itself appears to be working fine(eg. add a 30hz
timer to IN.3 to score +100)
***************************************************************************/
#include "emu.h"
#include "cpu/cop400/cop400.h"
#include "video/pwm.h"
#include "machine/timer.h"
#include "sound/spkrdev.h"
#include "sound/dac.h"
#include "sound/volt_reg.h"
#include "screen.h"
#include "speaker.h"
// internal artwork
#include "bship82.lh" // clickable
#include "ctstein.lh" // clickable
#include "einvaderc.lh"
#include "funjacks.lh" // clickable
#include "funrlgl.lh"
#include "h2hbaskbc.lh"
#include "h2hhockeyc.lh"
#include "h2hsoccerc.lh"
#include "lchicken.lh" // clickable
#include "lightfgt.lh" // clickable
#include "mdallas.lh"
#include "qkracer.lh"
#include "unkeinv.lh"
#include "vidchal.lh"
//#include "hh_cop400_test.lh" // common test-layout - use external artwork
class hh_cop400_state : public driver_device
{
public:
hh_cop400_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_display(*this, "display"),
m_speaker(*this, "speaker"),
m_inputs(*this, "IN.%u", 0)
{ }
// devices
required_device<cop400_cpu_device> m_maincpu;
optional_device<pwm_display_device> m_display;
optional_device<speaker_sound_device> m_speaker;
optional_ioport_array<6> m_inputs; // max 6
// misc common
u8 m_l; // MCU port L write data
u8 m_g; // MCU port G write data
u8 m_d; // MCU port D write data
int m_so; // MCU SO line state
int m_sk; // MCU SK line state
u16 m_inp_mux; // multiplexed inputs mask
u16 read_inputs(int columns, u16 colmask = ~0);
virtual DECLARE_INPUT_CHANGED_MEMBER(reset_button);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
};
// machine start/reset
void hh_cop400_state::machine_start()
{
// zerofill
m_l = 0;
m_g = 0;
m_d = 0;
m_so = 0;
m_sk = 0;
m_inp_mux = ~0;
// register for savestates
save_item(NAME(m_l));
save_item(NAME(m_g));
save_item(NAME(m_d));
save_item(NAME(m_so));
save_item(NAME(m_sk));
save_item(NAME(m_inp_mux));
}
void hh_cop400_state::machine_reset()
{
}
/***************************************************************************
Helper Functions
***************************************************************************/
// generic input handlers
u16 hh_cop400_state::read_inputs(int columns, u16 colmask)
{
// active low
u16 ret = ~0 & colmask;
// read selected input rows
for (int i = 0; i < columns; i++)
if (~m_inp_mux >> i & 1)
ret &= m_inputs[i]->read();
return ret;
}
INPUT_CHANGED_MEMBER(hh_cop400_state::reset_button)
{
// when an input is directly wired to MCU reset pin
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
}
/***************************************************************************
Minidrivers (subclass, I/O, Inputs, Machine Config, ROM Defs)
***************************************************************************/
namespace {
/***************************************************************************
Castle Toy Einstein
* COP421 MCU label ~/927 COP421-NEZ/N
* 4 lamps, 1-bit sound
This is a Simon clone, the tones are not harmonic. Two models exist, each
with a different batteries setup, assume they're same otherwise.
***************************************************************************/
class ctstein_state : public hh_cop400_state
{
public:
ctstein_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void write_g(u8 data);
void write_l(u8 data);
u8 read_l();
void ctstein(machine_config &config);
};
// handlers
void ctstein_state::write_g(u8 data)
{
// G0-G2: input mux
m_inp_mux = data & 7;
}
void ctstein_state::write_l(u8 data)
{
// L0-L3: button lamps
m_display->matrix(1, data & 0xf);
}
u8 ctstein_state::read_l()
{
// L4-L7: multiplexed inputs
return read_inputs(3, 0xf) << 4 | 0xf;
}
// config
static INPUT_PORTS_START( ctstein )
PORT_START("IN.0") // G0 port L
PORT_CONFNAME( 0x0f, 0x01^0x0f, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x01^0x0f, "1" )
PORT_CONFSETTING( 0x02^0x0f, "2" )
PORT_CONFSETTING( 0x04^0x0f, "3" )
PORT_CONFSETTING( 0x08^0x0f, "4" )
PORT_START("IN.1") // G1 port L
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("Best Score")
PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.2") // G2 port L
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Red Button")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Yellow Button")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Green Button")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Blue Button")
INPUT_PORTS_END
void ctstein_state::ctstein(machine_config &config)
{
/* basic machine hardware */
COP421(config, m_maincpu, 850000); // approximation - RC osc. R=12K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_g().set(FUNC(ctstein_state::write_g));
m_maincpu->write_l().set(FUNC(ctstein_state::write_l));
m_maincpu->write_sk().set(m_speaker, FUNC(speaker_sound_device::level_w));
m_maincpu->read_l().set(FUNC(ctstein_state::read_l));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(1, 4);
config.set_default_layout(layout_ctstein);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( ctstein )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop421-nez_n", 0x0000, 0x0400, CRC(16148e03) SHA1(b2b74891d36813d9a1eefd56a925054997c4b7f7) ) // 2nd half empty
ROM_END
/***************************************************************************
Coleco Head to Head: Electronic Basketball/Hockey/Soccer (model 2150/2160/2170)
* COP420 MCU label COP420L-NEZ/N
* 2-digit 7seg display, 41 other leds, 1-bit sound
3 Head to Head games were released using this MCU/ROM. They play very much
the same, only differing on game time. The PCB is pre-configured on G1+IN2
and IN3 to select the game.
An earlier revision of this runs on TMS1000, see hh_tms1k.cpp driver. Model
numbers are the same. From the outside, an easy way to spot the difference is
the Start/Display button: TMS1000 version button label is D, COP420 one is a *.
The COP420 version also plays much slower.
***************************************************************************/
class h2hbaskbc_state : public hh_cop400_state
{
public:
h2hbaskbc_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void write_d(u8 data);
void write_g(u8 data);
void write_l(u8 data);
u8 read_in();
void h2hsoccerc(machine_config &config);
void h2hbaskbc(machine_config &config);
void h2hhockeyc(machine_config &config);
};
// handlers
void h2hbaskbc_state::write_d(u8 data)
{
// D: led select
m_d = data & 0xf;
}
void h2hbaskbc_state::write_g(u8 data)
{
// G: led select, input mux
m_inp_mux = data;
m_g = data & 0xf;
}
void h2hbaskbc_state::write_l(u8 data)
{
// D2,D3 double as multiplexer
u16 mask = ((m_d >> 2 & 1) * 0x00ff) | ((m_d >> 3 & 1) * 0xff00);
u16 sel = (m_g | m_d << 4 | m_g << 8 | m_d << 12) & mask;
// D2+G0,G1 are 7segs
// L0-L6: digit segments A-G, L0-L4: led data
m_display->matrix(sel, data);
}
u8 h2hbaskbc_state::read_in()
{
// IN: multiplexed inputs
return read_inputs(4, 7) | (m_inputs[4]->read() & 8);
}
// config
static INPUT_PORTS_START( h2hbaskbc )
PORT_START("IN.0") // G0 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_16WAY PORT_NAME("P1 Pass CW") // clockwise
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_16WAY PORT_NAME("P1 Pass CCW") // counter-clockwise
PORT_CONFNAME( 0x04, 0x04, DEF_STR( Players ) )
PORT_CONFSETTING( 0x04, "1" )
PORT_CONFSETTING( 0x00, "2" )
PORT_START("IN.1") // G1 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Shoot")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start/Display")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_CUSTOM ) // factory set
PORT_START("IN.2") // G2 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL PORT_16WAY PORT_NAME("P2 Defense Right")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL PORT_16WAY PORT_NAME("P2 Defense Left")
PORT_CONFNAME( 0x04, 0x04, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x04, "1" )
PORT_CONFSETTING( 0x00, "2" )
PORT_START("IN.3") // G3 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_CONFNAME( 0x04, 0x04, "Factory Test" )
PORT_CONFSETTING( 0x04, DEF_STR( Off ) )
PORT_CONFSETTING( 0x00, DEF_STR( On ) )
PORT_START("IN.4") // IN3 (factory set)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM )
INPUT_PORTS_END
static INPUT_PORTS_START( h2hhockeyc )
PORT_INCLUDE( h2hbaskbc )
PORT_MODIFY("IN.3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_NAME("P2 Goalie Right")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("P2 Goalie Left")
PORT_MODIFY("IN.4")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM )
INPUT_PORTS_END
static INPUT_PORTS_START( h2hsoccerc )
PORT_INCLUDE( h2hhockeyc )
PORT_MODIFY("IN.1")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_CUSTOM )
INPUT_PORTS_END
void h2hbaskbc_state::h2hbaskbc(machine_config &config)
{
/* basic machine hardware */
COP420(config, m_maincpu, 1000000); // approximation - RC osc. R=43K, C=101pF
m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(h2hbaskbc_state::write_d));
m_maincpu->write_g().set(FUNC(h2hbaskbc_state::write_g));
m_maincpu->write_l().set(FUNC(h2hbaskbc_state::write_l));
m_maincpu->read_in().set(FUNC(h2hbaskbc_state::read_in));
m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(16, 7);
m_display->set_segmask(3, 0x7f);
config.set_default_layout(layout_h2hbaskbc);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
void h2hbaskbc_state::h2hhockeyc(machine_config &config)
{
h2hbaskbc(config);
config.set_default_layout(layout_h2hhockeyc);
}
void h2hbaskbc_state::h2hsoccerc(machine_config &config)
{
h2hbaskbc(config);
config.set_default_layout(layout_h2hsoccerc);
}
// roms
ROM_START( h2hbaskbc )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop420l-nmy", 0x0000, 0x0400, CRC(87152509) SHA1(acdb869b65d49b3b9855a557ed671cbbb0f61e2c) )
ROM_END
#define rom_h2hhockeyc rom_h2hbaskbc // dumped from Basketball
#define rom_h2hsoccerc rom_h2hbaskbc // "
/***************************************************************************
Entex Space Invader
* COP444L MCU label /B138 COPL444-HRZ/N INV II (die label HRZ COP 444L/A)
* 3 7seg LEDs, LED matrix and overlay mask, 1-bit sound
The first version was on TMS1100 (see hh_tms1k.c), this is the reprogrammed
second release with a gray case instead of black.
***************************************************************************/
class einvaderc_state : public hh_cop400_state
{
public:
einvaderc_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_d(u8 data);
void write_g(u8 data);
DECLARE_WRITE_LINE_MEMBER(write_sk);
DECLARE_WRITE_LINE_MEMBER(write_so);
void write_l(u8 data);
void einvaderc(machine_config &config);
};
// handlers
void einvaderc_state::update_display()
{
u8 l = bitswap<8>(m_l,7,6,0,1,2,3,4,5);
u16 grid = (m_d | m_g << 4 | m_sk << 8 | m_so << 9) ^ 0x0ff;
m_display->matrix(grid, l);
}
void einvaderc_state::write_d(u8 data)
{
// D: led grid 0-3 (D0-D2 are 7segs)
m_d = data;
update_display();
}
void einvaderc_state::write_g(u8 data)
{
// G: led grid 4-7
m_g = data;
update_display();
}
WRITE_LINE_MEMBER(einvaderc_state::write_sk)
{
// SK: speaker out + led grid 8
m_speaker->level_w(state);
m_sk = state;
update_display();
}
WRITE_LINE_MEMBER(einvaderc_state::write_so)
{
// SO: led grid 9
m_so = state;
update_display();
}
void einvaderc_state::write_l(u8 data)
{
// L: led state/segment
m_l = data;
update_display();
}
// config
static INPUT_PORTS_START( einvaderc )
PORT_START("IN.0") // port IN
PORT_CONFNAME( 0x01, 0x01, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x01, "Amateur" )
PORT_CONFSETTING( 0x00, "Professional" )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_16WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_16WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 )
INPUT_PORTS_END
void einvaderc_state::einvaderc(machine_config &config)
{
/* basic machine hardware */
COP444L(config, m_maincpu, 850000); // approximation - RC osc. R=47K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->read_in().set_ioport("IN.0");
m_maincpu->write_d().set(FUNC(einvaderc_state::write_d));
m_maincpu->write_g().set(FUNC(einvaderc_state::write_g));
m_maincpu->write_sk().set(FUNC(einvaderc_state::write_sk));
m_maincpu->write_so().set(FUNC(einvaderc_state::write_so));
m_maincpu->write_l().set(FUNC(einvaderc_state::write_l));
/* video hardware */
screen_device &mask(SCREEN(config, "mask", SCREEN_TYPE_SVG));
mask.set_refresh_hz(60);
mask.set_size(919, 1080);
mask.set_visarea_full();
PWM_DISPLAY(config, m_display).set_size(10, 8);
m_display->set_segmask(7, 0x7f);
config.set_default_layout(layout_einvaderc);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( einvaderc )
ROM_REGION( 0x0800, "maincpu", 0 )
ROM_LOAD( "copl444-hrz_n_inv_ii", 0x0000, 0x0800, CRC(76400f38) SHA1(0e92ab0517f7b7687293b189d30d57110df20fe0) )
ROM_REGION( 82104, "mask", 0)
ROM_LOAD( "einvaderc.svg", 0, 82104, CRC(0013227f) SHA1(44a3ac48c947369231f010559331ad16fcbef7be) )
ROM_END
/***************************************************************************
Gordon Barlow Design electronic Space Invaders game (unreleased, from patent US4345764)
* COP421 (likely a development chip)
* 36+9 LEDs, 1-bit sound
This game is presumedly unreleased. The title is unknown, the patent simply names
it "Hand-held electronic game". There is no mass-manufacture company assigned
to it either. The game seems unfinished(no scorekeeping, some bugs), and the design
is very complex. Player ship and bullets are on a moving "wand", a 2-way mirror
makes it appear on the same plane as the enemies and barriers.
***************************************************************************/
class unkeinv_state : public hh_cop400_state
{
public:
unkeinv_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_g(u8 data);
void write_d(u8 data);
void write_l(u8 data);
u8 read_l();
DECLARE_INPUT_CHANGED_MEMBER(position_changed) { update_display(); }
void unkeinv(machine_config &config);
};
// handlers
void unkeinv_state::update_display()
{
m_display->matrix(m_l, m_g << 4 | m_d, false);
// positional led row is on L6,L7
u16 wand = m_display->read_row(7) << 8 | m_display->read_row(6);
m_display->write_row(8 + m_inputs[1]->read(), wand);
m_display->update();
}
void unkeinv_state::write_g(u8 data)
{
// G0-G3: led select part
// G2,G3: input mux
m_g = ~data & 0xf;
update_display();
}
void unkeinv_state::write_d(u8 data)
{
// D0-D3: led select part
m_d = ~data & 0xf;
update_display();
}
void unkeinv_state::write_l(u8 data)
{
// L0-L7: led data
m_l = ~data & 0xff;
update_display();
}
u8 unkeinv_state::read_l()
{
u8 ret = 0xff;
// L0-L5+G2: positional odd
// L0-L5+G3: positional even
u8 pos = m_inputs[1]->read();
if (m_g & 4 && pos & 1)
ret ^= (1 << (pos >> 1));
if (m_g & 8 && ~pos & 1)
ret ^= (1 << (pos >> 1));
// L7+G3: fire button
if (m_g & 8 && m_inputs[0]->read())
ret ^= 0x80;
return ret & ~m_l;
}
// config
static INPUT_PORTS_START( unkeinv )
PORT_START("IN.0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_START("IN.1")
PORT_BIT( 0x0f, 0x00, IPT_POSITIONAL ) PORT_POSITIONS(12) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_CENTERDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, unkeinv_state, position_changed, 0)
INPUT_PORTS_END
void unkeinv_state::unkeinv(machine_config &config)
{
/* basic machine hardware */
COP421(config, m_maincpu, 850000); // frequency guessed
m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_g().set(FUNC(unkeinv_state::write_g));
m_maincpu->write_d().set(FUNC(unkeinv_state::write_d));
m_maincpu->write_l().set(FUNC(unkeinv_state::write_l));
m_maincpu->read_l().set(FUNC(unkeinv_state::read_l));
m_maincpu->read_l_tristate().set_constant(0xff);
m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(8+12, 8+8);
config.set_default_layout(layout_unkeinv);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( unkeinv )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop421_us4345764", 0x0000, 0x0400, CRC(0068c3a3) SHA1(4e5fd566a5a26c066cc14623a9bd01e109ebf797) ) // typed in from patent US4345764, good print quality
ROM_END
/***************************************************************************
LJN I Took a Lickin' From a Chicken
* COP421 MCU label ~/005 COP421-NJC/N
* 11 leds, 1-bit sound, motor to a chicken on a spring
This toy includes 4 games: Tic Tac Toe, Chicken Sez, and Total Recall I/II.
known releases:
- USA: I Took a Lickin' From a Chicken
- Japan: Professor Chicken's Genius Classroom 「にわとり博士の天才教室」, published by Bandai
(not sure if it's the same ROM, or just licensed the outer shell)
***************************************************************************/
class lchicken_state : public hh_cop400_state
{
public:
lchicken_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
u8 m_motor_pos;
TIMER_DEVICE_CALLBACK_MEMBER(motor_sim_tick);
DECLARE_READ_LINE_MEMBER(motor_switch_r);
void write_l(u8 data);
void write_d(u8 data);
void write_g(u8 data);
u8 read_g();
DECLARE_WRITE_LINE_MEMBER(write_so);
DECLARE_READ_LINE_MEMBER(read_si);
void lchicken(machine_config &config);
protected:
virtual void machine_start() override;
};
void lchicken_state::machine_start()
{
hh_cop400_state::machine_start();
// zerofill, register for savestates
m_motor_pos = 0;
save_item(NAME(m_motor_pos));
}
// handlers
READ_LINE_MEMBER(lchicken_state::motor_switch_r)
{
return m_motor_pos > 0xe8; // approximation
}
TIMER_DEVICE_CALLBACK_MEMBER(lchicken_state::motor_sim_tick)
{
if (~m_inp_mux & 8)
{
m_motor_pos++;
output().set_value("motor_pos", 100 * (m_motor_pos / (float)0x100));
}
}
void lchicken_state::write_l(u8 data)
{
// L0-L3: led data
// L4-L6: led select
// L7: N/C
m_display->matrix(data >> 4 & 7, ~data & 0xf);
}
void lchicken_state::write_d(u8 data)
{
// D0-D3: input mux
// D3: motor on
m_inp_mux = data & 0xf;
output().set_value("motor_on", ~data >> 3 & 1);
}
void lchicken_state::write_g(u8 data)
{
m_g = data;
}
u8 lchicken_state::read_g()
{
// G0-G3: multiplexed inputs
return read_inputs(4, m_g);
}
WRITE_LINE_MEMBER(lchicken_state::write_so)
{
// SO: speaker out
m_speaker->level_w(state);
m_so = state;
}
READ_LINE_MEMBER(lchicken_state::read_si)
{
// SI: SO
return m_so;
}
// config
static INPUT_PORTS_START( lchicken )
PORT_START("IN.0") // D0 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.1") // D1 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.2") // D2 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.3") // D3 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(lchicken_state, motor_switch_r)
INPUT_PORTS_END
void lchicken_state::lchicken(machine_config &config)
{
/* basic machine hardware */
COP421(config, m_maincpu, 850000); // approximation - RC osc. R=12K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_l().set(FUNC(lchicken_state::write_l));
m_maincpu->write_d().set(FUNC(lchicken_state::write_d));
m_maincpu->write_g().set(FUNC(lchicken_state::write_g));
m_maincpu->read_g().set(FUNC(lchicken_state::read_g));
m_maincpu->write_so().set(FUNC(lchicken_state::write_so));
m_maincpu->read_si().set(FUNC(lchicken_state::read_si));
TIMER(config, "chicken_motor").configure_periodic(FUNC(lchicken_state::motor_sim_tick), attotime::from_msec(6000/0x100)); // ~6sec for a full rotation
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(3, 4);
config.set_default_layout(layout_lchicken);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( lchicken )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop421-njc_n", 0x0000, 0x0400, CRC(319e7985) SHA1(9714327518f65ebefe38ac7911bed2b9b9c77307) )
ROM_END
/***************************************************************************
Mattel Funtronics: Jacks
* COP410L MCU bonded directly to PCB (die label COP410L/B NGS)
* 8 LEDs, 1-bit sound
***************************************************************************/
class funjacks_state : public hh_cop400_state
{
public:
funjacks_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_d(u8 data);
void write_l(u8 data);
void write_g(u8 data);
u8 read_l();
u8 read_g();
void funjacks(machine_config &config);
};
// handlers
void funjacks_state::update_display()
{
m_display->matrix(m_d, m_l);
}
void funjacks_state::write_d(u8 data)
{
// D: led grid + input mux
m_inp_mux = data;
m_d = ~data & 0xf;
update_display();
}
void funjacks_state::write_l(u8 data)
{
// L0,L1: led state
m_l = data & 3;
update_display();
}
void funjacks_state::write_g(u8 data)
{
// G1: speaker out
m_speaker->level_w(data >> 1 & 1);
m_g = data;
}
u8 funjacks_state::read_l()
{
// L4,L5: multiplexed inputs
return read_inputs(3, 0x30) | m_l;
}
u8 funjacks_state::read_g()
{
// G1: speaker out state
// G2,G3: inputs
return m_inputs[3]->read() | (m_g & 2);
}
// config
static INPUT_PORTS_START( funjacks )
PORT_START("IN.0") // D0 port G
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_START("IN.1") // D1 port G
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 )
PORT_START("IN.2") // D2 port G
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON6 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // positioned at 1 o'clock on panel, increment clockwise
PORT_START("IN.3") // port G
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_CUSTOM ) // speaker
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START )
PORT_CONFNAME( 0x08, 0x00, DEF_STR( Players ) )
PORT_CONFSETTING( 0x00, "1" )
PORT_CONFSETTING( 0x08, "2" )
INPUT_PORTS_END
void funjacks_state::funjacks(machine_config &config)
{
/* basic machine hardware */
COP410(config, m_maincpu, 750000); // approximation - RC osc. R=47K, C=56pF
m_maincpu->set_config(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(funjacks_state::write_d));
m_maincpu->write_l().set(FUNC(funjacks_state::write_l));
m_maincpu->write_g().set(FUNC(funjacks_state::write_g));
m_maincpu->read_l().set(FUNC(funjacks_state::read_l));
m_maincpu->read_g().set(FUNC(funjacks_state::read_g));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(4, 2);
config.set_default_layout(layout_funjacks);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( funjacks )
ROM_REGION( 0x0200, "maincpu", 0 )
ROM_LOAD( "cop410l_b_ngs", 0x0000, 0x0200, CRC(863368ea) SHA1(f116cc27ae721b3a3e178fa13765808bdc275663) )
ROM_END
/***************************************************************************
Mattel Funtronics: Red Light Green Light
* COP410L MCU bonded directly to PCB (die label COP410L/B NHZ)
* 14 LEDs, 1-bit sound
known releases:
- USA: Funtronics: Red Light Green Light
- USA(rerelease): Funtronics: Hot Wheels Drag Race
***************************************************************************/
class funrlgl_state : public hh_cop400_state
{
public:
funrlgl_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_d(u8 data);
void write_l(u8 data);
void write_g(u8 data);
void funrlgl(machine_config &config);
};
// handlers
void funrlgl_state::update_display()
{
m_display->matrix(m_d, m_l);
}
void funrlgl_state::write_d(u8 data)
{
// D: led grid
m_d = ~data & 0xf;
update_display();
}
void funrlgl_state::write_l(u8 data)
{
// L0-L3: led state
// L4-L7: N/C
m_l = ~data & 0xf;
update_display();
}
void funrlgl_state::write_g(u8 data)
{
// G3: speaker out
m_speaker->level_w(data >> 3 & 1);
}
// config
static INPUT_PORTS_START( funrlgl )
PORT_START("IN.0") // port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_CONFNAME( 0x04, 0x04, DEF_STR( Difficulty ) )
PORT_CONFSETTING( 0x04, "1" )
PORT_CONFSETTING( 0x00, "2" )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("RESET")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START ) PORT_CHANGED_MEMBER(DEVICE_SELF, hh_cop400_state, reset_button, 0)
INPUT_PORTS_END
void funrlgl_state::funrlgl(machine_config &config)
{
/* basic machine hardware */
COP410(config, m_maincpu, 750000); // approximation - RC osc. R=51K, C=91pF
m_maincpu->set_config(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(funrlgl_state::write_d));
m_maincpu->write_l().set(FUNC(funrlgl_state::write_l));
m_maincpu->read_l_tristate().set_constant(0xff);
m_maincpu->write_g().set(FUNC(funrlgl_state::write_g));
m_maincpu->read_g().set_ioport("IN.0");
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(4, 4);
m_display->set_bri_levels(0.01, 0.1); // top led is brighter
config.set_default_layout(layout_funrlgl);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( funrlgl )
ROM_REGION( 0x0200, "maincpu", 0 )
ROM_LOAD( "cop410l_b_nhz", 0x0000, 0x0200, CRC(4065c3ce) SHA1(f0bc8125d922949e0d7ab1ba89c805a836d20e09) )
ROM_END
/***************************************************************************
Mattel Dalla$ (J.R. handheld)
* COP444 MCU label COP444L-HYN/N
* 8-digit 7seg display, 1-bit sound
This is a board game, only the handheld device is emulated here.
***************************************************************************/
class mdallas_state : public hh_cop400_state
{
public:
mdallas_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_l(u8 data);
void write_d(u8 data);
void write_g(u8 data);
u8 read_in();
void mdallas(machine_config &config);
};
// handlers
void mdallas_state::update_display()
{
m_display->matrix(~(m_d << 4 | m_g), m_l);
}
void mdallas_state::write_l(u8 data)
{
// L: digit segment data
m_l = data;
update_display();
}
void mdallas_state::write_d(u8 data)
{
// D: select digit, input mux high
m_inp_mux = (m_inp_mux & 0xf) | (data << 4 & 3);
m_d = data & 0xf;
update_display();
}
void mdallas_state::write_g(u8 data)
{
// G: select digit, input mux low
m_inp_mux = (m_inp_mux & 0x30) | (data & 0xf);
m_g = data & 0xf;
update_display();
}
u8 mdallas_state::read_in()
{
// IN: multiplexed inputs
return read_inputs(6, 0xf);
}
// config
/* physical button layout and labels is like this:
< ON> [YES] [NO] [NEXT]
[<W] [^N] [Sv] [E>]
[7] [8] [9] [STATUS]
[4] [5] [6] [ASSETS]
[1] [2] [3] [START]
[CLEAR] [0] [MOVE] [ENTER]
*/
static INPUT_PORTS_START( mdallas )
PORT_START("IN.0") // G0 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CODE(KEYCODE_DEL) PORT_NAME("Clear")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("Move")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter")
PORT_START("IN.1") // G1 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_S) PORT_NAME("Start")
PORT_START("IN.2") // G2 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("Assets")
PORT_START("IN.3") // G3 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_T) PORT_NAME("Status")
PORT_START("IN.4") // D0 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("West") // W
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_X) PORT_NAME("Next")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("East") // E
PORT_START("IN.5") // D1 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_N) PORT_NAME("No")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Y) PORT_NAME("Yes")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("South") // S
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("North") // N
INPUT_PORTS_END
void mdallas_state::mdallas(machine_config &config)
{
/* basic machine hardware */
COP444L(config, m_maincpu, 1000000); // approximation - RC osc. R=57K, C=101pF
m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_l().set(FUNC(mdallas_state::write_l));
m_maincpu->write_d().set(FUNC(mdallas_state::write_d));
m_maincpu->write_g().set(FUNC(mdallas_state::write_g));
m_maincpu->read_in().set(FUNC(mdallas_state::read_in));
m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(8, 8);
m_display->set_segmask(0xff, 0xff);
config.set_default_layout(layout_mdallas);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( mdallas )
ROM_REGION( 0x0800, "maincpu", 0 )
ROM_LOAD( "copl444l-hyn_n", 0x0000, 0x0800, CRC(7848b78c) SHA1(778d24512180892f58c49df3c72ca77b2618d63b) )
ROM_END
/***************************************************************************
Milton Bradley Plus One
* COP410L MCU in 8-pin DIP, label ~/029 MM 57405 (die label COP410L/B NNE)
* orientation sensor(4 directions), 1-bit sound
This is a board game, each player needs to rotate a triangular pyramid
shaped piece the same as the previous player, plus 1.
***************************************************************************/
class plus1_state : public hh_cop400_state
{
public:
plus1_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void write_d(u8 data);
void write_l(u8 data);
u8 read_l();
void plus1(machine_config &config);
};
// handlers
void plus1_state::write_d(u8 data)
{
// D0?: speaker out
m_speaker->level_w(data & 1);
}
void plus1_state::write_l(u8 data)
{
m_l = data;
}
u8 plus1_state::read_l()
{
// L: IN.1, mask with output
return m_inputs[1]->read() & m_l;
}
// config
static INPUT_PORTS_START( plus1 )
PORT_START("IN.0") // port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Sensor Position 3")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Sensor Position 1")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.1") // port L
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Sensor Position 4")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Sensor Position 2")
PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
void plus1_state::plus1(machine_config &config)
{
/* basic machine hardware */
COP410(config, m_maincpu, 1000000); // approximation - RC osc. R=51K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(plus1_state::write_d));
m_maincpu->read_g().set_ioport("IN.0");
m_maincpu->write_l().set(FUNC(plus1_state::write_l));
m_maincpu->read_l().set(FUNC(plus1_state::read_l));
/* no visual feedback! */
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( plus1 )
ROM_REGION( 0x0200, "maincpu", 0 )
ROM_LOAD( "cop410l_b_nne", 0x0000, 0x0200, CRC(d861b80c) SHA1(4652f8ee0dd4c3c48b625285bb4f094d96434071) )
ROM_END
/***************************************************************************
Milton Bradley Electronic Lightfight
* COP421L MCU label /B119 COP421L-HLA/N
* LED matrix, 1-bit sound
Xbox-shaped electronic game for 2 or more players, with long diagonal buttons
next to each outer LED. The main object of the game is to pinpoint a light
by pressing 2 buttons. To start, press a skill-level button(P2 button 7/8/9)
after selecting a game mode(P1 button 6-10).
The game variations are:
1: LightFight
2: NightFight
3: RiteSite
4: QuiteBrite
5: RightLight
***************************************************************************/
class lightfgt_state : public hh_cop400_state
{
public:
lightfgt_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
DECLARE_WRITE_LINE_MEMBER(write_so);
void write_d(u8 data);
void write_l(u8 data);
u8 read_g();
void lightfgt(machine_config &config);
};
// handlers
void lightfgt_state::update_display()
{
u8 grid = (m_so | m_d << 1) ^ 0x1f;
m_display->matrix(grid, m_l);
}
WRITE_LINE_MEMBER(lightfgt_state::write_so)
{
// SO: led grid 0 (and input mux)
m_so = state;
update_display();
}
void lightfgt_state::write_d(u8 data)
{
// D: led grid 1-4 (and input mux)
m_d = data;
update_display();
}
void lightfgt_state::write_l(u8 data)
{
// L0-L4: led state
// L5-L7: N/C
m_l = data & 0x1f;
update_display();
}
u8 lightfgt_state::read_g()
{
// G: multiplexed inputs
m_inp_mux = m_d << 1 | m_so;
return read_inputs(5, 0xf);
}
// config
static INPUT_PORTS_START( lightfgt )
PORT_START("IN.0") // SO port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) // note: button 1 is on the left side from player perspective
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_COCKTAIL
PORT_START("IN.1") // D0 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_COCKTAIL
PORT_START("IN.2") // D1 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_COCKTAIL
PORT_START("IN.3") // D2 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON9 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_COCKTAIL
PORT_START("IN.4") // D3 port G
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON10 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_COCKTAIL
INPUT_PORTS_END
void lightfgt_state::lightfgt(machine_config &config)
{
/* basic machine hardware */
COP421(config, m_maincpu, 950000); // approximation - RC osc. R=82K, C=56pF
m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_so().set(FUNC(lightfgt_state::write_so));
m_maincpu->write_d().set(FUNC(lightfgt_state::write_d));
m_maincpu->write_l().set(FUNC(lightfgt_state::write_l));
m_maincpu->write_sk().set(m_speaker, FUNC(speaker_sound_device::level_w));
m_maincpu->read_g().set(FUNC(lightfgt_state::read_g));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(5, 5);
config.set_default_layout(layout_lightfgt);
/* sound hardware */
SPEAKER(config, "mono").front_center();
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
}
// roms
ROM_START( lightfgt )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop421l-hla_n", 0x0000, 0x0400, CRC(aceb2d65) SHA1(2328cbb195faf93c575f3afa3a1fe0079180edd7) )
ROM_END
/***************************************************************************
Milton Bradley Electronic Battleship (1982 version)
* COP420 MCU label COP420-JWE/N
see hh_tms1k.cpp bship driver for more information
***************************************************************************/
class bship82_state : public hh_cop400_state
{
public:
bship82_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void write_d(u8 data);
u8 read_l();
u8 read_in();
DECLARE_WRITE_LINE_MEMBER(write_so);
void bship82(machine_config &config);
};
// handlers
void bship82_state::write_d(u8 data)
{
// D: input mux
m_inp_mux = data;
}
u8 bship82_state::read_l()
{
// L: multiplexed inputs
return read_inputs(4, 0xff);
}
u8 bship82_state::read_in()
{
// IN: multiplexed inputs
return read_inputs(4, 0xf00) >> 8;
}
WRITE_LINE_MEMBER(bship82_state::write_so)
{
// SO: led
m_display->matrix(1, state);
}
// config
static INPUT_PORTS_START( bship82 )
PORT_START("IN.0") // D0 ports L,IN
PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("P1 Clear Last Entry") // CLE
PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("P1 A")
PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_NAME("P1 B")
PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_NAME("P1 C")
PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_NAME("P1 D")
PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("P1 E")
PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_NAME("P1 F")
PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_NAME("P1 G")
PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_H) PORT_NAME("P1 H")
PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_I) PORT_NAME("P1 I")
PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_J) PORT_NAME("P1 J")
PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.1") // D1 ports L,IN
PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_DEL) PORT_NAME("P1 Clear Memory") // CM
PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("P1 1")
PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("P1 2")
PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("P1 3")
PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("P1 4")
PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("P1 5")
PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("P1 6")
PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("P1 7")
PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("P1 8")
PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("P1 9")
PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("P1 10")
PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("P1 Fire")
PORT_START("IN.2") // D2 ports L,IN
PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Clear Last Entry") // CLE
PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 A")
PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 B")
PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 C")
PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 D")
PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 E")
PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 F")
PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 G")
PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 H")
PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 I")
PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 J")
PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN.3") // D3 ports L,IN
PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Clear Memory") // CM
PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 1")
PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 2")
PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 3")
PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 4")
PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 5")
PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 6")
PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 7")
PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 8")
PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 9")
PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 10")
PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Fire")
PORT_START("IN.4") // SI
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_CODE(KEYCODE_F1) PORT_NAME("Load/Go") // switch
INPUT_PORTS_END
/*
http://www.seanriddle.com/bship82.txt
21 G0 3.9K resistor to speaker transistor base
22 G1 2.2K resistor to speaker transistor base
23 G2 1.0K resistor to speaker transistor base
24 G3 speaker transistor base tied high 4.7K
speaker connection
2N3904 transistor:
emitter to 10ohm resistor to ground
collector to 68ohm resistor to speaker (other speaker terminal to VCC)
base pulled high with 4.7K resistor, connects directly to G3, 1K resistor to G2,
2.2K resistor to G1, 3.9K resistor to G0
*/
void bship82_state::bship82(machine_config &config)
{
/* basic machine hardware */
COP420(config, m_maincpu, 750000); // approximation - RC osc. R=14K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(bship82_state::write_d));
m_maincpu->write_g().set("dac", FUNC(dac_byte_interface::data_w));
m_maincpu->read_l().set(FUNC(bship82_state::read_l));
m_maincpu->read_in().set(FUNC(bship82_state::read_in));
m_maincpu->write_so().set(FUNC(bship82_state::write_so));
m_maincpu->read_si().set_ioport("IN.4");
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(1, 1);
config.set_default_layout(layout_bship82);
/* sound hardware */
SPEAKER(config, "mono").front_center();
DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE(config, "dac").add_route(ALL_OUTPUTS, "mono", 0.125); // see above
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
// roms
ROM_START( bship82 )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop420-jwe_n", 0x0000, 0x0400, CRC(5ea8111a) SHA1(34931463b806b48dce4f8ae2361512510bae0ebf) )
ROM_END
/***************************************************************************
National Semiconductor QuizKid Racer (COP420 version)
* COP420 MCU label COP420-NPG/N
* 8-digit 7seg led display(1 custom digit), 1 green led, no sound
This is the COP420 version, the first release was on a MM5799 MCU.
***************************************************************************/
class qkracer_state : public hh_cop400_state
{
public:
qkracer_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_d(u8 data);
void write_g(u8 data);
void write_l(u8 data);
u8 read_in();
DECLARE_WRITE_LINE_MEMBER(write_sk);
void qkracer(machine_config &config);
};
// handlers
void qkracer_state::update_display()
{
m_display->matrix(~(m_d | m_g << 4 | m_sk << 8), m_l);
}
void qkracer_state::write_d(u8 data)
{
// D: select digit, D3: input mux high bit
m_inp_mux = (m_inp_mux & 0xf) | (data << 1 & 0x10);
m_d = data & 0xf;
update_display();
}
void qkracer_state::write_g(u8 data)
{
// G: select digit, input mux
m_inp_mux = (m_inp_mux & 0x10) | (data & 0xf);
m_g = data & 0xf;
update_display();
}
void qkracer_state::write_l(u8 data)
{
// L0-L6: digit segment data
m_l = data & 0x7f;
update_display();
}
u8 qkracer_state::read_in()
{
// IN: multiplexed inputs
return read_inputs(5, 0xf);
}
WRITE_LINE_MEMBER(qkracer_state::write_sk)
{
// SK: green led
m_sk = state;
update_display();
}
// config
static INPUT_PORTS_START( qkracer )
PORT_START("IN.0") // G0 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_SLASH_PAD) PORT_NAME(UTF8_DIVIDE)
PORT_START("IN.1") // G1 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME(UTF8_MULTIPLY)
PORT_START("IN.2") // G2 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("-")
PORT_START("IN.3") // G3 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS) PORT_NAME("Slow")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("Fast")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("+")
PORT_START("IN.4") // D3 port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("Amateur")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("Pro")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Complex")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("Tables")
INPUT_PORTS_END
void qkracer_state::qkracer(machine_config &config)
{
/* basic machine hardware */
COP420(config, m_maincpu, 1000000); // approximation - RC osc. R=47K, C=100pF
m_maincpu->set_config(COP400_CKI_DIVISOR_32, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(qkracer_state::write_d));
m_maincpu->write_g().set(FUNC(qkracer_state::write_g));
m_maincpu->write_l().set(FUNC(qkracer_state::write_l));
m_maincpu->read_in().set(FUNC(qkracer_state::read_in));
m_maincpu->write_sk().set(FUNC(qkracer_state::write_sk));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(9, 7);
m_display->set_segmask(0xdf, 0x7f);
m_display->set_segmask(0x20, 0x41); // equals sign
config.set_default_layout(layout_qkracer);
/* no sound! */
}
// roms
ROM_START( qkracer )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop420-npg_n", 0x0000, 0x0400, CRC(17f8e538) SHA1(23d1a1819e6ba552d8da83da2948af1cf5b13d5b) )
ROM_END
/***************************************************************************
Select Merchandise Video Challenger
* COP420 MCU label COP420-TDX/N
* 6-digit 7seg led display, 3 other leds, 4-bit sound
This is a lightgun with scorekeeping. The "games" themselves were released
on VHS tapes. To determine scoring, the lightgun detects strobe lighting
from objects in the video.
known releases:
- Japan: Video Challenger, published by Takara
- UK: Video Challenger, published by Bandai
- Canada: Video Challenger, published by Irwin
***************************************************************************/
class vidchal_state : public hh_cop400_state
{
public:
vidchal_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_cop400_state(mconfig, type, tag)
{ }
void update_display();
void write_d(u8 data);
void write_l(u8 data);
DECLARE_WRITE_LINE_MEMBER(write_sk);
void vidchal(machine_config &config);
};
// handlers
void vidchal_state::update_display()
{
m_display->matrix(m_d | m_sk << 6, m_l);
}
void vidchal_state::write_d(u8 data)
{
// D: CD4028BE to digit select
m_d = 1 << data & 0x3f;
update_display();
}
void vidchal_state::write_l(u8 data)
{
// L: digit segment data
m_l = bitswap<8>(data,0,3,1,5,4,7,2,6);
update_display();
}
WRITE_LINE_MEMBER(vidchal_state::write_sk)
{
// SK: hit led
m_sk = state;
update_display();
}
// config
static INPUT_PORTS_START( vidchal )
PORT_START("IN.0") // port IN
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_NAME("Light Sensor")
INPUT_PORTS_END
void vidchal_state::vidchal(machine_config &config)
{
/* basic machine hardware */
COP420(config, m_maincpu, 900000); // approximation
m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
m_maincpu->write_d().set(FUNC(vidchal_state::write_d));
m_maincpu->write_g().set("dac", FUNC(dac_byte_interface::data_w));
m_maincpu->write_l().set(FUNC(vidchal_state::write_l));
m_maincpu->read_in().set_ioport("IN.0");
m_maincpu->write_sk().set(FUNC(vidchal_state::write_sk));
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(6+1, 8);
m_display->set_segmask(0x3f, 0xff);
config.set_default_layout(layout_vidchal);
/* sound hardware */
SPEAKER(config, "mono").front_center();
DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE(config, "dac").add_route(ALL_OUTPUTS, "mono", 0.125); // unknown DAC
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
}
// roms
ROM_START( vidchal )
ROM_REGION( 0x0400, "maincpu", 0 )
ROM_LOAD( "cop420-tdx_n", 0x0000, 0x0400, CRC(c9bd041c) SHA1(ab0dcaf4741620fa4c28ab75337a23d646af7626) )
ROM_END
} // anonymous namespace
/***************************************************************************
Game driver(s)
***************************************************************************/
// YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1979, ctstein, 0, 0, ctstein, ctstein, ctstein_state, empty_init, "Castle Toy", "Einstein (Castle Toy)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1980, h2hbaskbc, h2hbaskb, 0, h2hbaskbc, h2hbaskbc, h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Basketball (COP420L version)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, h2hhockeyc, h2hhockey, 0, h2hhockeyc, h2hhockeyc, h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Hockey (COP420L version)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, h2hsoccerc, 0, 0, h2hsoccerc, h2hsoccerc, h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Soccer (COP420L version)", MACHINE_SUPPORTS_SAVE )
CONS( 1981, einvaderc, einvader, 0, einvaderc, einvaderc, einvaderc_state, empty_init, "Entex", "Space Invader (Entex, COP444L version)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, unkeinv, 0, 0, unkeinv, unkeinv, unkeinv_state, empty_init, "Gordon Barlow Design", "unknown electronic Space Invaders game (patent)", MACHINE_SUPPORTS_SAVE )
CONS( 1980, lchicken, 0, 0, lchicken, lchicken, lchicken_state, empty_init, "LJN", "I Took a Lickin' From a Chicken", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_MECHANICAL )
CONS( 1979, funjacks, 0, 0, funjacks, funjacks, funjacks_state, empty_init, "Mattel", "Funtronics: Jacks", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1979, funrlgl, 0, 0, funrlgl, funrlgl, funrlgl_state, empty_init, "Mattel", "Funtronics: Red Light Green Light", MACHINE_SUPPORTS_SAVE )
CONS( 1981, mdallas, 0, 0, mdallas, mdallas, mdallas_state, empty_init, "Mattel", "Dalla$ (J.R. handheld)", MACHINE_SUPPORTS_SAVE ) // ***
CONS( 1980, plus1, 0, 0, plus1, plus1, plus1_state, empty_init, "Milton Bradley", "Plus One", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS ) // ***
CONS( 1981, lightfgt, 0, 0, lightfgt, lightfgt, lightfgt_state, empty_init, "Milton Bradley", "Electronic Lightfight - The Games of Dueling Lights", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
CONS( 1982, bship82, bship, 0, bship82, bship82, bship82_state, empty_init, "Milton Bradley", "Electronic Battleship (1982 version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // ***
CONS( 1978, qkracer, 0, 0, qkracer, qkracer, qkracer_state, empty_init, "National Semiconductor", "QuizKid Racer (COP420 version)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW )
CONS( 1987, vidchal, 0, 0, vidchal, vidchal, vidchal_state, empty_init, "Select Merchandise", "Video Challenger", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING )
// ***: As far as MAME is concerned, the game is emulated fine. But for it to be playable, it requires interaction
// with other, unemulatable, things eg. game board/pieces, playing cards, pen & paper, etc.