1 // license:BSD-3-Clause
2 // copyright-holders:AJR
3 /****************************************************************************
4 
5     Skeleton driver for EFO "Z-Pinball" hardware.
6 
7 ****************************************************************************/
8 
9 #include "emu.h"
10 #include "audio/efo_zsu.h"
11 #include "cpu/z80/z80.h"
12 #include "machine/nvram.h"
13 #include "machine/z80ctc.h"
14 #include "sound/saa1099.h"
15 #include "speaker.h"
16 
17 class zpinball_state : public driver_device
18 {
19 public:
zpinball_state(const machine_config & mconfig,device_type type,const char * tag)20 	zpinball_state(const machine_config &mconfig, device_type type, const char *tag)
21 		: driver_device(mconfig, type, tag)
22 		, m_zpumpu(*this, "zpumpu")
23 		, m_zpuctc(*this, "zpuctc")
24 		, m_zsu(*this, "zsu")
25 		, m_pal_input(0)
26 		, m_hc165_data(0)
27 		, m_shift_clock(false)
28 		, m_shift_enabled(false)
29 	{
30 	}
31 
32 	void zpinball(machine_config &config);
33 
34 protected:
35 	virtual void machine_start() override;
36 	virtual void machine_reset() override;
37 
38 private:
39 	u8 pal_r();
40 	void pal_w(u8 data);
41 	void shift_load_w(u8 data);
42 
43 	DECLARE_WRITE_LINE_MEMBER(shift_toggle_w);
44 	DECLARE_WRITE_LINE_MEMBER(clock_off_w);
45 
46 	u8 in1_r();
47 	u8 in2_r();
48 	void out1_w(u8 data);
49 	void out2_w(u8 data);
50 	void out3_w(u8 data);
51 	void strobes_w(u8 data);
52 	void o0_w(u8 data);
53 	void o1_w(u8 data);
54 	void o2_w(u8 data);
55 	void o3_w(u8 data);
56 	void o4_w(u8 data);
57 	void o5_w(u8 data);
58 	void o6_w(u8 data);
59 
60 	void zpu_mem(address_map &map);
61 	void zpu_io(address_map &map);
62 
63 	required_device<z80_device> m_zpumpu;
64 	required_device<z80ctc_device> m_zpuctc;
65 	required_device<efo_zsu_device> m_zsu;
66 
67 	u8 m_pal_input;
68 	u8 m_hc165_data;
69 	bool m_shift_clock;
70 	bool m_shift_enabled;
71 };
72 
73 
machine_start()74 void zpinball_state::machine_start()
75 {
76 	save_item(NAME(m_pal_input));
77 	save_item(NAME(m_hc165_data));
78 	save_item(NAME(m_shift_clock));
79 	save_item(NAME(m_shift_enabled));
80 }
81 
machine_reset()82 void zpinball_state::machine_reset()
83 {
84 	m_shift_clock = false;
85 	m_shift_enabled = false;
86 	m_zpuctc->subdevice("ch0")->set_unscaled_clock(0);
87 
88 	// Clear latches
89 	out1_w(0);
90 	out2_w(0);
91 	out3_w(0);
92 	strobes_w(0);
93 	o0_w(0);
94 	o1_w(0);
95 	o2_w(0);
96 	o3_w(0);
97 	o4_w(0);
98 	o5_w(0);
99 	o6_w(0);
100 }
101 
102 
pal_r()103 u8 zpinball_state::pal_r()
104 {
105 	// TODO: at least simulate this
106 	return m_pal_input;
107 }
108 
pal_w(u8 data)109 void zpinball_state::pal_w(u8 data)
110 {
111 	m_pal_input = data;
112 }
113 
shift_load_w(u8 data)114 void zpinball_state::shift_load_w(u8 data)
115 {
116 	m_hc165_data = data;
117 	m_shift_enabled = true;
118 	m_zpuctc->subdevice("ch0")->set_unscaled_clock(8_MHz_XTAL / 4);
119 }
120 
WRITE_LINE_MEMBER(zpinball_state::shift_toggle_w)121 WRITE_LINE_MEMBER(zpinball_state::shift_toggle_w)
122 {
123 	if (state && m_shift_enabled)
124 	{
125 		m_shift_clock = !m_shift_clock;
126 		if (m_shift_clock)
127 			m_hc165_data <<= 1;
128 	}
129 }
130 
WRITE_LINE_MEMBER(zpinball_state::clock_off_w)131 WRITE_LINE_MEMBER(zpinball_state::clock_off_w)
132 {
133 	if (state)
134 	{
135 		m_shift_clock = false;
136 		m_shift_enabled = false;
137 		m_zpuctc->subdevice("ch0")->set_unscaled_clock(0);
138 	}
139 }
140 
in1_r()141 u8 zpinball_state::in1_r()
142 {
143 	// TODO
144 	return 0;
145 }
146 
in2_r()147 u8 zpinball_state::in2_r()
148 {
149 	// TODO
150 	return 0;
151 }
152 
out1_w(u8 data)153 void zpinball_state::out1_w(u8 data)
154 {
155 	logerror("%s: out1_w(0x%02X)\n", machine().describe_context(), data);
156 }
157 
out2_w(u8 data)158 void zpinball_state::out2_w(u8 data)
159 {
160 	logerror("%s: out2_w(0x%02X)\n", machine().describe_context(), data);
161 }
162 
out3_w(u8 data)163 void zpinball_state::out3_w(u8 data)
164 {
165 	logerror("%s: out3_w(0x%02X)\n", machine().describe_context(), data);
166 }
167 
strobes_w(u8 data)168 void zpinball_state::strobes_w(u8 data)
169 {
170 	logerror("%s: strobes_w(0x%02X)\n", machine().describe_context(), data);
171 }
172 
o0_w(u8 data)173 void zpinball_state::o0_w(u8 data)
174 {
175 	logerror("%s: o0_w(0x%02X)\n", machine().describe_context(), data);
176 }
177 
o1_w(u8 data)178 void zpinball_state::o1_w(u8 data)
179 {
180 	logerror("%s: o1_w(0x%02X)\n", machine().describe_context(), data);
181 }
182 
o2_w(u8 data)183 void zpinball_state::o2_w(u8 data)
184 {
185 	logerror("%s: o2_w(0x%02X)\n", machine().describe_context(), data);
186 }
187 
o3_w(u8 data)188 void zpinball_state::o3_w(u8 data)
189 {
190 	logerror("%s: o3_w(0x%02X)\n", machine().describe_context(), data);
191 }
192 
o4_w(u8 data)193 void zpinball_state::o4_w(u8 data)
194 {
195 	logerror("%s: o4_w(0x%02X)\n", machine().describe_context(), data);
196 }
197 
o5_w(u8 data)198 void zpinball_state::o5_w(u8 data)
199 {
200 	logerror("%s: o5_w(0x%02X)\n", machine().describe_context(), data);
201 }
202 
o6_w(u8 data)203 void zpinball_state::o6_w(u8 data)
204 {
205 	logerror("%s: o6_w(0x%02X)\n", machine().describe_context(), data);
206 }
207 
208 
zpu_mem(address_map & map)209 void zpinball_state::zpu_mem(address_map &map)
210 {
211 	map(0x0000, 0x7fff).rom().region("zpurom", 0);
212 	map(0x8000, 0x87ff).mirror(0x1800).ram().share("nvram");
213 	map(0xa000, 0xa000).mirror(0x1fff).rw(FUNC(zpinball_state::pal_r), FUNC(zpinball_state::pal_w));
214 	map(0xc000, 0xc000).mirror(0x1ff8).w(FUNC(zpinball_state::o0_w));
215 	map(0xc001, 0xc001).mirror(0x1ff8).w(FUNC(zpinball_state::o1_w));
216 	map(0xc002, 0xc002).mirror(0x1ff8).w(FUNC(zpinball_state::o2_w));
217 	map(0xc003, 0xc003).mirror(0x1ff8).w(FUNC(zpinball_state::o3_w));
218 	map(0xc004, 0xc004).mirror(0x1ff8).w(FUNC(zpinball_state::o4_w));
219 	map(0xc005, 0xc005).mirror(0x1ff8).w(FUNC(zpinball_state::o5_w));
220 	map(0xc006, 0xc006).mirror(0x1ff8).w(FUNC(zpinball_state::o6_w));
221 	map(0xe000, 0xe001).mirror(0x1ffe).w("saa", FUNC(saa1099_device::write));
222 }
223 
zpu_io(address_map & map)224 void zpinball_state::zpu_io(address_map &map)
225 {
226 	map.global_mask(0x1f);
227 	map(0x00, 0x03).rw(m_zpuctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
228 	map(0x04, 0x04).mirror(3).r(FUNC(zpinball_state::in1_r));
229 	map(0x08, 0x08).mirror(3).r(FUNC(zpinball_state::in2_r));
230 	map(0x0c, 0x0c).mirror(3).w(FUNC(zpinball_state::out1_w));
231 	map(0x10, 0x10).mirror(3).w(FUNC(zpinball_state::shift_load_w));
232 	map(0x14, 0x14).mirror(3).w(FUNC(zpinball_state::out2_w));
233 	map(0x18, 0x18).mirror(3).w(FUNC(zpinball_state::strobes_w));
234 	map(0x1c, 0x1c).mirror(3).w(FUNC(zpinball_state::out3_w));
235 }
236 
237 
238 static INPUT_PORTS_START(zpinball)
239 INPUT_PORTS_END
240 
241 
242 static const z80_daisy_config daisy_chain[] =
243 {
244 	{ "zpuctc" },
245 	{ nullptr }
246 };
247 
zpinball(machine_config & config)248 void zpinball_state::zpinball(machine_config &config)
249 {
250 	Z80(config, m_zpumpu, 8_MHz_XTAL / 2); // Z80A
251 	m_zpumpu->set_addrmap(AS_PROGRAM, &zpinball_state::zpu_mem);
252 	m_zpumpu->set_addrmap(AS_IO, &zpinball_state::zpu_io);
253 	m_zpumpu->set_daisy_config(daisy_chain);
254 
255 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // 6116 + battery
256 
257 	Z80CTC(config, m_zpuctc, 8_MHz_XTAL / 2);
258 	m_zpuctc->set_clk<0>(8_MHz_XTAL / 4);
259 	m_zpuctc->set_clk<2>(100); // rectified from power supply
260 	m_zpuctc->set_clk<3>(100);
261 	m_zpuctc->intr_callback().set_inputline(m_zpumpu, INPUT_LINE_IRQ0);
262 	m_zpuctc->zc_callback<0>().set(FUNC(zpinball_state::shift_toggle_w));
263 	m_zpuctc->zc_callback<0>().append(m_zpuctc, FUNC(z80ctc_device::trg1));
264 	m_zpuctc->zc_callback<1>().set(FUNC(zpinball_state::clock_off_w));
265 
266 	SPEAKER(config, "mono").front_center();
267 	SAA1099(config, "saa", 8_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 1.0);
268 
269 	EFO_ZSU1(config, m_zsu, 0);
270 }
271 
272 
273 // Eight Ball Champ (Maibesa) on EFO "Z-Pinball" hardware - very different from the Bally original
274 // actual year uncertain; schematic in manual says hardware was designed in 1986, so probably not 1985 as claimed
275 ROM_START(eballchps)
276 	ROM_REGION(0x8000, "zpurom", 0)
277 	ROM_LOAD("u18-jeb 5a0 - cpu.bin", 0x0000, 0x8000, CRC(87615a7d) SHA1(b27ca2d863040a2641f88f9bd3143467a83f181b))
278 
279 	ROM_REGION(0x28000, "zsu:soundcpu", 0)
280 	ROM_LOAD("u3-ebe a02 - sonido.bin", 0x00000, 0x8000, CRC(34be32ee) SHA1(ce0271540164639f28d617753760ecc479b6b0d0))
281 	ROM_LOAD("u4-ebe b01 - sonido.bin", 0x08000, 0x8000, CRC(d696c4e8) SHA1(501e18c258e6d42819d25d72e1907984a6cfeecb))
282 	ROM_LOAD("u5-ebe c01 - sonido.bin", 0x10000, 0x8000, CRC(fe78d7ef) SHA1(ed91c51dd230854a007f88446011f786759687ca))
283 	ROM_LOAD("u6-ebe d02 - sonido.bin", 0x18000, 0x8000, CRC(a507081b) SHA1(72d025852a12f455981c61a405f97eaaac9c6fac))
284 ROM_END
285 
286 // Cobra (Playbar)
287 ROM_START(cobrapb)
288 	ROM_REGION(0x8000, "zpurom", 0)
289 	ROM_LOAD("u18 - jcb 4 a0 - cpu.bin", 0x0000, 0x8000, CRC(c663910e) SHA1(c38692343f114388259c4e7b7943e5be934189ca))
290 
291 	ROM_REGION(0x28000, "zsu:soundcpu", 0)
292 	ROM_LOAD("u3 - scb 1 a0 - sonido.bin", 0x00000, 0x8000, CRC(d3675770) SHA1(882ce748308f2d78cccd28fc8cd64fe69bd223e3))
293 	ROM_LOAD("u4 - scb 1 b0 - sonido.bin", 0x08000, 0x8000, CRC(e8e1bdbb) SHA1(215bdfab751cb0ea47aa529df0ac30976de4f772))
294 	ROM_LOAD("u5 - scb 1 c0 - sonido.bin", 0x10000, 0x8000, CRC(c36340ab) SHA1(cd662457959de3a929ba02779e2046ed18b797e2))
295 ROM_END
296 
297 // Come Back (Nondum)
298 ROM_START(comeback)
299 	ROM_REGION(0x8000, "zpurom", 0)
300 	ROM_LOAD("jeb_5a0.u18", 0x0000, 0x8000, CRC(87615a7d) SHA1(b27ca2d863040a2641f88f9bd3143467a83f181b))
301 
302 	ROM_REGION(0x28000, "zsu:soundcpu", 0)
303 	ROM_LOAD("cbs_3a0.u3", 0x00000, 0x8000, CRC(d0f55dc9) SHA1(91186e2cbe248323380418911240a9a5887063fb))
304 	ROM_LOAD("cbs_3b0.u4", 0x08000, 0x8000, CRC(1da16d36) SHA1(9f7a27ae23064c1183a346ff042e6cba148257c7))
305 	ROM_LOAD("cbs_1c0.u5", 0x10000, 0x8000, CRC(794ae588) SHA1(adaa5e69232523369a6a2da865ac05102cc04ec8))
306 ROM_END
307 
308 
309 GAME(1986, eballchps, eballchp, zpinball, zpinball, zpinball_state, empty_init, ROT0, "Bally (Maibesa license)", "Eight Ball Champ (Spain, Z-Pinball hardware)", MACHINE_IS_SKELETON_MECHANICAL)
310 GAME(1987, cobrapb,   0,        zpinball, zpinball, zpinball_state, empty_init, ROT0, "Playbar", "Cobra (Playbar)", MACHINE_IS_SKELETON_MECHANICAL)
311 GAME(198?, comeback,  0,        zpinball, zpinball, zpinball_state, empty_init, ROT0, "Nondum / CIFA", "Come Back", MACHINE_IS_SKELETON_MECHANICAL)
312