1 // license:BSD-3-Clause
2 // copyright-holders:hap
3 // thanks-to:Sean Riddle
4 /***************************************************************************
5 
6   National Semiconductor COP400 MCU handhelds or other simple devices,
7   mostly LED electronic games/toys.
8 
9   TODO:
10   - why does h2hbaskbc(and clones) need a workaround on writing L pins?
11   - plus1: which sensor position is which colour?
12   - vidchal: Add screen and gun cursor with brightness detection callback,
13     and softwarelist for the video tapes. We'd also need a VHS player device.
14     The emulated lightgun itself appears to be working fine(eg. add a 30hz
15     timer to IN.3 to score +100)
16 
17 ***************************************************************************/
18 
19 #include "emu.h"
20 #include "cpu/cop400/cop400.h"
21 #include "video/pwm.h"
22 #include "machine/timer.h"
23 #include "sound/spkrdev.h"
24 #include "sound/dac.h"
25 #include "screen.h"
26 #include "speaker.h"
27 
28 // internal artwork
29 #include "bship82.lh" // clickable
30 #include "ctstein.lh" // clickable
31 #include "einvaderc.lh"
32 #include "funjacks.lh" // clickable
33 #include "funrlgl.lh"
34 #include "h2hbaskbc.lh"
35 #include "h2hhockeyc.lh"
36 #include "h2hsoccerc.lh"
37 #include "lchicken.lh" // clickable
38 #include "lightfgt.lh" // clickable
39 #include "mdallas.lh"
40 #include "qkracer.lh"
41 #include "unkeinv.lh"
42 #include "vidchal.lh"
43 
44 //#include "hh_cop400_test.lh" // common test-layout - use external artwork
45 
46 
47 class hh_cop400_state : public driver_device
48 {
49 public:
hh_cop400_state(const machine_config & mconfig,device_type type,const char * tag)50 	hh_cop400_state(const machine_config &mconfig, device_type type, const char *tag) :
51 		driver_device(mconfig, type, tag),
52 		m_maincpu(*this, "maincpu"),
53 		m_display(*this, "display"),
54 		m_speaker(*this, "speaker"),
55 		m_inputs(*this, "IN.%u", 0)
56 	{ }
57 
58 	// devices
59 	required_device<cop400_cpu_device> m_maincpu;
60 	optional_device<pwm_display_device> m_display;
61 	optional_device<speaker_sound_device> m_speaker;
62 	optional_ioport_array<6> m_inputs; // max 6
63 
64 	// misc common
65 	u8 m_l;                         // MCU port L write data
66 	u8 m_g;                         // MCU port G write data
67 	u8 m_d;                         // MCU port D write data
68 	int m_so;                       // MCU SO line state
69 	int m_sk;                       // MCU SK line state
70 	u16 m_inp_mux;                  // multiplexed inputs mask
71 
72 	u16 read_inputs(int columns, u16 colmask = ~0);
73 	virtual DECLARE_INPUT_CHANGED_MEMBER(reset_button);
74 
75 protected:
76 	virtual void machine_start() override;
77 	virtual void machine_reset() override;
78 };
79 
80 
81 // machine start/reset
82 
machine_start()83 void hh_cop400_state::machine_start()
84 {
85 	// zerofill
86 	m_l = 0;
87 	m_g = 0;
88 	m_d = 0;
89 	m_so = 0;
90 	m_sk = 0;
91 	m_inp_mux = ~0;
92 
93 	// register for savestates
94 	save_item(NAME(m_l));
95 	save_item(NAME(m_g));
96 	save_item(NAME(m_d));
97 	save_item(NAME(m_so));
98 	save_item(NAME(m_sk));
99 	save_item(NAME(m_inp_mux));
100 }
101 
machine_reset()102 void hh_cop400_state::machine_reset()
103 {
104 }
105 
106 
107 
108 /***************************************************************************
109 
110   Helper Functions
111 
112 ***************************************************************************/
113 
114 // generic input handlers
115 
read_inputs(int columns,u16 colmask)116 u16 hh_cop400_state::read_inputs(int columns, u16 colmask)
117 {
118 	// active low
119 	u16 ret = ~0 & colmask;
120 
121 	// read selected input rows
122 	for (int i = 0; i < columns; i++)
123 		if (~m_inp_mux >> i & 1)
124 			ret &= m_inputs[i]->read();
125 
126 	return ret;
127 }
128 
INPUT_CHANGED_MEMBER(hh_cop400_state::reset_button)129 INPUT_CHANGED_MEMBER(hh_cop400_state::reset_button)
130 {
131 	// when an input is directly wired to MCU reset pin
132 	m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
133 }
134 
135 
136 
137 /***************************************************************************
138 
139   Minidrivers (subclass, I/O, Inputs, Machine Config, ROM Defs)
140 
141 ***************************************************************************/
142 
143 namespace {
144 
145 /***************************************************************************
146 
147   Castle Toy Einstein
148   * COP421 MCU label ~/927 COP421-NEZ/N
149   * 4 lamps, 1-bit sound
150 
151   This is a Simon clone, the tones are not harmonic. Two models exist, each
152   with a different batteries setup, assume they're same otherwise.
153 
154 ***************************************************************************/
155 
156 class ctstein_state : public hh_cop400_state
157 {
158 public:
ctstein_state(const machine_config & mconfig,device_type type,const char * tag)159 	ctstein_state(const machine_config &mconfig, device_type type, const char *tag) :
160 		hh_cop400_state(mconfig, type, tag)
161 	{ }
162 
163 	void write_g(u8 data);
164 	void write_l(u8 data);
165 	u8 read_l();
166 	void ctstein(machine_config &config);
167 };
168 
169 // handlers
170 
write_g(u8 data)171 void ctstein_state::write_g(u8 data)
172 {
173 	// G0-G2: input mux
174 	m_inp_mux = data & 7;
175 }
176 
write_l(u8 data)177 void ctstein_state::write_l(u8 data)
178 {
179 	// L0-L3: button lamps
180 	m_display->matrix(1, data & 0xf);
181 }
182 
read_l()183 u8 ctstein_state::read_l()
184 {
185 	// L4-L7: multiplexed inputs
186 	return read_inputs(3, 0xf) << 4 | 0xf;
187 }
188 
189 // config
190 
191 static INPUT_PORTS_START( ctstein )
192 	PORT_START("IN.0") // G0 port L
DEF_STR(Difficulty)193 	PORT_CONFNAME( 0x0f, 0x01^0x0f, DEF_STR( Difficulty ) )
194 	PORT_CONFSETTING(    0x01^0x0f, "1" )
195 	PORT_CONFSETTING(    0x02^0x0f, "2" )
196 	PORT_CONFSETTING(    0x04^0x0f, "3" )
197 	PORT_CONFSETTING(    0x08^0x0f, "4" )
198 
199 	PORT_START("IN.1") // G1 port L
200 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START )
201 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("Best Score")
202 	PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
203 
204 	PORT_START("IN.2") // G2 port L
205 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Red Button")
206 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Yellow Button")
207 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Green Button")
208 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Blue Button")
209 INPUT_PORTS_END
210 
211 void ctstein_state::ctstein(machine_config &config)
212 {
213 	/* basic machine hardware */
214 	COP421(config, m_maincpu, 850000); // approximation - RC osc. R=12K, C=100pF
215 	m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
216 	m_maincpu->write_g().set(FUNC(ctstein_state::write_g));
217 	m_maincpu->write_l().set(FUNC(ctstein_state::write_l));
218 	m_maincpu->write_sk().set(m_speaker, FUNC(speaker_sound_device::level_w));
219 	m_maincpu->read_l().set(FUNC(ctstein_state::read_l));
220 
221 	/* video hardware */
222 	PWM_DISPLAY(config, m_display).set_size(1, 4);
223 	config.set_default_layout(layout_ctstein);
224 
225 	/* sound hardware */
226 	SPEAKER(config, "mono").front_center();
227 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
228 }
229 
230 // roms
231 
232 ROM_START( ctstein )
233 	ROM_REGION( 0x0400, "maincpu", 0 )
234 	ROM_LOAD( "cop421-nez_n", 0x0000, 0x0400, CRC(16148e03) SHA1(b2b74891d36813d9a1eefd56a925054997c4b7f7) ) // 2nd half empty
235 ROM_END
236 
237 
238 
239 
240 
241 /***************************************************************************
242 
243   Coleco Head to Head: Electronic Basketball/Hockey/Soccer (model 2150/2160/2170)
244   * COP420 MCU label COP420L-NEZ/N
245   * 2-digit 7seg display, 41 other leds, 1-bit sound
246 
247   3 Head to Head games were released using this MCU/ROM. They play very much
248   the same, only differing on game time. The PCB is pre-configured on G1+IN2
249   and IN3 to select the game.
250 
251   An earlier revision of this runs on TMS1000, see hh_tms1k.cpp driver. Model
252   numbers are the same. From the outside, an easy way to spot the difference is
253   the Start/Display button: TMS1000 version button label is D, COP420 one is a *.
254   The COP420 version also plays much slower.
255 
256 ***************************************************************************/
257 
258 class h2hbaskbc_state : public hh_cop400_state
259 {
260 public:
h2hbaskbc_state(const machine_config & mconfig,device_type type,const char * tag)261 	h2hbaskbc_state(const machine_config &mconfig, device_type type, const char *tag) :
262 		hh_cop400_state(mconfig, type, tag)
263 	{ }
264 
265 	void write_d(u8 data);
266 	void write_g(u8 data);
267 	void write_l(u8 data);
268 	u8 read_in();
269 	void h2hsoccerc(machine_config &config);
270 	void h2hbaskbc(machine_config &config);
271 	void h2hhockeyc(machine_config &config);
272 };
273 
274 // handlers
275 
write_d(u8 data)276 void h2hbaskbc_state::write_d(u8 data)
277 {
278 	// D: led select
279 	m_d = data & 0xf;
280 }
281 
write_g(u8 data)282 void h2hbaskbc_state::write_g(u8 data)
283 {
284 	// G: led select, input mux
285 	m_inp_mux = data;
286 	m_g = data & 0xf;
287 }
288 
write_l(u8 data)289 void h2hbaskbc_state::write_l(u8 data)
290 {
291 	// D2,D3 double as multiplexer
292 	u16 mask = ((m_d >> 2 & 1) * 0x00ff) | ((m_d >> 3 & 1) * 0xff00);
293 	u16 sel = (m_g | m_d << 4 | m_g << 8 | m_d << 12) & mask;
294 
295 	// D2+G0,G1 are 7segs
296 	// L0-L6: digit segments A-G, L0-L4: led data
297 	m_display->matrix(sel, data);
298 }
299 
read_in()300 u8 h2hbaskbc_state::read_in()
301 {
302 	// IN: multiplexed inputs
303 	return read_inputs(4, 7) | (m_inputs[4]->read() & 8);
304 }
305 
306 // config
307 
308 static INPUT_PORTS_START( h2hbaskbc )
309 	PORT_START("IN.0") // G0 port IN
310 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_16WAY PORT_NAME("P1 Pass CW") // clockwise
311 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_16WAY PORT_NAME("P1 Pass CCW") // counter-clockwise
DEF_STR(Players)312 	PORT_CONFNAME( 0x04, 0x04, DEF_STR( Players ) )
313 	PORT_CONFSETTING(    0x04, "1" )
314 	PORT_CONFSETTING(    0x00, "2" )
315 
316 	PORT_START("IN.1") // G1 port IN
317 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("P1 Shoot")
318 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start/Display")
319 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_CUSTOM ) // factory set
320 
321 	PORT_START("IN.2") // G2 port IN
322 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_COCKTAIL PORT_16WAY PORT_NAME("P2 Defense Right")
323 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_COCKTAIL PORT_16WAY PORT_NAME("P2 Defense Left")
324 	PORT_CONFNAME( 0x04, 0x04, DEF_STR( Difficulty ) )
325 	PORT_CONFSETTING(    0x04, "1" )
326 	PORT_CONFSETTING(    0x00, "2" )
327 
328 	PORT_START("IN.3") // G3 port IN
329 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
330 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
331 	PORT_CONFNAME( 0x04, 0x04, "Factory Test" )
332 	PORT_CONFSETTING(    0x04, DEF_STR( Off ) )
333 	PORT_CONFSETTING(    0x00, DEF_STR( On ) )
334 
335 	PORT_START("IN.4") // IN3 (factory set)
336 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM )
337 INPUT_PORTS_END
338 
339 static INPUT_PORTS_START( h2hhockeyc )
340 	PORT_INCLUDE( h2hbaskbc )
341 
342 	PORT_MODIFY("IN.3")
343 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL PORT_NAME("P2 Goalie Right")
344 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL PORT_NAME("P2 Goalie Left")
345 
346 	PORT_MODIFY("IN.4")
347 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM )
348 INPUT_PORTS_END
349 
350 static INPUT_PORTS_START( h2hsoccerc )
351 	PORT_INCLUDE( h2hhockeyc )
352 
353 	PORT_MODIFY("IN.1")
354 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_CUSTOM )
355 INPUT_PORTS_END
356 
357 void h2hbaskbc_state::h2hbaskbc(machine_config &config)
358 {
359 	/* basic machine hardware */
360 	COP420(config, m_maincpu, 1000000); // approximation - RC osc. R=43K, C=101pF
361 	m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
362 	m_maincpu->write_d().set(FUNC(h2hbaskbc_state::write_d));
363 	m_maincpu->write_g().set(FUNC(h2hbaskbc_state::write_g));
364 	m_maincpu->write_l().set(FUNC(h2hbaskbc_state::write_l));
365 	m_maincpu->read_in().set(FUNC(h2hbaskbc_state::read_in));
366 	m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
367 
368 	/* video hardware */
369 	PWM_DISPLAY(config, m_display).set_size(16, 7);
370 	m_display->set_segmask(3, 0x7f);
371 	config.set_default_layout(layout_h2hbaskbc);
372 
373 	/* sound hardware */
374 	SPEAKER(config, "mono").front_center();
375 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
376 }
377 
h2hhockeyc(machine_config & config)378 void h2hbaskbc_state::h2hhockeyc(machine_config &config)
379 {
380 	h2hbaskbc(config);
381 	config.set_default_layout(layout_h2hhockeyc);
382 }
383 
h2hsoccerc(machine_config & config)384 void h2hbaskbc_state::h2hsoccerc(machine_config &config)
385 {
386 	h2hbaskbc(config);
387 	config.set_default_layout(layout_h2hsoccerc);
388 }
389 
390 // roms
391 
392 ROM_START( h2hbaskbc )
393 	ROM_REGION( 0x0400, "maincpu", 0 )
394 	ROM_LOAD( "cop420l-nmy", 0x0000, 0x0400, CRC(87152509) SHA1(acdb869b65d49b3b9855a557ed671cbbb0f61e2c) )
395 ROM_END
396 
397 #define rom_h2hhockeyc rom_h2hbaskbc // dumped from Basketball
398 #define rom_h2hsoccerc rom_h2hbaskbc // "
399 
400 
401 
402 
403 
404 /***************************************************************************
405 
406   Entex Space Invader
407   * COP444L MCU label /B138 COPL444-HRZ/N INV II (die label HRZ COP 444L/A)
408   * 3 7seg LEDs, LED matrix and overlay mask, 1-bit sound
409 
410   The first version was on TMS1100 (see hh_tms1k.c), this is the reprogrammed
411   second release with a gray case instead of black.
412 
413 ***************************************************************************/
414 
415 class einvaderc_state : public hh_cop400_state
416 {
417 public:
einvaderc_state(const machine_config & mconfig,device_type type,const char * tag)418 	einvaderc_state(const machine_config &mconfig, device_type type, const char *tag) :
419 		hh_cop400_state(mconfig, type, tag)
420 	{ }
421 
422 	void update_display();
423 	void write_d(u8 data);
424 	void write_g(u8 data);
425 	DECLARE_WRITE_LINE_MEMBER(write_sk);
426 	DECLARE_WRITE_LINE_MEMBER(write_so);
427 	void write_l(u8 data);
428 	void einvaderc(machine_config &config);
429 };
430 
431 // handlers
432 
update_display()433 void einvaderc_state::update_display()
434 {
435 	u8 l = bitswap<8>(m_l,7,6,0,1,2,3,4,5);
436 	u16 grid = (m_d | m_g << 4 | m_sk << 8 | m_so << 9) ^ 0x0ff;
437 
438 	m_display->matrix(grid, l);
439 }
440 
write_d(u8 data)441 void einvaderc_state::write_d(u8 data)
442 {
443 	// D: led grid 0-3 (D0-D2 are 7segs)
444 	m_d = data;
445 	update_display();
446 }
447 
write_g(u8 data)448 void einvaderc_state::write_g(u8 data)
449 {
450 	// G: led grid 4-7
451 	m_g = data;
452 	update_display();
453 }
454 
WRITE_LINE_MEMBER(einvaderc_state::write_sk)455 WRITE_LINE_MEMBER(einvaderc_state::write_sk)
456 {
457 	// SK: speaker out + led grid 8
458 	m_speaker->level_w(state);
459 	m_sk = state;
460 	update_display();
461 }
462 
WRITE_LINE_MEMBER(einvaderc_state::write_so)463 WRITE_LINE_MEMBER(einvaderc_state::write_so)
464 {
465 	// SO: led grid 9
466 	m_so = state;
467 	update_display();
468 }
469 
write_l(u8 data)470 void einvaderc_state::write_l(u8 data)
471 {
472 	// L: led state/segment
473 	m_l = data;
474 	update_display();
475 }
476 
477 // config
478 
479 static INPUT_PORTS_START( einvaderc )
480 	PORT_START("IN.0") // port IN
DEF_STR(Difficulty)481 	PORT_CONFNAME( 0x01, 0x01, DEF_STR( Difficulty ) )
482 	PORT_CONFSETTING(    0x01, "Amateur" )
483 	PORT_CONFSETTING(    0x00, "Professional" )
484 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_16WAY
485 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_16WAY
486 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 )
487 INPUT_PORTS_END
488 
489 void einvaderc_state::einvaderc(machine_config &config)
490 {
491 	/* basic machine hardware */
492 	COP444L(config, m_maincpu, 850000); // approximation - RC osc. R=47K, C=100pF
493 	m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
494 	m_maincpu->read_in().set_ioport("IN.0");
495 	m_maincpu->write_d().set(FUNC(einvaderc_state::write_d));
496 	m_maincpu->write_g().set(FUNC(einvaderc_state::write_g));
497 	m_maincpu->write_sk().set(FUNC(einvaderc_state::write_sk));
498 	m_maincpu->write_so().set(FUNC(einvaderc_state::write_so));
499 	m_maincpu->write_l().set(FUNC(einvaderc_state::write_l));
500 
501 	/* video hardware */
502 	screen_device &mask(SCREEN(config, "mask", SCREEN_TYPE_SVG));
503 	mask.set_refresh_hz(60);
504 	mask.set_size(919, 1080);
505 	mask.set_visarea_full();
506 
507 	PWM_DISPLAY(config, m_display).set_size(10, 8);
508 	m_display->set_segmask(7, 0x7f);
509 	config.set_default_layout(layout_einvaderc);
510 
511 	/* sound hardware */
512 	SPEAKER(config, "mono").front_center();
513 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
514 }
515 
516 // roms
517 
518 ROM_START( einvaderc )
519 	ROM_REGION( 0x0800, "maincpu", 0 )
520 	ROM_LOAD( "copl444-hrz_n_inv_ii", 0x0000, 0x0800, CRC(76400f38) SHA1(0e92ab0517f7b7687293b189d30d57110df20fe0) )
521 
522 	ROM_REGION( 82104, "mask", 0)
523 	ROM_LOAD( "einvaderc.svg", 0, 82104, CRC(0013227f) SHA1(44a3ac48c947369231f010559331ad16fcbef7be) )
524 ROM_END
525 
526 
527 
528 
529 
530 /***************************************************************************
531 
532   Gordon Barlow Design electronic Space Invaders game (unreleased, from patent US4345764)
533   * COP421 (likely a development chip)
534   * 36+9 LEDs, 1-bit sound
535 
536   This game is presumedly unreleased. The title is unknown, the patent simply names
537   it "Hand-held electronic game". There is no mass-manufacture company assigned
538   to it either. The game seems unfinished(no scorekeeping, some bugs), and the design
539   is very complex. Player ship and bullets are on a moving "wand", a 2-way mirror
540   makes it appear on the same plane as the enemies and barriers.
541 
542 ***************************************************************************/
543 
544 class unkeinv_state : public hh_cop400_state
545 {
546 public:
unkeinv_state(const machine_config & mconfig,device_type type,const char * tag)547 	unkeinv_state(const machine_config &mconfig, device_type type, const char *tag) :
548 		hh_cop400_state(mconfig, type, tag)
549 	{ }
550 
551 	void update_display();
552 	void write_g(u8 data);
553 	void write_d(u8 data);
554 	void write_l(u8 data);
555 	u8 read_l();
556 
557 	void unkeinv(machine_config &config);
558 };
559 
560 // handlers
561 
update_display()562 void unkeinv_state::update_display()
563 {
564 	m_display->matrix(m_g << 4 | m_d, m_l);
565 }
566 
write_g(u8 data)567 void unkeinv_state::write_g(u8 data)
568 {
569 	// G0,G1: led select part
570 	// G2,G3: input mux
571 	m_g = ~data & 0xf;
572 	update_display();
573 }
574 
write_d(u8 data)575 void unkeinv_state::write_d(u8 data)
576 {
577 	// D0-D3: led select part
578 	m_d = ~data & 0xf;
579 	update_display();
580 }
581 
write_l(u8 data)582 void unkeinv_state::write_l(u8 data)
583 {
584 	// L0-L7: led data
585 	m_l = ~data & 0xff;
586 	update_display();
587 }
588 
read_l()589 u8 unkeinv_state::read_l()
590 {
591 	u8 ret = 0xff;
592 
593 	// L0-L5+G2: positional odd
594 	// L0-L5+G3: positional even
595 	u8 pos = m_inputs[1]->read();
596 	if (m_g & 4 && pos & 1)
597 		ret ^= (1 << (pos >> 1));
598 	if (m_g & 8 && ~pos & 1)
599 		ret ^= (1 << (pos >> 1));
600 
601 	// L7+G3: fire button
602 	if (m_g & 8 && m_inputs[0]->read())
603 		ret ^= 0x80;
604 
605 	return ret & ~m_l;
606 }
607 
608 // config
609 
610 static INPUT_PORTS_START( unkeinv )
611 	PORT_START("IN.0")
612 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 )
613 
614 	PORT_START("IN.1")
615 	PORT_BIT( 0x0f, 0x00, IPT_POSITIONAL ) PORT_POSITIONS(12) PORT_SENSITIVITY(10) PORT_KEYDELTA(1) PORT_CENTERDELTA(0)
616 INPUT_PORTS_END
617 
unkeinv(machine_config & config)618 void unkeinv_state::unkeinv(machine_config &config)
619 {
620 	/* basic machine hardware */
621 	COP421(config, m_maincpu, 850000); // frequency guessed
622 	m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
623 	m_maincpu->write_g().set(FUNC(unkeinv_state::write_g));
624 	m_maincpu->write_d().set(FUNC(unkeinv_state::write_d));
625 	m_maincpu->write_l().set(FUNC(unkeinv_state::write_l));
626 	m_maincpu->read_l().set(FUNC(unkeinv_state::read_l));
627 	m_maincpu->read_l_tristate().set_constant(0xff);
628 	m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
629 
630 	/* video hardware */
631 	PWM_DISPLAY(config, m_display).set_size(6, 8);
632 	config.set_default_layout(layout_unkeinv);
633 
634 	/* sound hardware */
635 	SPEAKER(config, "mono").front_center();
636 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
637 }
638 
639 // roms
640 
641 ROM_START( unkeinv )
642 	ROM_REGION( 0x0400, "maincpu", 0 )
643 	ROM_LOAD( "cop421_us4345764", 0x0000, 0x0400, CRC(0068c3a3) SHA1(4e5fd566a5a26c066cc14623a9bd01e109ebf797) ) // typed in from patent US4345764, good print quality
644 ROM_END
645 
646 
647 
648 
649 
650 /***************************************************************************
651 
652   LJN I Took a Lickin' From a Chicken
653   * COP421 MCU label ~/005 COP421-NJC/N
654   * 11 leds, 1-bit sound, motor to a chicken on a spring
655 
656   This toy includes 4 games: Tic Tac Toe, Chicken Sez, and Total Recall I/II.
657 
658   known releases:
659   - USA: I Took a Lickin' From a Chicken
660   - Japan: Professor Chicken's Genius Classroom 「にわとり博士の天才教室」, published by Bandai
661     (not sure if it's the same ROM, or just licensed the outer shell)
662 
663 ***************************************************************************/
664 
665 class lchicken_state : public hh_cop400_state
666 {
667 public:
lchicken_state(const machine_config & mconfig,device_type type,const char * tag)668 	lchicken_state(const machine_config &mconfig, device_type type, const char *tag) :
669 		hh_cop400_state(mconfig, type, tag)
670 	{ }
671 
672 	u8 m_motor_pos;
673 	TIMER_DEVICE_CALLBACK_MEMBER(motor_sim_tick);
674 	DECLARE_READ_LINE_MEMBER(motor_switch_r);
675 
676 	void write_l(u8 data);
677 	void write_d(u8 data);
678 	void write_g(u8 data);
679 	u8 read_g();
680 	DECLARE_WRITE_LINE_MEMBER(write_so);
681 	DECLARE_READ_LINE_MEMBER(read_si);
682 	void lchicken(machine_config &config);
683 
684 protected:
685 	virtual void machine_start() override;
686 };
687 
machine_start()688 void lchicken_state::machine_start()
689 {
690 	hh_cop400_state::machine_start();
691 
692 	// zerofill, register for savestates
693 	m_motor_pos = 0;
694 	save_item(NAME(m_motor_pos));
695 }
696 
697 // handlers
698 
READ_LINE_MEMBER(lchicken_state::motor_switch_r)699 READ_LINE_MEMBER(lchicken_state::motor_switch_r)
700 {
701 	return m_motor_pos > 0xe8; // approximation
702 }
703 
TIMER_DEVICE_CALLBACK_MEMBER(lchicken_state::motor_sim_tick)704 TIMER_DEVICE_CALLBACK_MEMBER(lchicken_state::motor_sim_tick)
705 {
706 	if (~m_inp_mux & 8)
707 	{
708 		m_motor_pos++;
709 		output().set_value("motor_pos", 100 * (m_motor_pos / (float)0x100));
710 	}
711 }
712 
write_l(u8 data)713 void lchicken_state::write_l(u8 data)
714 {
715 	// L0-L3: led data
716 	// L4-L6: led select
717 	// L7: N/C
718 	m_display->matrix(data >> 4 & 7, ~data & 0xf);
719 }
720 
write_d(u8 data)721 void lchicken_state::write_d(u8 data)
722 {
723 	// D0-D3: input mux
724 	// D3: motor on
725 	m_inp_mux = data & 0xf;
726 	output().set_value("motor_on", ~data >> 3 & 1);
727 }
728 
write_g(u8 data)729 void lchicken_state::write_g(u8 data)
730 {
731 	m_g = data;
732 }
733 
read_g()734 u8 lchicken_state::read_g()
735 {
736 	// G0-G3: multiplexed inputs
737 	return read_inputs(4, m_g);
738 }
739 
WRITE_LINE_MEMBER(lchicken_state::write_so)740 WRITE_LINE_MEMBER(lchicken_state::write_so)
741 {
742 	// SO: speaker out
743 	m_speaker->level_w(state);
744 	m_so = state;
745 }
746 
READ_LINE_MEMBER(lchicken_state::read_si)747 READ_LINE_MEMBER(lchicken_state::read_si)
748 {
749 	// SI: SO
750 	return m_so;
751 }
752 
753 // config
754 
755 static INPUT_PORTS_START( lchicken )
756 	PORT_START("IN.0") // D0 port G
PORT_CODE(KEYCODE_3)757 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
758 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
759 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
760 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
761 
762 	PORT_START("IN.1") // D1 port G
763 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
764 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
765 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
766 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
767 
768 	PORT_START("IN.2") // D2 port G
769 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
770 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
771 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
772 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
773 
774 	PORT_START("IN.3") // D3 port G
775 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
776 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
777 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
778 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(lchicken_state, motor_switch_r)
779 INPUT_PORTS_END
780 
781 void lchicken_state::lchicken(machine_config &config)
782 {
783 	/* basic machine hardware */
784 	COP421(config, m_maincpu, 850000); // approximation - RC osc. R=12K, C=100pF
785 	m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
786 	m_maincpu->write_l().set(FUNC(lchicken_state::write_l));
787 	m_maincpu->write_d().set(FUNC(lchicken_state::write_d));
788 	m_maincpu->write_g().set(FUNC(lchicken_state::write_g));
789 	m_maincpu->read_g().set(FUNC(lchicken_state::read_g));
790 	m_maincpu->write_so().set(FUNC(lchicken_state::write_so));
791 	m_maincpu->read_si().set(FUNC(lchicken_state::read_si));
792 
793 	TIMER(config, "chicken_motor").configure_periodic(FUNC(lchicken_state::motor_sim_tick), attotime::from_msec(6000/0x100)); // ~6sec for a full rotation
794 
795 	/* video hardware */
796 	PWM_DISPLAY(config, m_display).set_size(3, 4);
797 	config.set_default_layout(layout_lchicken);
798 
799 	/* sound hardware */
800 	SPEAKER(config, "mono").front_center();
801 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
802 }
803 
804 // roms
805 
806 ROM_START( lchicken )
807 	ROM_REGION( 0x0400, "maincpu", 0 )
808 	ROM_LOAD( "cop421-njc_n", 0x0000, 0x0400, CRC(319e7985) SHA1(9714327518f65ebefe38ac7911bed2b9b9c77307) )
809 ROM_END
810 
811 
812 
813 
814 
815 /***************************************************************************
816 
817   Mattel Funtronics: Jacks
818   * COP410L MCU bonded directly to PCB (die label COP410L/B NGS)
819   * 8 LEDs, 1-bit sound
820 
821 ***************************************************************************/
822 
823 class funjacks_state : public hh_cop400_state
824 {
825 public:
funjacks_state(const machine_config & mconfig,device_type type,const char * tag)826 	funjacks_state(const machine_config &mconfig, device_type type, const char *tag) :
827 		hh_cop400_state(mconfig, type, tag)
828 	{ }
829 
830 	void update_display();
831 	void write_d(u8 data);
832 	void write_l(u8 data);
833 	void write_g(u8 data);
834 	u8 read_l();
835 	u8 read_g();
836 	void funjacks(machine_config &config);
837 };
838 
839 // handlers
840 
update_display()841 void funjacks_state::update_display()
842 {
843 	m_display->matrix(m_d, m_l);
844 }
845 
write_d(u8 data)846 void funjacks_state::write_d(u8 data)
847 {
848 	// D: led grid + input mux
849 	m_inp_mux = data;
850 	m_d = ~data & 0xf;
851 	update_display();
852 }
853 
write_l(u8 data)854 void funjacks_state::write_l(u8 data)
855 {
856 	// L0,L1: led state
857 	m_l = data & 3;
858 	update_display();
859 }
860 
write_g(u8 data)861 void funjacks_state::write_g(u8 data)
862 {
863 	// G1: speaker out
864 	m_speaker->level_w(data >> 1 & 1);
865 	m_g = data;
866 }
867 
read_l()868 u8 funjacks_state::read_l()
869 {
870 	// L4,L5: multiplexed inputs
871 	return read_inputs(3, 0x30) | m_l;
872 }
873 
read_g()874 u8 funjacks_state::read_g()
875 {
876 	// G1: speaker out state
877 	// G2,G3: inputs
878 	return m_inputs[3]->read() | (m_g & 2);
879 }
880 
881 // config
882 
883 static INPUT_PORTS_START( funjacks )
884 	PORT_START("IN.0") // D0 port G
885 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3 )
886 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
887 
888 	PORT_START("IN.1") // D1 port G
889 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 )
890 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON5 )
891 
892 	PORT_START("IN.2") // D2 port G
893 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON6 )
894 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // positioned at 1 o'clock on panel, increment clockwise
895 
896 	PORT_START("IN.3") // port G
897 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
898 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_CUSTOM ) // speaker
899 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START )
DEF_STR(Players)900 	PORT_CONFNAME( 0x08, 0x00, DEF_STR( Players ) )
901 	PORT_CONFSETTING(    0x00, "1" )
902 	PORT_CONFSETTING(    0x08, "2" )
903 INPUT_PORTS_END
904 
905 void funjacks_state::funjacks(machine_config &config)
906 {
907 	/* basic machine hardware */
908 	COP410(config, m_maincpu, 750000); // approximation - RC osc. R=47K, C=56pF
909 	m_maincpu->set_config(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
910 	m_maincpu->write_d().set(FUNC(funjacks_state::write_d));
911 	m_maincpu->write_l().set(FUNC(funjacks_state::write_l));
912 	m_maincpu->write_g().set(FUNC(funjacks_state::write_g));
913 	m_maincpu->read_l().set(FUNC(funjacks_state::read_l));
914 	m_maincpu->read_g().set(FUNC(funjacks_state::read_g));
915 
916 	/* video hardware */
917 	PWM_DISPLAY(config, m_display).set_size(4, 2);
918 	config.set_default_layout(layout_funjacks);
919 
920 	/* sound hardware */
921 	SPEAKER(config, "mono").front_center();
922 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
923 }
924 
925 // roms
926 
927 ROM_START( funjacks )
928 	ROM_REGION( 0x0200, "maincpu", 0 )
929 	ROM_LOAD( "cop410l_b_ngs", 0x0000, 0x0200, CRC(863368ea) SHA1(f116cc27ae721b3a3e178fa13765808bdc275663) )
930 ROM_END
931 
932 
933 
934 
935 
936 /***************************************************************************
937 
938   Mattel Funtronics: Red Light Green Light
939   * COP410L MCU bonded directly to PCB (die label COP410L/B NHZ)
940   * 14 LEDs, 1-bit sound
941 
942   known releases:
943   - USA: Funtronics: Red Light Green Light
944   - USA(rerelease): Funtronics: Hot Wheels Drag Race
945 
946 ***************************************************************************/
947 
948 class funrlgl_state : public hh_cop400_state
949 {
950 public:
funrlgl_state(const machine_config & mconfig,device_type type,const char * tag)951 	funrlgl_state(const machine_config &mconfig, device_type type, const char *tag) :
952 		hh_cop400_state(mconfig, type, tag)
953 	{ }
954 
955 	void update_display();
956 	void write_d(u8 data);
957 	void write_l(u8 data);
958 	void write_g(u8 data);
959 	void funrlgl(machine_config &config);
960 };
961 
962 // handlers
963 
update_display()964 void funrlgl_state::update_display()
965 {
966 	m_display->matrix(m_d, m_l);
967 }
968 
write_d(u8 data)969 void funrlgl_state::write_d(u8 data)
970 {
971 	// D: led grid
972 	m_d = ~data & 0xf;
973 	update_display();
974 }
975 
write_l(u8 data)976 void funrlgl_state::write_l(u8 data)
977 {
978 	// L0-L3: led state
979 	// L4-L7: N/C
980 	m_l = ~data & 0xf;
981 	update_display();
982 }
983 
write_g(u8 data)984 void funrlgl_state::write_g(u8 data)
985 {
986 	// G3: speaker out
987 	m_speaker->level_w(data >> 3 & 1);
988 }
989 
990 // config
991 
992 static INPUT_PORTS_START( funrlgl )
993 	PORT_START("IN.0") // port G
994 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
995 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
DEF_STR(Difficulty)996 	PORT_CONFNAME( 0x04, 0x04, DEF_STR( Difficulty ) )
997 	PORT_CONFSETTING(    0x04, "1" )
998 	PORT_CONFSETTING(    0x00, "2" )
999 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1000 
1001 	PORT_START("RESET")
1002 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_START ) PORT_CHANGED_MEMBER(DEVICE_SELF, hh_cop400_state, reset_button, 0)
1003 INPUT_PORTS_END
1004 
1005 void funrlgl_state::funrlgl(machine_config &config)
1006 {
1007 	/* basic machine hardware */
1008 	COP410(config, m_maincpu, 750000); // approximation - RC osc. R=51K, C=91pF
1009 	m_maincpu->set_config(COP400_CKI_DIVISOR_8, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1010 	m_maincpu->write_d().set(FUNC(funrlgl_state::write_d));
1011 	m_maincpu->write_l().set(FUNC(funrlgl_state::write_l));
1012 	m_maincpu->read_l_tristate().set_constant(0xff);
1013 	m_maincpu->write_g().set(FUNC(funrlgl_state::write_g));
1014 	m_maincpu->read_g().set_ioport("IN.0");
1015 
1016 	/* video hardware */
1017 	PWM_DISPLAY(config, m_display).set_size(4, 4);
1018 	m_display->set_bri_levels(0.01, 0.1); // top led is brighter
1019 	config.set_default_layout(layout_funrlgl);
1020 
1021 	/* sound hardware */
1022 	SPEAKER(config, "mono").front_center();
1023 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
1024 }
1025 
1026 // roms
1027 
1028 ROM_START( funrlgl )
1029 	ROM_REGION( 0x0200, "maincpu", 0 )
1030 	ROM_LOAD( "cop410l_b_nhz", 0x0000, 0x0200, CRC(4065c3ce) SHA1(f0bc8125d922949e0d7ab1ba89c805a836d20e09) )
1031 ROM_END
1032 
1033 
1034 
1035 
1036 
1037 /***************************************************************************
1038 
1039   Mattel Dalla$ (J.R. handheld)
1040   * COP444 MCU label COP444L-HYN/N
1041   * 8-digit 7seg display, 1-bit sound
1042 
1043   This is a board game, only the handheld device is emulated here.
1044 
1045 ***************************************************************************/
1046 
1047 class mdallas_state : public hh_cop400_state
1048 {
1049 public:
mdallas_state(const machine_config & mconfig,device_type type,const char * tag)1050 	mdallas_state(const machine_config &mconfig, device_type type, const char *tag) :
1051 		hh_cop400_state(mconfig, type, tag)
1052 	{ }
1053 
1054 	void update_display();
1055 	void write_l(u8 data);
1056 	void write_d(u8 data);
1057 	void write_g(u8 data);
1058 	u8 read_in();
1059 	void mdallas(machine_config &config);
1060 };
1061 
1062 // handlers
1063 
update_display()1064 void mdallas_state::update_display()
1065 {
1066 	m_display->matrix(~(m_d << 4 | m_g), m_l);
1067 }
1068 
write_l(u8 data)1069 void mdallas_state::write_l(u8 data)
1070 {
1071 	// L: digit segment data
1072 	m_l = data;
1073 	update_display();
1074 }
1075 
write_d(u8 data)1076 void mdallas_state::write_d(u8 data)
1077 {
1078 	// D: select digit, input mux high
1079 	m_inp_mux = (m_inp_mux & 0xf) | (data << 4 & 3);
1080 	m_d = data & 0xf;
1081 	update_display();
1082 }
1083 
write_g(u8 data)1084 void mdallas_state::write_g(u8 data)
1085 {
1086 	// G: select digit, input mux low
1087 	m_inp_mux = (m_inp_mux & 0x30) | (data & 0xf);
1088 	m_g = data & 0xf;
1089 	update_display();
1090 }
1091 
read_in()1092 u8 mdallas_state::read_in()
1093 {
1094 	// IN: multiplexed inputs
1095 	return read_inputs(6, 0xf);
1096 }
1097 
1098 // config
1099 
1100 /* physical button layout and labels is like this:
1101 
1102     <  ON>  [YES]   [NO]   [NEXT]
1103     [<W]    [^N]    [Sv]   [E>]
1104     [7]     [8]     [9]    [STATUS]
1105     [4]     [5]     [6]    [ASSETS]
1106     [1]     [2]     [3]    [START]
1107     [CLEAR] [0]     [MOVE] [ENTER]
1108 */
1109 
1110 static INPUT_PORTS_START( mdallas )
1111 	PORT_START("IN.0") // G0 port IN
PORT_CODE(KEYCODE_C)1112 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_CODE(KEYCODE_DEL) PORT_NAME("Clear")
1113 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
1114 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("Move")
1115 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter")
1116 
1117 	PORT_START("IN.1") // G1 port IN
1118 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
1119 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
1120 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
1121 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_S) PORT_NAME("Start")
1122 
1123 	PORT_START("IN.2") // G2 port IN
1124 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
1125 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
1126 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
1127 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("Assets")
1128 
1129 	PORT_START("IN.3") // G3 port IN
1130 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
1131 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
1132 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
1133 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_T) PORT_NAME("Status")
1134 
1135 	PORT_START("IN.4") // D0 port IN
1136 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("West") // W
1137 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1138 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_X) PORT_NAME("Next")
1139 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("East") // E
1140 
1141 	PORT_START("IN.5") // D1 port IN
1142 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_N) PORT_NAME("No")
1143 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Y) PORT_NAME("Yes")
1144 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("South") // S
1145 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("North") // N
1146 INPUT_PORTS_END
1147 
1148 void mdallas_state::mdallas(machine_config &config)
1149 {
1150 	/* basic machine hardware */
1151 	COP444L(config, m_maincpu, 1000000); // approximation - RC osc. R=57K, C=101pF
1152 	m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1153 	m_maincpu->write_l().set(FUNC(mdallas_state::write_l));
1154 	m_maincpu->write_d().set(FUNC(mdallas_state::write_d));
1155 	m_maincpu->write_g().set(FUNC(mdallas_state::write_g));
1156 	m_maincpu->read_in().set(FUNC(mdallas_state::read_in));
1157 	m_maincpu->write_so().set(m_speaker, FUNC(speaker_sound_device::level_w));
1158 
1159 	/* video hardware */
1160 	PWM_DISPLAY(config, m_display).set_size(8, 8);
1161 	m_display->set_segmask(0xff, 0xff);
1162 	config.set_default_layout(layout_mdallas);
1163 
1164 	/* sound hardware */
1165 	SPEAKER(config, "mono").front_center();
1166 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
1167 }
1168 
1169 // roms
1170 
1171 ROM_START( mdallas )
1172 	ROM_REGION( 0x0800, "maincpu", 0 )
1173 	ROM_LOAD( "copl444l-hyn_n", 0x0000, 0x0800, CRC(7848b78c) SHA1(778d24512180892f58c49df3c72ca77b2618d63b) )
1174 ROM_END
1175 
1176 
1177 
1178 
1179 
1180 /***************************************************************************
1181 
1182   Milton Bradley Plus One
1183   * COP410L MCU in 8-pin DIP, label ~/029 MM 57405 (die label COP410L/B NNE)
1184   * orientation sensor(4 directions), 1-bit sound
1185 
1186   This is a board game, each player needs to rotate a triangular pyramid
1187   shaped piece the same as the previous player, plus 1.
1188 
1189 ***************************************************************************/
1190 
1191 class plus1_state : public hh_cop400_state
1192 {
1193 public:
plus1_state(const machine_config & mconfig,device_type type,const char * tag)1194 	plus1_state(const machine_config &mconfig, device_type type, const char *tag) :
1195 		hh_cop400_state(mconfig, type, tag)
1196 	{ }
1197 
1198 	void write_d(u8 data);
1199 	void write_l(u8 data);
1200 	u8 read_l();
1201 	void plus1(machine_config &config);
1202 };
1203 
1204 // handlers
1205 
write_d(u8 data)1206 void plus1_state::write_d(u8 data)
1207 {
1208 	// D0?: speaker out
1209 	m_speaker->level_w(data & 1);
1210 }
1211 
write_l(u8 data)1212 void plus1_state::write_l(u8 data)
1213 {
1214 	m_l = data;
1215 }
1216 
read_l()1217 u8 plus1_state::read_l()
1218 {
1219 	// L: IN.1, mask with output
1220 	return m_inputs[1]->read() & m_l;
1221 }
1222 
1223 // config
1224 
1225 static INPUT_PORTS_START( plus1 )
1226 	PORT_START("IN.0") // port G
1227 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
1228 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Sensor Position 3")
1229 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Sensor Position 1")
1230 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
1231 
1232 	PORT_START("IN.1") // port L
1233 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Sensor Position 4")
1234 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
1235 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
1236 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Sensor Position 2")
1237 	PORT_BIT( 0xf0, IP_ACTIVE_LOW, IPT_UNUSED )
1238 INPUT_PORTS_END
1239 
plus1(machine_config & config)1240 void plus1_state::plus1(machine_config &config)
1241 {
1242 	/* basic machine hardware */
1243 	COP410(config, m_maincpu, 1000000); // approximation - RC osc. R=51K, C=100pF
1244 	m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1245 	m_maincpu->write_d().set(FUNC(plus1_state::write_d));
1246 	m_maincpu->read_g().set_ioport("IN.0");
1247 	m_maincpu->write_l().set(FUNC(plus1_state::write_l));
1248 	m_maincpu->read_l().set(FUNC(plus1_state::read_l));
1249 
1250 	/* no visual feedback! */
1251 
1252 	/* sound hardware */
1253 	SPEAKER(config, "mono").front_center();
1254 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
1255 }
1256 
1257 // roms
1258 
1259 ROM_START( plus1 )
1260 	ROM_REGION( 0x0200, "maincpu", 0 )
1261 	ROM_LOAD( "cop410l_b_nne", 0x0000, 0x0200, CRC(d861b80c) SHA1(4652f8ee0dd4c3c48b625285bb4f094d96434071) )
1262 ROM_END
1263 
1264 
1265 
1266 
1267 
1268 /***************************************************************************
1269 
1270   Milton Bradley Electronic Lightfight
1271   * COP421L MCU label /B119 COP421L-HLA/N
1272   * LED matrix, 1-bit sound
1273 
1274   Xbox-shaped electronic game for 2 or more players, with long diagonal buttons
1275   next to each outer LED. The main object of the game is to pinpoint a light
1276   by pressing 2 buttons. To start, press a skill-level button(P2 button 7/8/9)
1277   after selecting a game mode(P1 button 6-10).
1278 
1279   The game variations are:
1280   1: LightFight
1281   2: NightFight
1282   3: RiteSite
1283   4: QuiteBrite
1284   5: RightLight
1285 
1286 ***************************************************************************/
1287 
1288 class lightfgt_state : public hh_cop400_state
1289 {
1290 public:
lightfgt_state(const machine_config & mconfig,device_type type,const char * tag)1291 	lightfgt_state(const machine_config &mconfig, device_type type, const char *tag) :
1292 		hh_cop400_state(mconfig, type, tag)
1293 	{ }
1294 
1295 	void update_display();
1296 	DECLARE_WRITE_LINE_MEMBER(write_so);
1297 	void write_d(u8 data);
1298 	void write_l(u8 data);
1299 	u8 read_g();
1300 	void lightfgt(machine_config &config);
1301 };
1302 
1303 // handlers
1304 
update_display()1305 void lightfgt_state::update_display()
1306 {
1307 	u8 grid = (m_so | m_d << 1) ^ 0x1f;
1308 	m_display->matrix(grid, m_l);
1309 }
1310 
WRITE_LINE_MEMBER(lightfgt_state::write_so)1311 WRITE_LINE_MEMBER(lightfgt_state::write_so)
1312 {
1313 	// SO: led grid 0 (and input mux)
1314 	m_so = state;
1315 	update_display();
1316 }
1317 
write_d(u8 data)1318 void lightfgt_state::write_d(u8 data)
1319 {
1320 	// D: led grid 1-4 (and input mux)
1321 	m_d = data;
1322 	update_display();
1323 }
1324 
write_l(u8 data)1325 void lightfgt_state::write_l(u8 data)
1326 {
1327 	// L0-L4: led state
1328 	// L5-L7: N/C
1329 	m_l = data & 0x1f;
1330 	update_display();
1331 }
1332 
read_g()1333 u8 lightfgt_state::read_g()
1334 {
1335 	// G: multiplexed inputs
1336 	m_inp_mux = m_d << 1 | m_so;
1337 	return read_inputs(5, 0xf);
1338 }
1339 
1340 // config
1341 
1342 static INPUT_PORTS_START( lightfgt )
1343 	PORT_START("IN.0") // SO port G
1344 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 )
1345 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) // note: button 1 is on the left side from player perspective
1346 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_COCKTAIL
1347 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_COCKTAIL
1348 
1349 	PORT_START("IN.1") // D0 port G
1350 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 )
1351 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
1352 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_COCKTAIL
1353 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_COCKTAIL
1354 
1355 	PORT_START("IN.2") // D1 port G
1356 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON8 )
1357 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 )
1358 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_COCKTAIL
1359 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_COCKTAIL
1360 
1361 	PORT_START("IN.3") // D2 port G
1362 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON9 )
1363 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON4 )
1364 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
1365 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_COCKTAIL
1366 
1367 	PORT_START("IN.4") // D3 port G
1368 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON10 )
1369 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 )
1370 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
1371 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_COCKTAIL
1372 INPUT_PORTS_END
1373 
lightfgt(machine_config & config)1374 void lightfgt_state::lightfgt(machine_config &config)
1375 {
1376 	/* basic machine hardware */
1377 	COP421(config, m_maincpu, 950000); // approximation - RC osc. R=82K, C=56pF
1378 	m_maincpu->set_config(COP400_CKI_DIVISOR_16, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1379 	m_maincpu->write_so().set(FUNC(lightfgt_state::write_so));
1380 	m_maincpu->write_d().set(FUNC(lightfgt_state::write_d));
1381 	m_maincpu->write_l().set(FUNC(lightfgt_state::write_l));
1382 	m_maincpu->write_sk().set(m_speaker, FUNC(speaker_sound_device::level_w));
1383 	m_maincpu->read_g().set(FUNC(lightfgt_state::read_g));
1384 
1385 	/* video hardware */
1386 	PWM_DISPLAY(config, m_display).set_size(5, 5);
1387 	config.set_default_layout(layout_lightfgt);
1388 
1389 	/* sound hardware */
1390 	SPEAKER(config, "mono").front_center();
1391 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.25);
1392 }
1393 
1394 // roms
1395 
1396 ROM_START( lightfgt )
1397 	ROM_REGION( 0x0400, "maincpu", 0 )
1398 	ROM_LOAD( "cop421l-hla_n", 0x0000, 0x0400, CRC(aceb2d65) SHA1(2328cbb195faf93c575f3afa3a1fe0079180edd7) )
1399 ROM_END
1400 
1401 
1402 
1403 
1404 
1405 /***************************************************************************
1406 
1407   Milton Bradley Electronic Battleship (1982 version)
1408   * COP420 MCU label COP420-JWE/N
1409 
1410   see hh_tms1k.cpp bship driver for more information
1411 
1412 ***************************************************************************/
1413 
1414 class bship82_state : public hh_cop400_state
1415 {
1416 public:
bship82_state(const machine_config & mconfig,device_type type,const char * tag)1417 	bship82_state(const machine_config &mconfig, device_type type, const char *tag) :
1418 		hh_cop400_state(mconfig, type, tag)
1419 	{ }
1420 
1421 	void write_d(u8 data);
1422 	u8 read_l();
1423 	u8 read_in();
1424 	DECLARE_WRITE_LINE_MEMBER(write_so);
1425 	void bship82(machine_config &config);
1426 };
1427 
1428 // handlers
1429 
write_d(u8 data)1430 void bship82_state::write_d(u8 data)
1431 {
1432 	// D: input mux
1433 	m_inp_mux = data;
1434 }
1435 
read_l()1436 u8 bship82_state::read_l()
1437 {
1438 	// L: multiplexed inputs
1439 	return read_inputs(4, 0xff);
1440 }
1441 
read_in()1442 u8 bship82_state::read_in()
1443 {
1444 	// IN: multiplexed inputs
1445 	return read_inputs(4, 0xf00) >> 8;
1446 }
1447 
WRITE_LINE_MEMBER(bship82_state::write_so)1448 WRITE_LINE_MEMBER(bship82_state::write_so)
1449 {
1450 	// SO: led
1451 	m_display->matrix(1, state);
1452 }
1453 
1454 // config
1455 
1456 static INPUT_PORTS_START( bship82 )
1457 	PORT_START("IN.0") // D0 ports L,IN
PORT_CODE(KEYCODE_BACKSPACE)1458 	PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("P1 Clear Last Entry") // CLE
1459 	PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("P1 A")
1460 	PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_NAME("P1 B")
1461 	PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_NAME("P1 C")
1462 	PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_NAME("P1 D")
1463 	PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("P1 E")
1464 	PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_NAME("P1 F")
1465 	PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_NAME("P1 G")
1466 	PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_H) PORT_NAME("P1 H")
1467 	PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_I) PORT_NAME("P1 I")
1468 	PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_J) PORT_NAME("P1 J")
1469 	PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_UNUSED )
1470 
1471 	PORT_START("IN.1") // D1 ports L,IN
1472 	PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_DEL) PORT_NAME("P1 Clear Memory") // CM
1473 	PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("P1 1")
1474 	PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("P1 2")
1475 	PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("P1 3")
1476 	PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("P1 4")
1477 	PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("P1 5")
1478 	PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("P1 6")
1479 	PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("P1 7")
1480 	PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("P1 8")
1481 	PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("P1 9")
1482 	PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("P1 10")
1483 	PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("P1 Fire")
1484 
1485 	PORT_START("IN.2") // D2 ports L,IN
1486 	PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Clear Last Entry") // CLE
1487 	PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 A")
1488 	PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 B")
1489 	PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 C")
1490 	PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 D")
1491 	PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 E")
1492 	PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 F")
1493 	PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 G")
1494 	PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 H")
1495 	PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 I")
1496 	PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 J")
1497 	PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_UNUSED )
1498 
1499 	PORT_START("IN.3") // D3 ports L,IN
1500 	PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Clear Memory") // CM
1501 	PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 1")
1502 	PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 2")
1503 	PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 3")
1504 	PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 4")
1505 	PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 5")
1506 	PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 6")
1507 	PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 7")
1508 	PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 8")
1509 	PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 9")
1510 	PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 10")
1511 	PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("P2 Fire")
1512 
1513 	PORT_START("IN.4") // SI
1514 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_TOGGLE PORT_CODE(KEYCODE_F1) PORT_NAME("Load/Go") // switch
1515 INPUT_PORTS_END
1516 
1517 /*
1518 
1519 http://www.seanriddle.com/bship82.txt
1520 
1521 21 G0     3.9K resistor to speaker transistor base
1522 22 G1     2.2K resistor to speaker transistor base
1523 23 G2     1.0K resistor to speaker transistor base
1524 24 G3     speaker transistor base tied high 4.7K
1525 
1526 speaker connection
1527 2N3904 transistor:
1528 emitter to 10ohm resistor to ground
1529 collector to 68ohm resistor to speaker (other speaker terminal to VCC)
1530 base pulled high with 4.7K resistor, connects directly to G3, 1K resistor to G2,
1531 2.2K resistor to G1, 3.9K resistor to G0
1532 
1533 */
1534 
1535 void bship82_state::bship82(machine_config &config)
1536 {
1537 	/* basic machine hardware */
1538 	COP420(config, m_maincpu, 750000); // approximation - RC osc. R=14K, C=100pF
1539 	m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1540 	m_maincpu->write_d().set(FUNC(bship82_state::write_d));
1541 	m_maincpu->write_g().set("dac", FUNC(dac_byte_interface::data_w));
1542 	m_maincpu->read_l().set(FUNC(bship82_state::read_l));
1543 	m_maincpu->read_in().set(FUNC(bship82_state::read_in));
1544 	m_maincpu->write_so().set(FUNC(bship82_state::write_so));
1545 	m_maincpu->read_si().set_ioport("IN.4");
1546 
1547 	/* video hardware */
1548 	PWM_DISPLAY(config, m_display).set_size(1, 1);
1549 	config.set_default_layout(layout_bship82);
1550 
1551 	/* sound hardware */
1552 	SPEAKER(config, "mono").front_center();
1553 	DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE(config, "dac").add_route(ALL_OUTPUTS, "mono", 0.125); // see above
1554 }
1555 
1556 // roms
1557 
1558 ROM_START( bship82 )
1559 	ROM_REGION( 0x0400, "maincpu", 0 )
1560 	ROM_LOAD( "cop420-jwe_n", 0x0000, 0x0400, CRC(5ea8111a) SHA1(34931463b806b48dce4f8ae2361512510bae0ebf) )
1561 ROM_END
1562 
1563 
1564 
1565 
1566 
1567 /***************************************************************************
1568 
1569   National Semiconductor QuizKid Racer (COP420 version)
1570   * COP420 MCU label COP420-NPG/N
1571   * 8-digit 7seg led display(1 custom digit), 1 green led, no sound
1572 
1573   This is the COP420 version, the first release was on a MM5799 MCU.
1574 
1575 ***************************************************************************/
1576 
1577 class qkracer_state : public hh_cop400_state
1578 {
1579 public:
qkracer_state(const machine_config & mconfig,device_type type,const char * tag)1580 	qkracer_state(const machine_config &mconfig, device_type type, const char *tag) :
1581 		hh_cop400_state(mconfig, type, tag)
1582 	{ }
1583 
1584 	void update_display();
1585 	void write_d(u8 data);
1586 	void write_g(u8 data);
1587 	void write_l(u8 data);
1588 	u8 read_in();
1589 	DECLARE_WRITE_LINE_MEMBER(write_sk);
1590 	void qkracer(machine_config &config);
1591 };
1592 
1593 // handlers
1594 
update_display()1595 void qkracer_state::update_display()
1596 {
1597 	m_display->matrix(~(m_d | m_g << 4 | m_sk << 8), m_l);
1598 }
1599 
write_d(u8 data)1600 void qkracer_state::write_d(u8 data)
1601 {
1602 	// D: select digit, D3: input mux high bit
1603 	m_inp_mux = (m_inp_mux & 0xf) | (data << 1 & 0x10);
1604 	m_d = data & 0xf;
1605 	update_display();
1606 }
1607 
write_g(u8 data)1608 void qkracer_state::write_g(u8 data)
1609 {
1610 	// G: select digit, input mux
1611 	m_inp_mux = (m_inp_mux & 0x10) | (data & 0xf);
1612 	m_g = data & 0xf;
1613 	update_display();
1614 }
1615 
write_l(u8 data)1616 void qkracer_state::write_l(u8 data)
1617 {
1618 	// L0-L6: digit segment data
1619 	m_l = data & 0x7f;
1620 	update_display();
1621 }
1622 
read_in()1623 u8 qkracer_state::read_in()
1624 {
1625 	// IN: multiplexed inputs
1626 	return read_inputs(5, 0xf);
1627 }
1628 
WRITE_LINE_MEMBER(qkracer_state::write_sk)1629 WRITE_LINE_MEMBER(qkracer_state::write_sk)
1630 {
1631 	// SK: green led
1632 	m_sk = state;
1633 	update_display();
1634 }
1635 
1636 // config
1637 
1638 static INPUT_PORTS_START( qkracer )
1639 	PORT_START("IN.0") // G0 port IN
PORT_CODE(KEYCODE_7)1640 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
1641 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
1642 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
1643 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_SLASH_PAD) PORT_NAME(UTF8_DIVIDE)
1644 
1645 	PORT_START("IN.1") // G1 port IN
1646 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
1647 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
1648 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
1649 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME(UTF8_MULTIPLY)
1650 
1651 	PORT_START("IN.2") // G2 port IN
1652 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
1653 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
1654 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
1655 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("-")
1656 
1657 	PORT_START("IN.3") // G3 port IN
1658 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS) PORT_NAME("Slow")
1659 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("Fast")
1660 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
1661 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("+")
1662 
1663 	PORT_START("IN.4") // D3 port IN
1664 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("Amateur")
1665 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("Pro")
1666 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Complex")
1667 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("Tables")
1668 INPUT_PORTS_END
1669 
1670 void qkracer_state::qkracer(machine_config &config)
1671 {
1672 	/* basic machine hardware */
1673 	COP420(config, m_maincpu, 1000000); // approximation - RC osc. R=47K, C=100pF
1674 	m_maincpu->set_config(COP400_CKI_DIVISOR_32, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1675 	m_maincpu->write_d().set(FUNC(qkracer_state::write_d));
1676 	m_maincpu->write_g().set(FUNC(qkracer_state::write_g));
1677 	m_maincpu->write_l().set(FUNC(qkracer_state::write_l));
1678 	m_maincpu->read_in().set(FUNC(qkracer_state::read_in));
1679 	m_maincpu->write_sk().set(FUNC(qkracer_state::write_sk));
1680 
1681 	/* video hardware */
1682 	PWM_DISPLAY(config, m_display).set_size(9, 7);
1683 	m_display->set_segmask(0xdf, 0x7f);
1684 	m_display->set_segmask(0x20, 0x41); // equals sign
1685 	config.set_default_layout(layout_qkracer);
1686 
1687 	/* no sound! */
1688 }
1689 
1690 // roms
1691 
1692 ROM_START( qkracer )
1693 	ROM_REGION( 0x0400, "maincpu", 0 )
1694 	ROM_LOAD( "cop420-npg_n", 0x0000, 0x0400, CRC(17f8e538) SHA1(23d1a1819e6ba552d8da83da2948af1cf5b13d5b) )
1695 ROM_END
1696 
1697 
1698 
1699 
1700 
1701 /***************************************************************************
1702 
1703   Select Merchandise Video Challenger
1704   * COP420 MCU label COP420-TDX/N
1705   * 6-digit 7seg led display, 3 other leds, 4-bit sound
1706 
1707   This is a lightgun with scorekeeping. The "games" themselves were released
1708   on VHS tapes. To determine scoring, the lightgun detects strobe lighting
1709   from objects in the video.
1710 
1711   known releases:
1712   - Japan: Video Challenger, published by Takara
1713   - UK: Video Challenger, published by Bandai
1714   - Canada: Video Challenger, published by Irwin
1715 
1716 ***************************************************************************/
1717 
1718 class vidchal_state : public hh_cop400_state
1719 {
1720 public:
vidchal_state(const machine_config & mconfig,device_type type,const char * tag)1721 	vidchal_state(const machine_config &mconfig, device_type type, const char *tag) :
1722 		hh_cop400_state(mconfig, type, tag)
1723 	{ }
1724 
1725 	void update_display();
1726 	void write_d(u8 data);
1727 	void write_l(u8 data);
1728 	DECLARE_WRITE_LINE_MEMBER(write_sk);
1729 	void vidchal(machine_config &config);
1730 };
1731 
1732 // handlers
1733 
update_display()1734 void vidchal_state::update_display()
1735 {
1736 	m_display->matrix(m_d | m_sk << 6, m_l);
1737 }
1738 
write_d(u8 data)1739 void vidchal_state::write_d(u8 data)
1740 {
1741 	// D: CD4028BE to digit select
1742 	m_d = 1 << data & 0x3f;
1743 	update_display();
1744 }
1745 
write_l(u8 data)1746 void vidchal_state::write_l(u8 data)
1747 {
1748 	// L: digit segment data
1749 	m_l = bitswap<8>(data,0,3,1,5,4,7,2,6);
1750 	update_display();
1751 }
1752 
WRITE_LINE_MEMBER(vidchal_state::write_sk)1753 WRITE_LINE_MEMBER(vidchal_state::write_sk)
1754 {
1755 	// SK: hit led
1756 	m_sk = state;
1757 	update_display();
1758 }
1759 
1760 // config
1761 
1762 static INPUT_PORTS_START( vidchal )
1763 	PORT_START("IN.0") // port IN
1764 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
1765 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
1766 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_CODE(KEYCODE_F1)1767 	PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER) PORT_CODE(KEYCODE_F1) PORT_NAME("Light Sensor")
1768 INPUT_PORTS_END
1769 
1770 void vidchal_state::vidchal(machine_config &config)
1771 {
1772 	/* basic machine hardware */
1773 	COP420(config, m_maincpu, 900000); // approximation
1774 	m_maincpu->set_config(COP400_CKI_DIVISOR_4, COP400_CKO_OSCILLATOR_OUTPUT, false); // guessed
1775 	m_maincpu->write_d().set(FUNC(vidchal_state::write_d));
1776 	m_maincpu->write_g().set("dac", FUNC(dac_byte_interface::data_w));
1777 	m_maincpu->write_l().set(FUNC(vidchal_state::write_l));
1778 	m_maincpu->read_in().set_ioport("IN.0");
1779 	m_maincpu->write_sk().set(FUNC(vidchal_state::write_sk));
1780 
1781 	/* video hardware */
1782 	PWM_DISPLAY(config, m_display).set_size(6+1, 8);
1783 	m_display->set_segmask(0x3f, 0xff);
1784 	config.set_default_layout(layout_vidchal);
1785 
1786 	/* sound hardware */
1787 	SPEAKER(config, "mono").front_center();
1788 	DAC_4BIT_BINARY_WEIGHTED_SIGN_MAGNITUDE(config, "dac").add_route(ALL_OUTPUTS, "mono", 0.125); // unknown DAC
1789 }
1790 
1791 // roms
1792 
1793 ROM_START( vidchal )
1794 	ROM_REGION( 0x0400, "maincpu", 0 )
1795 	ROM_LOAD( "cop420-tdx_n", 0x0000, 0x0400, CRC(c9bd041c) SHA1(ab0dcaf4741620fa4c28ab75337a23d646af7626) )
1796 ROM_END
1797 
1798 
1799 
1800 } // anonymous namespace
1801 
1802 /***************************************************************************
1803 
1804   Game driver(s)
1805 
1806 ***************************************************************************/
1807 
1808 //    YEAR  NAME        PARENT    CMP MACHINE     INPUT       CLASS            INIT        COMPANY, FULLNAME, FLAGS
1809 CONS( 1979, ctstein,    0,         0, ctstein,    ctstein,    ctstein_state,   empty_init, "Castle Toy", "Einstein (Castle Toy)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
1810 
1811 CONS( 1980, h2hbaskbc,  h2hbaskb,  0, h2hbaskbc,  h2hbaskbc,  h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Basketball (COP420L version)", MACHINE_SUPPORTS_SAVE )
1812 CONS( 1980, h2hhockeyc, h2hhockey, 0, h2hhockeyc, h2hhockeyc, h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Hockey (COP420L version)", MACHINE_SUPPORTS_SAVE )
1813 CONS( 1980, h2hsoccerc, 0,         0, h2hsoccerc, h2hsoccerc, h2hbaskbc_state, empty_init, "Coleco", "Head to Head: Electronic Soccer (COP420L version)", MACHINE_SUPPORTS_SAVE )
1814 
1815 CONS( 1981, einvaderc,  einvader,  0, einvaderc,  einvaderc,  einvaderc_state, empty_init, "Entex", "Space Invader (Entex, COP444L version)", MACHINE_SUPPORTS_SAVE )
1816 
1817 CONS( 1980, unkeinv,    0,         0, unkeinv,    unkeinv,    unkeinv_state,   empty_init, "Gordon Barlow Design", "unknown electronic Space Invaders game (patent)", MACHINE_SUPPORTS_SAVE )
1818 
1819 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 )
1820 
1821 CONS( 1979, funjacks,   0,         0, funjacks,   funjacks,   funjacks_state,  empty_init, "Mattel", "Funtronics: Jacks", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK )
1822 CONS( 1979, funrlgl,    0,         0, funrlgl,    funrlgl,    funrlgl_state,   empty_init, "Mattel", "Funtronics: Red Light Green Light", MACHINE_SUPPORTS_SAVE )
1823 CONS( 1981, mdallas,    0,         0, mdallas,    mdallas,    mdallas_state,   empty_init, "Mattel", "Dalla$ (J.R. handheld)", MACHINE_SUPPORTS_SAVE ) // ***
1824 
1825 CONS( 1980, plus1,      0,         0, plus1,      plus1,      plus1_state,     empty_init, "Milton Bradley", "Plus One", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS ) // ***
1826 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 )
1827 CONS( 1982, bship82,    bship,     0, bship82,    bship82,    bship82_state,   empty_init, "Milton Bradley", "Electronic Battleship (1982 version)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) // ***
1828 
1829 CONS( 1978, qkracer,    0,         0, qkracer,    qkracer,    qkracer_state,   empty_init, "National Semiconductor", "QuizKid Racer (COP420 version)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW )
1830 
1831 CONS( 1987, vidchal,    0,         0, vidchal,    vidchal,    vidchal_state,   empty_init, "Select Merchandise", "Video Challenger", MACHINE_SUPPORTS_SAVE | MACHINE_NOT_WORKING )
1832 
1833 // ***: As far as MAME is concerned, the game is emulated fine. But for it to be playable, it requires interaction
1834 // with other, unemulatable, things eg. game board/pieces, playing cards, pen & paper, etc.
1835