1 // license: BSD-3-Clause
2 // copyright-holders: Mathis Rosenhauer, Dirk Best
3 // thanks-to: Jonathan Gevaryahu
4 /***************************************************************************
5 
6     Beezer
7 
8     (c) 1982 Tong Electronic
9 
10     Notes:
11     - To enter test mode, hold down 1P Start and 2P Start, then reset
12       (only works for version 9.0)
13     - One of the ROMs contains a message that this game was created
14       by "Pacific Polytechnical Corporation, Santa Cruz"
15 
16     TODO:
17     - Improve sound (filters? A reference recording would be nice)
18     - Schematics in the sound area seem incomplete, there are
19       several unknown connections
20     - Watchdog timing (controlled by a 555)
21     - Figure out differences between the two sets (test mode isn't
22       working in beezer1, instruction screen is different)
23     - Verify accuracy of colors
24 
25 ***************************************************************************/
26 
27 #include "emu.h"
28 #include "cpu/m6809/m6809.h"
29 #include "machine/input_merger.h"
30 #include "machine/timer.h"
31 #include "machine/watchdog.h"
32 #include "machine/bankdev.h"
33 #include "machine/6522via.h"
34 #include "machine/6840ptm.h"
35 #include "sound/mm5837.h"
36 #include "sound/dac76.h"
37 #include "video/resnet.h"
38 #include "emupal.h"
39 #include "screen.h"
40 #include "speaker.h"
41 
42 
43 //**************************************************************************
44 //  TYPE DEFINITIONS
45 //**************************************************************************
46 
47 class beezer_state : public driver_device
48 {
49 public:
beezer_state(const machine_config & mconfig,device_type type,const char * tag)50 	beezer_state(const machine_config &mconfig, device_type type, const char *tag) :
51 		driver_device(mconfig, type, tag),
52 		m_maincpu(*this, "maincpu"),
53 		m_sysbank(*this, "sysbank"),
54 		m_banked_roms(*this, "banked"),
55 		m_rombank{ {*this, "rombank_f1"}, {*this, "rombank_f3"}, {*this, "rombank_e1"}, {*this, "rombank_e3"}, {*this, "rombank_e5"}, {*this, "rombank_f5"}, {*this, "rombank_f7"} },
56 		m_via_system(*this, "via_u6"),
57 		m_screen(*this, "screen"),
58 		m_palette(*this, "palette"),
59 		m_videoram(*this, "videoram"),
60 		m_audiocpu(*this, "audiocpu"),
61 		m_via_audio(*this, "via_u18"),
62 		m_ptm(*this, "ptm"),
63 		m_dac(*this, "dac"),
64 		m_dac_timer(nullptr),
65 		m_scanline_timer(nullptr),
66 		m_count(0), m_noise(0),
67 		m_pbus(0xff), m_x(0), m_y(0), m_z(0)
68 	{
69 		m_ch_sign[0] = m_ch_sign[1] = m_ch_sign[2] = m_ch_sign[3] = 0;
70 		m_dac_data[0] = m_dac_data[1] = m_dac_data[2] = m_dac_data[3] = 0;
71 	}
72 
73 	void scanline_cb();
74 	void dac_update_cb();
75 	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
76 	void palette_init(palette_device &palette);
77 	void palette_w(offs_t offset, uint8_t data);
78 	uint8_t line_r();
79 
80 	DECLARE_WRITE_LINE_MEMBER(noise_w);
81 	void dac_w(offs_t offset, uint8_t data);
82 	uint8_t via_audio_pa_r();
83 	void via_audio_pa_w(uint8_t data);
84 	void via_audio_pb_w(uint8_t data);
85 	DECLARE_WRITE_LINE_MEMBER(ptm_o1_w);
86 	DECLARE_WRITE_LINE_MEMBER(ptm_o2_w);
87 	DECLARE_WRITE_LINE_MEMBER(ptm_o3_w);
88 	DECLARE_WRITE_LINE_MEMBER(dmod_clr_w);
89 	DECLARE_WRITE_LINE_MEMBER(dmod_data_w);
90 
91 	uint8_t via_system_pa_r();
92 	uint8_t via_system_pb_r();
93 	void via_system_pa_w(uint8_t data);
94 	void via_system_pb_w(uint8_t data);
95 	void bankswitch_w(uint8_t data);
96 
97 	void beezer(machine_config &config);
98 	void banked_map(address_map &map);
99 	void main_map(address_map &map);
100 	void sound_map(address_map &map);
101 protected:
102 	virtual void machine_start() override;
103 	virtual void machine_reset() override;
104 
105 	enum
106 	{
107 		TIMER_DAC,
108 		TIMER_SCANLINE
109 	};
110 
111 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
112 
113 private:
114 	required_device<cpu_device> m_maincpu;
115 	required_device<address_map_bank_device> m_sysbank;
116 	required_memory_region m_banked_roms;
117 	required_memory_bank m_rombank[7];
118 	required_device<via6522_device> m_via_system;
119 	required_device<screen_device> m_screen;
120 	required_device<palette_device> m_palette;
121 	required_shared_ptr<uint8_t> m_videoram;
122 	required_device<cpu_device> m_audiocpu;
123 	required_device<via6522_device> m_via_audio;
124 	required_device<ptm6840_device> m_ptm;
125 	required_device<dac76_device> m_dac;
126 
127 	double m_weights_r[3];
128 	double m_weights_g[3];
129 	double m_weights_b[2];
130 
131 	emu_timer *m_dac_timer;
132 	emu_timer *m_scanline_timer;
133 
134 	int m_ch_sign[4];
135 	uint8_t m_dac_data[4];
136 	int m_count;
137 	int m_noise;
138 
139 	uint8_t m_pbus;
140 	int m_x, m_y, m_z;
141 };
142 
143 
144 //**************************************************************************
145 //  ADDRESS MAPS
146 //**************************************************************************
147 
main_map(address_map & map)148 void beezer_state::main_map(address_map &map)
149 {
150 	map(0x0000, 0xbfff).ram().share("videoram");
151 	map(0xc000, 0xcfff).m(m_sysbank, FUNC(address_map_bank_device::amap8));
152 	map(0xd000, 0xdfff).rom().region("maincpu", 0x0000).w(FUNC(beezer_state::bankswitch_w)); // g1
153 	map(0xe000, 0xefff).rom().region("maincpu", 0x1000); // g3
154 	map(0xf000, 0xffff).rom().region("maincpu", 0x2000); // g5
155 }
156 
banked_map(address_map & map)157 void beezer_state::banked_map(address_map &map)
158 {
159 	map(0x0600, 0x0600).mirror(0x1ff).w("watchdog", FUNC(watchdog_timer_device::reset_w));
160 	map(0x0800, 0x080f).mirror(0x1f0).w(FUNC(beezer_state::palette_w));
161 	map(0x0a00, 0x0a00).mirror(0x1ff).r(FUNC(beezer_state::line_r));
162 	map(0x0e00, 0x0e0f).mirror(0x1f0).m("via_u6", FUNC(via6522_device::map));
163 	map(0x1000, 0x1fff).bankr("rombank_f1");
164 	map(0x2000, 0x2fff).bankr("rombank_f3");
165 	map(0x3000, 0x3fff).bankr("rombank_e1");
166 	map(0x4000, 0x4fff).bankr("rombank_e3");
167 	map(0x5000, 0x5fff).bankr("rombank_e5");
168 	map(0x6000, 0x6fff).bankr("rombank_f5");
169 	map(0x7000, 0x7fff).bankr("rombank_f7");
170 }
171 
sound_map(address_map & map)172 void beezer_state::sound_map(address_map &map)
173 {
174 	map(0x0000, 0x07ff).ram(); // 0d
175 	map(0x0800, 0x0fff).ram(); // 2d, optional (can be rom)
176 	map(0x1000, 0x1007).mirror(0x07f8).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write));
177 	map(0x1800, 0x180f).mirror(0x07f0).m(m_via_audio, FUNC(via6522_device::map));
178 	map(0x8000, 0x8003).mirror(0x1ffc).w(FUNC(beezer_state::dac_w));
179 //  map(0xa000, 0xbfff).rom(); // 2d (can be ram, unpopulated)
180 //  map(0xc000, 0xdfff).rom(); // 4d (unpopulated)
181 	map(0xe000, 0xffff).rom().region("audiocpu", 0); // 6d
182 }
183 
184 
185 //**************************************************************************
186 //  INPUTS
187 //**************************************************************************
188 
189 static INPUT_PORTS_START( beezer )
190 	PORT_START("IN0")
191 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_TILT )
192 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN1 )
193 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_START2 )
194 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
195 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
196 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
197 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
198 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
199 
200 	PORT_START("IN1")
201 	PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE
202 	PORT_START("IN2")
203 	PORT_BIT( 0x0f, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(10) PORT_REVERSE
204 
205 	// DSWA isn't populated on the board and is pulled to 0xff with a resistor pack
206 	PORT_START("DSWA")
207 	PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
208 
209 	PORT_START("DSWB")
DEF_STR(Coinage)210 	PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) )      PORT_DIPLOCATION("SWB:1,2")
211 	PORT_DIPSETTING(    0x02, DEF_STR( 2C_1C ) )
212 	PORT_DIPSETTING(    0x03, DEF_STR( 1C_1C ) )
213 	PORT_DIPSETTING(    0x00, DEF_STR( Free_Play ) )
214 	PORT_DIPNAME( 0x04, 0x00, DEF_STR( Lives ) )        PORT_DIPLOCATION("SWB:3")
215 	PORT_DIPSETTING(    0x04, "3" )
216 	PORT_DIPSETTING(    0x00, "4" )
217 	PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )  PORT_DIPLOCATION("SWB:4")
218 	PORT_DIPSETTING(    0x00, DEF_STR( Off ) )
219 	PORT_DIPSETTING(    0x08, DEF_STR( On ) )
220 	PORT_DIPNAME( 0x30, 0x10, DEF_STR( Bonus_Life ) )   PORT_DIPLOCATION("SWB:5,6")
221 	PORT_DIPSETTING(    0x20, "30000" )
222 	PORT_DIPSETTING(    0x10, "60000" )
223 	PORT_DIPSETTING(    0x00, "90000" )
224 	PORT_DIPSETTING(    0x30, DEF_STR( No ) )
225 	PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Difficulty ) )   PORT_DIPLOCATION("SWB:7,8")
226 	PORT_DIPSETTING(    0xc0, DEF_STR( Easy ) )
227 	PORT_DIPSETTING(    0x80, DEF_STR( Medium ) )
228 	PORT_DIPSETTING(    0x40, DEF_STR( Hard ) )
229 	PORT_DIPSETTING(    0x00, DEF_STR( Hardest ) )
230 INPUT_PORTS_END
231 
232 
233 //**************************************************************************
234 //  VIDEO EMULATION
235 //**************************************************************************
236 
237 void beezer_state::scanline_cb()
238 {
239 	const int scanline = m_screen->vpos();
240 
241 	// TDISP, each 32 lines
242 	m_via_system->write_ca2((scanline & 32) ? 1 : 0);
243 
244 	// actually unused by the game (points to a tight loop)
245 	if (scanline == 240)
246 		m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
247 	else
248 		m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
249 
250 
251 	m_scanline_timer->adjust(m_screen->time_until_pos(scanline + 1));
252 }
253 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)254 uint32_t beezer_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
255 {
256 	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
257 	{
258 		for (int x = cliprect.min_x; x <= cliprect.max_x; x += 2)
259 		{
260 			bitmap.pix(y, x + 1) = m_videoram[0x80 * x + y] & 0x0f;
261 			bitmap.pix(y, x + 0) = m_videoram[0x80 * x + y] >> 4;
262 		}
263 	}
264 
265 	return 0;
266 }
267 
palette_init(palette_device & device)268 void beezer_state::palette_init(palette_device &device)
269 {
270 	const int resistances_rg[3] = { 1200, 560, 330 };
271 	const int resistances_b[2]  = { 560, 330 };
272 
273 	// calculate coefficients for later use
274 	compute_resistor_weights(0, 255, -1.0,
275 		3, resistances_rg, m_weights_r, 680, 150,
276 		3, resistances_rg, m_weights_g, 680, 150,
277 		2, resistances_b,  m_weights_b, 680, 150);
278 }
279 
palette_w(offs_t offset,uint8_t data)280 void beezer_state::palette_w(offs_t offset, uint8_t data)
281 {
282 	int r = combine_weights(m_weights_r, BIT(data, 0), BIT(data, 1), BIT(data, 2));
283 	int g = combine_weights(m_weights_g, BIT(data, 3), BIT(data, 4), BIT(data, 5));
284 	int b = combine_weights(m_weights_b, BIT(data, 6), BIT(data, 7));
285 
286 	m_palette->set_pen_color(offset, rgb_t(r, g, b));
287 }
288 
line_r()289 uint8_t beezer_state::line_r()
290 {
291 	// d2 to d7 connected to hex buffer u34
292 	return m_screen->vpos() & 0xfc;
293 }
294 
295 
296 //**************************************************************************
297 //  AUDIO
298 //**************************************************************************
299 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)300 void beezer_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
301 {
302 	switch (id)
303 	{
304 	case TIMER_DAC: dac_update_cb(); break;
305 	case TIMER_SCANLINE: scanline_cb(); break;
306 	default: throw emu_fatalerror("Unknown id in beezer_state::device_timer");
307 	}
308 }
309 
dac_update_cb()310 void beezer_state::dac_update_cb()
311 {
312 	// channel multiplexer at u52
313 	int ch = m_count++ & 3;
314 
315 	m_dac->update();
316 
317 	m_dac->b1_w(BIT(m_dac_data[ch], 6));
318 	m_dac->b2_w(BIT(m_dac_data[ch], 5));
319 	m_dac->b3_w(BIT(m_dac_data[ch], 4));
320 	m_dac->b4_w(BIT(m_dac_data[ch], 3));
321 	m_dac->b5_w(BIT(m_dac_data[ch], 2));
322 	m_dac->b6_w(BIT(m_dac_data[ch], 1));
323 	m_dac->b7_w(BIT(m_dac_data[ch], 0));
324 
325 	m_dac->sb_w(m_ch_sign[ch] ^ BIT(m_dac_data[ch], 7));
326 }
327 
WRITE_LINE_MEMBER(beezer_state::noise_w)328 WRITE_LINE_MEMBER( beezer_state::noise_w )
329 {
330 	m_noise = state;
331 	m_via_audio->write_pb6(m_noise);
332 }
333 
dac_w(offs_t offset,uint8_t data)334 void beezer_state::dac_w(offs_t offset, uint8_t data)
335 {
336 	m_dac_data[offset] = data;
337 }
338 
via_audio_pa_r()339 uint8_t beezer_state::via_audio_pa_r()
340 {
341 	return m_pbus;
342 }
343 
via_audio_pa_w(uint8_t data)344 void beezer_state::via_audio_pa_w(uint8_t data)
345 {
346 	m_pbus = data;
347 }
348 
via_audio_pb_w(uint8_t data)349 void beezer_state::via_audio_pb_w(uint8_t data)
350 {
351 	// bit 0 - dmod disable
352 	// bit 1 - fm or am
353 	// bit 2 - am
354 	// bit 3 - fmsel0
355 	// bit 4 - fmsel1
356 	// -- above bits not handled and only partially visible on the schematic
357 
358 	// bit 7 - noise gate on rising edge to ptm c1
359 	if (m_ch_sign[0] == 0 && (BIT(data, 7) == 1))
360 		m_ptm->set_c1(m_noise);
361 
362 	m_ch_sign[0] = BIT(data, 7);
363 }
364 
WRITE_LINE_MEMBER(beezer_state::ptm_o1_w)365 WRITE_LINE_MEMBER( beezer_state::ptm_o1_w )
366 {
367 	m_ch_sign[1] = state;
368 }
369 
WRITE_LINE_MEMBER(beezer_state::ptm_o2_w)370 WRITE_LINE_MEMBER( beezer_state::ptm_o2_w )
371 {
372 	// on rising edge, enable noise input to ptm c3
373 	if (m_ch_sign[2] == 0 && state == 1)
374 		m_ptm->set_c3(m_noise);
375 
376 	m_ch_sign[2] = state;
377 }
378 
WRITE_LINE_MEMBER(beezer_state::ptm_o3_w)379 WRITE_LINE_MEMBER( beezer_state::ptm_o3_w )
380 {
381 	m_ch_sign[3] = state;
382 }
383 
WRITE_LINE_MEMBER(beezer_state::dmod_clr_w)384 WRITE_LINE_MEMBER( beezer_state::dmod_clr_w )
385 {
386 	// schematics don't show where this is connected
387 }
388 
WRITE_LINE_MEMBER(beezer_state::dmod_data_w)389 WRITE_LINE_MEMBER( beezer_state::dmod_data_w )
390 {
391 	// schematics don't show where this is connected
392 }
393 
394 
395 //**************************************************************************
396 //  MACHINE EMULATION
397 //**************************************************************************
398 
via_system_pa_r()399 uint8_t beezer_state::via_system_pa_r()
400 {
401 	uint8_t data = 0;
402 
403 	data |= 1 << 4; // N/C
404 	data |= m_z << 5;
405 	data |= m_y << 6;
406 	data |= m_x << 7;
407 
408 	return data;
409 }
410 
via_system_pa_w(uint8_t data)411 void beezer_state::via_system_pa_w(uint8_t data)
412 {
413 	// bit 3, audio cpu reset line
414 	m_audiocpu->set_input_line(INPUT_LINE_RESET, BIT(data, 3) ? CLEAR_LINE : ASSERT_LINE);
415 
416 	// bit 2, enable for ls139
417 	if (BIT(data, 2) == 0)
418 	{
419 		// bit 0-1, input selection
420 		switch (data & 0x03)
421 		{
422 		case 0:
423 			m_pbus = ioport("IN0")->read();
424 			break;
425 		case 1:
426 			m_pbus = ioport("IN1")->read() | (ioport("IN2")->read() << 4);
427 			break;
428 		case 2:
429 			m_pbus = ioport("DSWB")->read();
430 			break;
431 		case 3:
432 			m_pbus = ioport("DSWA")->read();
433 			break;
434 		}
435 	}
436 }
437 
via_system_pb_r()438 uint8_t beezer_state::via_system_pb_r()
439 {
440 	return m_pbus;
441 }
442 
via_system_pb_w(uint8_t data)443 void beezer_state::via_system_pb_w(uint8_t data)
444 {
445 	m_pbus = data;
446 }
447 
bankswitch_w(uint8_t data)448 void beezer_state::bankswitch_w(uint8_t data)
449 {
450 	m_x = BIT(data, 3);
451 	m_y = BIT(data, 4);
452 	m_z = BIT(data, 5);
453 
454 	m_sysbank->set_bank(data & 0x07);
455 
456 	for (int i = 0; i < 7; i++)
457 		m_rombank[i]->set_entry(m_x);
458 }
459 
machine_start()460 void beezer_state::machine_start()
461 {
462 	// configure rom banks
463 	for (int i = 0; i < 7; i++)
464 		m_rombank[i]->configure_entries(0, 2, m_banked_roms->base() + (i * 0x2000), 0x1000);
465 
466 	// allocate timers
467 	m_dac_timer = timer_alloc(TIMER_DAC);
468 	m_scanline_timer = timer_alloc(TIMER_SCANLINE);
469 
470 	// register for state saving
471 	save_item(NAME(m_ch_sign));
472 	save_item(NAME(m_dac_data));
473 	save_item(NAME(m_count));
474 	save_item(NAME(m_noise));
475 	save_item(NAME(m_pbus));
476 	save_item(NAME(m_x));
477 	save_item(NAME(m_y));
478 	save_item(NAME(m_z));
479 }
480 
machine_reset()481 void beezer_state::machine_reset()
482 {
483 	m_pbus = 0xff;
484 
485 	// initialize memory banks
486 	bankswitch_w(0);
487 
488 	// start timer
489 	m_dac_timer->adjust(attotime::zero, 0, attotime::from_hz((XTAL(4'000'000) / 4) / 16));
490 	m_scanline_timer->adjust(m_screen->scan_period());
491 }
492 
493 
494 //**************************************************************************
495 //  MACHINE DEFINTIONS
496 //**************************************************************************
497 
beezer(machine_config & config)498 void beezer_state::beezer(machine_config &config)
499 {
500 	// basic machine hardware
501 	MC6809(config, m_maincpu, XTAL(12'000'000) / 3);
502 	m_maincpu->set_addrmap(AS_PROGRAM, &beezer_state::main_map);
503 
504 	ADDRESS_MAP_BANK(config, m_sysbank, 0);
505 	m_sysbank->set_addrmap(AS_PROGRAM, &beezer_state::banked_map);
506 	m_sysbank->set_endianness(ENDIANNESS_BIG);
507 	m_sysbank->set_data_width(8);
508 	m_sysbank->set_addr_width(15);
509 	m_sysbank->set_stride(0x1000);
510 
511 	VIA6522(config, m_via_system, XTAL(12'000'000) / 12);
512 	m_via_system->readpa_handler().set(FUNC(beezer_state::via_system_pa_r));
513 	m_via_system->readpb_handler().set(FUNC(beezer_state::via_system_pb_r));
514 	m_via_system->writepa_handler().set(FUNC(beezer_state::via_system_pa_w));
515 	m_via_system->writepb_handler().set(FUNC(beezer_state::via_system_pb_w));
516 	m_via_system->cb1_handler().set(m_via_audio, FUNC(via6522_device::write_ca2));
517 	m_via_system->cb2_handler().set(m_via_audio, FUNC(via6522_device::write_ca1));
518 	m_via_system->irq_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
519 
520 	WATCHDOG_TIMER(config, "watchdog");
521 
522 	// video hardware
523 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
524 	m_screen->set_refresh_hz(60);
525 	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
526 	m_screen->set_size(384, 256);
527 	m_screen->set_visarea(16, 304-1, 0, 240-1); // 288 x 240, correct?
528 	m_screen->set_screen_update(FUNC(beezer_state::screen_update));
529 	m_screen->set_palette(m_palette);
530 
531 	PALETTE(config, m_palette, FUNC(beezer_state::palette_init), 16);
532 
533 	// sound hardware
534 	MC6809(config, m_audiocpu, XTAL(4'000'000));
535 	m_audiocpu->set_addrmap(AS_PROGRAM, &beezer_state::sound_map);
536 
537 	input_merger_device &audio_irqs(INPUT_MERGER_ANY_HIGH(config, "audio_irqs"));
538 	audio_irqs.output_handler().set_inputline(m_audiocpu, M6809_IRQ_LINE);
539 
540 	VIA6522(config, m_via_audio, XTAL(4'000'000) / 4);
541 	m_via_audio->readpa_handler().set(FUNC(beezer_state::via_audio_pa_r));
542 	m_via_audio->writepa_handler().set(FUNC(beezer_state::via_audio_pa_w));
543 	m_via_audio->writepb_handler().set(FUNC(beezer_state::via_audio_pb_w));
544 	m_via_audio->ca2_handler().set(m_via_system, FUNC(via6522_device::write_cb1));
545 	m_via_audio->cb1_handler().set(FUNC(beezer_state::dmod_clr_w));
546 	m_via_audio->cb2_handler().set(FUNC(beezer_state::dmod_data_w));
547 	m_via_audio->irq_handler().set("audio_irqs", FUNC(input_merger_device::in_w<0>));
548 
549 	PTM6840(config, m_ptm, XTAL(4'000'000) / 4);
550 	m_ptm->o1_callback().set(FUNC(beezer_state::ptm_o1_w));
551 	m_ptm->o2_callback().set(FUNC(beezer_state::ptm_o2_w));
552 	m_ptm->o3_callback().set(FUNC(beezer_state::ptm_o3_w));
553 	m_ptm->irq_callback().set("audio_irqs", FUNC(input_merger_device::in_w<1>));
554 	// schematics show an input labeled VCO to channel 2, but the source is unknown
555 
556 	mm5837_device &noise(MM5837(config, "noise"));
557 	noise.set_vdd(-12);
558 	noise.output_callback().set(FUNC(beezer_state::noise_w));
559 
560 	SPEAKER(config, "speaker").front_center();
561 	DAC76(config, m_dac, 0);
562 	m_dac->add_route(ALL_OUTPUTS, "speaker", 1.0);
563 }
564 
565 
566 //**************************************************************************
567 //  ROM DEFINITIONS
568 //**************************************************************************
569 
570 ROM_START( beezer )
571 	ROM_REGION(0xc000, "maincpu", 0)
572 	ROM_LOAD("g1", 0x0000, 0x1000, CRC(3467a0ec) SHA1(0b094a9bf772b101acd26cf09009c67dd4785ed2))
573 	ROM_LOAD("g3", 0x1000, 0x1000, CRC(9950cdf2) SHA1(b2b59cc1080357de6ba297392881d626157df809))
574 	ROM_LOAD("g5", 0x2000, 0x1000, CRC(a4b09879) SHA1(69739dd1d3c88ee6ab310ca3c71b3b50d8ec618f))
575 
576 	// rom type can be either 2732 or 2764 in all locations
577 	ROM_REGION(0xe000, "banked", 0)
578 	ROM_LOAD("f1", 0x0000, 0x2000, CRC(ce1b0b8b) SHA1(8ed1d793928bb7afa041a4f61e0c2f78b4442f2f))
579 	ROM_LOAD("f3", 0x2000, 0x2000, CRC(6a11072a) SHA1(9700beaec669849da4d0e39d6dbf0b872d7f1b7f))
580 	ROM_LOAD("e1", 0x4000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539))
581 	ROM_RELOAD(0x5000, 0x1000)
582 	ROM_LOAD("e3", 0x6000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7))
583 	ROM_RELOAD(0x7000, 0x1000)
584 	ROM_LOAD("e5", 0x8000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a))
585 	ROM_RELOAD(0x9000, 0x1000)
586 	ROM_LOAD("f5", 0xa000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37))
587 	ROM_RELOAD(0xb000, 0x1000)
588 	ROM_LOAD("f7", 0xc000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a))
589 	ROM_RELOAD(0xd000, 0x1000)
590 
591 	ROM_REGION(0x2000, "audiocpu", 0)
592 	ROM_LOAD("d7", 0x1000, 0x1000, CRC(23b0782e) SHA1(7751327b84235a2e2700e4bdd21adec205c54f0e))
593 
594 	ROM_REGION(0x200, "proms", 0)
595 	ROM_LOAD("d1.cpu", 0x000, 0x100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2))
596 	ROM_LOAD("e1.cpu", 0x100, 0x100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b))
597 ROM_END
598 
599 ROM_START( beezer1 )
600 	ROM_REGION(0x3000, "maincpu", 0)
601 	ROM_LOAD("g1.32", 0x0000, 0x1000, CRC(3134cb93) SHA1(7d4a484378b66ccf2fded31885d6dfb2abae9317))
602 	ROM_LOAD("g3.32", 0x1000, 0x1000, CRC(a3cb2c2d) SHA1(1e17eb0eaf02f86865845a065a5f714fc51aa7d6))
603 	ROM_LOAD("g5.32", 0x2000, 0x1000, CRC(5e559bf9) SHA1(cd3713f3ed1215ea5c5640474ba6f005242cd093))
604 
605 	// rom type can be either 2732 or 2764 in all locations
606 	ROM_REGION(0xe000, "banked", 0)
607 	ROM_LOAD("f1.64", 0x0000, 0x2000, CRC(b8a78cca) SHA1(4218ef8c4c8e10d7cc47d6de4c4d189ef3c0f0a1))
608 	ROM_LOAD("f3.32", 0x2000, 0x1000, CRC(bfa023f5) SHA1(56fb15e2db61197e1aec5a5825beff7c788a4ba3))
609 	ROM_RELOAD(0x3000, 0x1000)
610 	ROM_LOAD("e1",    0x4000, 0x1000, CRC(21e4ca9b) SHA1(4024678a4006614051675858ba65db655931a539))
611 	ROM_RELOAD(0x5000, 0x1000)
612 	ROM_LOAD("e3",    0x6000, 0x1000, CRC(a4f735d7) SHA1(110061d1c63a331384729951f93a31e62744d0d7))
613 	ROM_RELOAD(0x7000, 0x1000)
614 	ROM_LOAD("e5",    0x8000, 0x1000, CRC(0485575b) SHA1(c3be070541459fad4da4a71604883b2f3043374a))
615 	ROM_RELOAD(0x9000, 0x1000)
616 	ROM_LOAD("f5",    0xa000, 0x1000, CRC(4b11f572) SHA1(4f283c98a7f1bcf534921b4a54cf564335c53e37))
617 	ROM_RELOAD(0xb000, 0x1000)
618 	ROM_LOAD("f7",    0xc000, 0x1000, CRC(bef67473) SHA1(5759ceeca0bb677cee97b74f1a1087d53c25463a))
619 	ROM_RELOAD(0xd000, 0x1000)
620 
621 	ROM_REGION(0x2000, "audiocpu", 0)
622 	ROM_LOAD("d7.32", 0x1000, 0x1000, CRC(b11028b5) SHA1(db8958f0bb12e333ce056da3338f1a824dda36e0))
623 
624 	ROM_REGION(0x200, "proms", 0)
625 	ROM_LOAD("d1.cpu", 0x000, 0x100, CRC(8db17a40) SHA1(0e04a4f5f99b302dbbbfda438808d549f8680fe2))
626 	ROM_LOAD("e1.cpu", 0x100, 0x100, CRC(3c775c5e) SHA1(ac86f45938c0c9d5fec1245bf86718442baf445b))
627 ROM_END
628 
629 
630 //**************************************************************************
631 //  SYSTEM DRIVERS
632 //**************************************************************************
633 
634 //    YEAR  NAME     PARENT  MACHINE  INPUT   CLASS         INIT        ROTATION  COMPANY            FULLNAME          FLAGS
635 GAME( 1982, beezer,  0,      beezer,  beezer, beezer_state, empty_init, ROT90,    "Tong Electronic", "Beezer (version 9.0)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // Has test mode, shows version
636 GAME( 1982, beezer1, beezer, beezer,  beezer, beezer_state, empty_init, ROT90,    "Tong Electronic", "Beezer (unknown earlier version)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // No test mode, possibly earlier?
637