1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria, Tormod Tjaberg, Mirko Buffoni,Lee Taylor, Valerio Verrando, Zsolt Vasvari
3 // thanks-to:Michael Strutts, Marco Cassili
4 /***************************************************************************
5 
6     Midway 8080-based black and white hardware
7 
8 ****************************************************************************/
9 #ifndef MAME_INCLUDES_MW8080BW_H
10 #define MAME_INCLUDES_MW8080BW_H
11 
12 #pragma once
13 
14 #include "audio/mw8080bw.h"
15 
16 #include "machine/mb14241.h"
17 #include "machine/timer.h"
18 #include "machine/watchdog.h"
19 #include "sound/discrete.h"
20 #include "screen.h"
21 
22 
23 #define MW8080BW_MASTER_CLOCK             (19968000.0)
24 #define MW8080BW_CPU_CLOCK                (MW8080BW_MASTER_CLOCK / 10)
25 #define MW8080BW_PIXEL_CLOCK              (MW8080BW_MASTER_CLOCK / 4)
26 #define MW8080BW_HTOTAL                   (0x140)
27 #define MW8080BW_HBEND                    (0x000)
28 #define MW8080BW_HBSTART                  (0x100)
29 #define MW8080BW_VTOTAL                   (0x106)
30 #define MW8080BW_VBEND                    (0x000)
31 #define MW8080BW_VBSTART                  (0x0e0)
32 #define MW8080BW_VCOUNTER_START_NO_VBLANK (0x020)
33 #define MW8080BW_VCOUNTER_START_VBLANK    (0x0da)
34 #define MW8080BW_INT_TRIGGER_COUNT_1      (0x080)
35 #define MW8080BW_INT_TRIGGER_VBLANK_1     (0)
36 #define MW8080BW_INT_TRIGGER_COUNT_2      MW8080BW_VCOUNTER_START_VBLANK
37 #define MW8080BW_INT_TRIGGER_VBLANK_2     (1)
38 #define MW8080BW_60HZ                     (MW8080BW_PIXEL_CLOCK / MW8080BW_HTOTAL / MW8080BW_VTOTAL)
39 
40 // +4 is added to HBSTART because the hardware displays that many pixels after setting HBLANK
41 #define MW8080BW_HPIXCOUNT                (MW8080BW_HBSTART + 4)
42 
43 
44 class mw8080bw_state : public driver_device
45 {
46 public:
mw8080bw_state(const machine_config & mconfig,device_type type,const char * tag)47 	mw8080bw_state(const machine_config &mconfig, device_type type, const char *tag) :
48 		driver_device(mconfig, type, tag),
49 		m_maincpu(*this,"maincpu"),
50 		m_mb14241(*this,"mb14241"),
51 		m_watchdog(*this, "watchdog"),
52 		m_main_ram(*this, "main_ram"),
53 		m_discrete(*this, "discrete"),
54 		m_screen(*this, "screen")
55 	{ }
56 
57 	void blueshrk(machine_config &config);
58 	void bowler(machine_config &config);
59 	void checkmat(machine_config &config);
60 	void dogpatch(machine_config &config);
61 	void invad2ct(machine_config &config);
62 	void invaders(machine_config &config);
63 	void maze(machine_config &config);
64 	void mw8080bw_root(machine_config &config);
65 	void phantom2(machine_config &config);
66 	void shuffle(machine_config &config);
67 	void tornbase(machine_config &config);
68 
69 	DECLARE_INPUT_CHANGED_MEMBER(direct_coin_count);
70 
71 	DECLARE_CUSTOM_INPUT_MEMBER(tornbase_hit_left_input_r);
72 	DECLARE_CUSTOM_INPUT_MEMBER(tornbase_hit_right_input_r);
73 	DECLARE_CUSTOM_INPUT_MEMBER(tornbase_pitch_left_input_r);
74 	DECLARE_CUSTOM_INPUT_MEMBER(tornbase_pitch_right_input_r);
75 	DECLARE_CUSTOM_INPUT_MEMBER(tornbase_score_input_r);
76 	DECLARE_CUSTOM_INPUT_MEMBER(blueshrk_coin_input_r);
77 
78 	DECLARE_CUSTOM_INPUT_MEMBER(invaders_sw6_sw7_r);
79 	DECLARE_CUSTOM_INPUT_MEMBER(invaders_sw5_r);
80 	DECLARE_CUSTOM_INPUT_MEMBER(invaders_in0_control_r);
81 	DECLARE_CUSTOM_INPUT_MEMBER(invaders_in1_control_r);
82 	DECLARE_CUSTOM_INPUT_MEMBER(invaders_in2_control_r);
83 
84 	DECLARE_MACHINE_RESET(mw8080bw);
85 
86 	IRQ_CALLBACK_MEMBER(interrupt_vector);
87 
88 protected:
89 	virtual void machine_start() override;
90 
91 	u8 mw8080bw_shift_result_rev_r();
92 
93 	int invaders_is_cabinet_cocktail();
94 
95 	uint32_t screen_update_invaders(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
96 	uint32_t screen_update_mw8080bw(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
97 
98 	// device/memory pointers
99 	required_device<cpu_device> m_maincpu;
100 	optional_device<mb14241_device> m_mb14241;
101 	optional_device<watchdog_timer_device> m_watchdog;
102 	required_shared_ptr<uint8_t> m_main_ram;
103 	optional_device<discrete_sound_device> m_discrete;
104 	required_device<screen_device> m_screen;
105 
106 	// misc game specific
107 	uint8_t       m_flip_screen;
108 
109 private:
110 	// misc game specific
111 	uint16_t      m_phantom2_cloud_counter;
112 	uint8_t       m_maze_tone_timing_state;   // output of IC C1, pin 5
113 
114 	// timers
115 	emu_timer   *m_interrupt_timer;
116 	emu_timer   *m_maze_tone_timer;
117 
118 	attotime m_interrupt_time;
119 
120 	void tornbase_io_w(offs_t offset, uint8_t data);
121 	void maze_coin_counter_w(uint8_t data);
122 	void maze_io_w(offs_t offset, uint8_t data);
123 	void checkmat_io_w(offs_t offset, uint8_t data);
124 	uint8_t bowler_shift_result_r();
125 	void bowler_lights_1_w(uint8_t data);
126 	void bowler_lights_2_w(uint8_t data);
127 	void bowler_audio_2_w(uint8_t data);
128 	void bowler_audio_3_w(uint8_t data);
129 	void bowler_audio_4_w(uint8_t data);
130 	void bowler_audio_5_w(uint8_t data);
131 	void bowler_audio_6_w(uint8_t data);
132 	DECLARE_MACHINE_START(maze);
133 	DECLARE_MACHINE_START(phantom2);
134 	DECLARE_MACHINE_START(invaders);
135 	uint32_t screen_update_phantom2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
136 	DECLARE_WRITE_LINE_MEMBER(screen_vblank_phantom2);
137 	TIMER_CALLBACK_MEMBER(maze_tone_timing_timer_callback);
138 	TIMER_CALLBACK_MEMBER(interrupt_trigger);
139 	void tornbase_audio_w(uint8_t data);
140 	void checkmat_audio_w(uint8_t data);
141 	void shuffle_audio_1_w(uint8_t data);
142 	void shuffle_audio_2_w(uint8_t data);
143 	void bowler_audio_1_w(uint8_t data);
144 	void blueshrk_audio_w(uint8_t data);
145 	void maze_update_discrete();
146 	void maze_write_discrete(uint8_t maze_tone_timing_state);
147 	uint8_t vpos_to_vysnc_chain_counter(int vpos);
148 	int vysnc_chain_counter_to_vpos(uint8_t counter, int vblank);
149 	void mw8080bw_create_interrupt_timer();
150 	void mw8080bw_start_interrupt_timer();
151 	uint8_t tornbase_get_cabinet_type();
152 
153 	void blueshrk_audio(machine_config &config);
154 	void bowler_audio(machine_config &config);
155 	void checkmat_audio(machine_config &config);
156 	void maze_audio(machine_config &config);
157 	void shuffle_audio(machine_config &config);
158 	void tornbase_audio(machine_config &config);
159 
160 	void blueshrk_io_map(address_map &map);
161 	void bowler_io_map(address_map &map);
162 	void checkmat_io_map(address_map &map);
163 	void dogpatch_io_map(address_map &map);
164 	void invad2ct_io_map(address_map &map);
165 	void invaders_io_map(address_map &map);
166 	void main_map(address_map &map);
167 	void maze_io_map(address_map &map);
168 	void phantom2_io_map(address_map &map);
169 	void shuffle_io_map(address_map &map);
170 	void tornbase_io_map(address_map &map);
171 };
172 
173 
174 #define SEAWOLF_ERASE_SW_PORT_TAG   ("ERASESW")
175 #define SEAWOLF_ERASE_DIP_PORT_TAG  ("ERASEDIP")
176 
177 class seawolf_state : public mw8080bw_state
178 {
179 public:
seawolf_state(machine_config const & mconfig,device_type type,char const * tag)180 	seawolf_state(machine_config const &mconfig, device_type type, char const *tag) :
181 		mw8080bw_state(mconfig, type, tag),
182 		m_erase_sw(*this, SEAWOLF_ERASE_SW_PORT_TAG),
183 		m_erase_dip(*this, SEAWOLF_ERASE_DIP_PORT_TAG),
184 		m_exp_lamps(*this, "EXP_LAMP_%X", 0U),
185 		m_torp_lamps(*this, "TORP_LAMP_%u", 1U),
186 		m_ready_lamp(*this, "READY_LAMP"),
187 		m_reload_lamp(*this, "RELOAD_LAMP")
188 	{
189 	}
190 
191 	void seawolf(machine_config &config);
192 
193 	DECLARE_CUSTOM_INPUT_MEMBER(erase_input_r);
194 
195 protected:
196 	virtual void machine_start() override;
197 
198 private:
199 	void explosion_lamp_w(u8 data);
200 	void periscope_lamp_w(u8 data);
201 
202 	void io_map(address_map &map);
203 
204 	required_ioport m_erase_sw;
205 	required_ioport m_erase_dip;
206 	output_finder<16> m_exp_lamps;
207 	output_finder<4> m_torp_lamps;
208 	output_finder<> m_ready_lamp;
209 	output_finder<> m_reload_lamp;
210 };
211 
212 
213 class gunfight_state : public mw8080bw_state
214 {
215 public:
gunfight_state(machine_config const & mconfig,device_type type,char const * tag)216 	gunfight_state(machine_config const &mconfig, device_type type, char const *tag) :
217 		mw8080bw_state(mconfig, type, tag),
218 		m_soundboard(*this, "soundboard")
219 	{
220 	}
221 
222 	void gunfight(machine_config &config);
223 
224 private:
225 	void io_w(offs_t offset, u8 data);
226 
227 	void io_map(address_map &map);
228 
229 	required_device<gunfight_audio_device> m_soundboard;
230 };
231 
232 
233 class boothill_state : public mw8080bw_state
234 {
235 public:
boothill_state(machine_config const & mconfig,device_type type,char const * tag)236 	boothill_state(machine_config const &mconfig, device_type type, char const *tag) :
237 		mw8080bw_state(mconfig, type, tag)
238 	{
239 	}
240 
241 	void boothill(machine_config &config);
242 	void gmissile(machine_config &config);
243 	void m4(machine_config &config);
244 
245 protected:
246 	virtual void machine_start() override;
247 
248 private:
249 	u8 reversible_shift_result_r();
250 	void reversible_shift_count_w(u8 data);
251 
252 	void boothill_io_map(address_map &map);
253 	void gmissile_io_map(address_map &map);
254 	void m4_io_map(address_map &map);
255 
256 	u8 m_rev_shift_res;
257 };
258 
259 
260 #define DESERTGU_GUN_X_PORT_TAG         ("GUNX")
261 #define DESERTGU_GUN_Y_PORT_TAG         ("GUNY")
262 
263 #define DESERTGU_DIP_SW_0_1_SET_1_TAG   ("DIPSW01SET1")
264 #define DESERTGU_DIP_SW_0_1_SET_2_TAG   ("DIPSW01SET2")
265 
266 class desertgu_state : public mw8080bw_state
267 {
268 public:
desertgu_state(machine_config const & mconfig,device_type type,char const * tag)269 	desertgu_state(machine_config const &mconfig, device_type type, char const *tag) :
270 		mw8080bw_state(mconfig, type, tag),
271 		m_gun_port(*this, { DESERTGU_GUN_Y_PORT_TAG, DESERTGU_GUN_X_PORT_TAG }),
272 		m_dip_sw_0_1(*this, { DESERTGU_DIP_SW_0_1_SET_1_TAG, DESERTGU_DIP_SW_0_1_SET_2_TAG })
273 	{
274 	}
275 
276 	void desertgu(machine_config &config);
277 
278 	DECLARE_CUSTOM_INPUT_MEMBER(gun_input_r);
279 	DECLARE_CUSTOM_INPUT_MEMBER(dip_sw_0_1_r);
280 
281 protected:
282 	virtual void machine_start() override;
283 
284 private:
285 	void io_map(address_map &map);
286 
287 	required_ioport_array<2> m_gun_port;
288 	required_ioport_array<2> m_dip_sw_0_1;
289 	u8 m_controller_select;
290 };
291 
292 
293 #define DPLAY_L_PITCH_PORT_TAG      ("LPITCH")
294 #define DPLAY_R_PITCH_PORT_TAG      ("RPITCH")
295 #define DPLAY_CAB_TYPE_PORT_TAG     ("CAB")
296 
297 class dplay_state : public mw8080bw_state
298 {
299 public:
dplay_state(machine_config const & mconfig,device_type type,char const * tag)300 	dplay_state(machine_config const &mconfig, device_type type, char const *tag) :
301 		mw8080bw_state(mconfig, type, tag),
302 		m_l_pitch(*this, DPLAY_L_PITCH_PORT_TAG),
303 		m_r_pitch(*this, DPLAY_L_PITCH_PORT_TAG),
304 		m_cab_type(*this, DPLAY_CAB_TYPE_PORT_TAG)
305 	{
306 	}
307 
308 	void dplay(machine_config &config);
309 
310 	DECLARE_CUSTOM_INPUT_MEMBER(dplay_pitch_left_input_r);
311 	DECLARE_CUSTOM_INPUT_MEMBER(dplay_pitch_right_input_r);
312 
313 private:
314 	void io_map(address_map &map);
315 
316 	required_ioport m_l_pitch;
317 	required_ioport m_r_pitch;
318 	required_ioport m_cab_type;
319 };
320 
321 
322 class clowns_state : public mw8080bw_state
323 {
324 public:
clowns_state(machine_config const & mconfig,device_type type,char const * tag)325 	clowns_state(machine_config const &mconfig, device_type type, char const *tag) :
326 		mw8080bw_state(mconfig, type, tag),
327 		m_controllers(*this, "CONTP%u", 1U)
328 	{
329 	}
330 
331 	void clowns(machine_config &config);
332 	void spacwalk(machine_config &config);
333 
334 	DECLARE_CUSTOM_INPUT_MEMBER(controller_r);
335 
336 protected:
337 	virtual void machine_start() override;
338 
339 private:
340 	void clowns_io_map(address_map &map);
341 	void spacwalk_io_map(address_map &map);
342 
343 	required_ioport_array<2> m_controllers;
344 	u8 m_controller_select;
345 };
346 
347 
348 class spcenctr_state : public mw8080bw_state
349 {
350 public:
spcenctr_state(machine_config const & mconfig,device_type type,char const * tag)351 	spcenctr_state(machine_config const &mconfig, device_type type, char const *tag) :
352 		mw8080bw_state(mconfig, type, tag),
353 		m_soundboard(*this, "soundboard")
354 	{
355 	}
356 
357 	void spcenctr(machine_config &config);
358 
359 protected:
360 	virtual void machine_start() override;
361 
362 private:
363 	void io_w(offs_t offset, u8 data);
364 
365 	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect);
366 
367 	void io_map(address_map &map);
368 
369 	required_device<spcenctr_audio_device> m_soundboard;
370 	u8 m_trench_width;
371 	u8 m_trench_center;
372 	u8 m_trench_slope[16];  // 16x4 bit RAM
373 	u8 m_bright_control;
374 	u8 m_brightness;
375 };
376 
377 
378 class zzzap_state : public mw8080bw_state
379 {
380 public:
zzzap_state(machine_config const & mconfig,device_type type,char const * tag)381 	zzzap_state(machine_config const &mconfig, device_type type, char const *tag) :
382 		mw8080bw_state(mconfig, type, tag)
383 	{
384 	}
385 
386 	void zzzap(machine_config &config);
387 
388 	void lagunar(machine_config &config);
389 
390 protected:
391 	void zzzap_common(machine_config &config);
392 
393 private:
394 	void io_map(address_map &map);
395 };
396 
397 
398 #define TORNBASE_CAB_TYPE_UPRIGHT_OLD   (0)
399 #define TORNBASE_CAB_TYPE_UPRIGHT_NEW   (1)
400 #define TORNBASE_CAB_TYPE_COCKTAIL      (2)
401 
402 #define INVADERS_CAB_TYPE_PORT_TAG      ("CAB")
403 #define INVADERS_P1_CONTROL_PORT_TAG    ("CONTP1")
404 #define INVADERS_P2_CONTROL_PORT_TAG    ("CONTP2")
405 #define INVADERS_SW6_SW7_PORT_TAG       ("SW6SW7")
406 #define INVADERS_SW5_PORT_TAG           ("SW5")
407 
408 #define BLUESHRK_SPEAR_PORT_TAG         ("IN0")
409 
410 #define INVADERS_CONTROL_PORT_P1 \
411 	PORT_START(INVADERS_P1_CONTROL_PORT_TAG) \
412 	INVADERS_CONTROL_PORT_PLAYER(1)
413 
414 #define INVADERS_CONTROL_PORT_P2 \
415 	PORT_START(INVADERS_P2_CONTROL_PORT_TAG) \
416 	INVADERS_CONTROL_PORT_PLAYER(2)
417 
418 #define INVADERS_CONTROL_PORT_PLAYER(player) \
419 	PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(player) \
420 	PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_PLAYER(player) \
421 	PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_PLAYER(player) \
422 	PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )
423 
424 #define INVADERS_CAB_TYPE_PORT \
425 	PORT_START(INVADERS_CAB_TYPE_PORT_TAG) \
426 	PORT_CONFNAME( 0x01, 0x00, DEF_STR( Cabinet ) ) \
427 	PORT_CONFSETTING(    0x00, DEF_STR( Upright ) ) \
428 	PORT_CONFSETTING(    0x01, DEF_STR( Cocktail ) )
429 
430 /*----------- defined in drivers/mw8080bw.c -----------*/
431 
432 extern const internal_layout layout_invaders;
433 
434 #endif // MAME_INCLUDES_MW8080BW_H
435