1 // license:BSD-3-Clause
2 // copyright-holders:Gordon Jefferyes, Nigel Barnes
3 /*****************************************************************************
4  *
5  * BBC Model B/B+/Master/Compact
6  *
7  * Driver by Gordon Jefferyes <mess_bbc@romvault.com>
8  *
9  ****************************************************************************/
10 #ifndef MAME_INCLUDES_BBC_H
11 #define MAME_INCLUDES_BBC_H
12 
13 #pragma once
14 
15 #include "cpu/m6502/m6502.h"
16 #include "cpu/m6502/m65sc02.h"
17 #include "imagedev/floppy.h"
18 #include "machine/74259.h"
19 #include "machine/6522via.h"
20 #include "machine/6850acia.h"
21 #include "machine/clock.h"
22 #include "machine/mc6854.h"
23 #include "machine/ram.h"
24 #include "machine/wd_fdc.h"
25 #include "machine/upd7002.h"
26 #include "machine/mc146818.h"
27 #include "machine/i2cmem.h"
28 #include "machine/bankdev.h"
29 #include "machine/input_merger.h"
30 #include "video/mc6845.h"
31 #include "video/saa5050.h"
32 #include "sound/sn76496.h"
33 #include "sound/tms5220.h"
34 #include "sound/samples.h"
35 #include "imagedev/cassette.h"
36 
37 #include "bus/rs232/rs232.h"
38 #include "bus/centronics/ctronics.h"
39 #include "bus/econet/econet.h"
40 #include "bus/bbc/rom/slot.h"
41 #include "bus/bbc/fdc/fdc.h"
42 #include "bus/bbc/analogue/analogue.h"
43 #include "bus/bbc/1mhzbus/1mhzbus.h"
44 #include "bus/bbc/modem/modem.h"
45 #include "bus/bbc/internal/internal.h"
46 #include "bus/bbc/tube/tube.h"
47 #include "bus/bbc/userport/userport.h"
48 #include "bus/bbc/exp/exp.h"
49 #include "bus/bbc/joyport/joyport.h"
50 #include "bus/bbc/cart/slot.h"
51 
52 #include "emupal.h"
53 #include "screen.h"
54 
55 
56 class bbc_state : public driver_device
57 {
58 public:
bbc_state(const machine_config & mconfig,device_type type,const char * tag)59 	bbc_state(const machine_config &mconfig, device_type type, const char *tag)
60 		: driver_device(mconfig, type, tag)
61 		, m_maincpu(*this, "maincpu")
62 		, m_ram(*this, RAM_TAG)
63 		, m_hd6845(*this, "hd6845")
64 		, m_screen(*this, "screen")
65 		, m_irqs(*this, "irqs")
66 		, m_palette(*this, "palette")
67 		, m_adlc(*this, "mc6854")
68 		, m_sn(*this, "sn76489")
69 		, m_samples(*this, "samples")
70 		, m_keyboard(*this, "COL%u", 0)
71 		, m_trom(*this, "saa5050")
72 		, m_tms(*this, "tms5220")
73 		, m_cassette(*this, "cassette")
74 		, m_acia(*this, "acia6850")
75 		, m_acia_clock(*this, "acia_clock")
76 		, m_latch(*this, "latch")
77 		, m_rs232(*this, "rs423")
78 		, m_via6522_0(*this, "via6522_0")
79 		, m_via6522_1(*this, "via6522_1")
80 		, m_upd7002(*this, "upd7002")
81 		, m_analog(*this, "analogue")
82 		, m_joyport(*this, "joyport")
83 		, m_tube(*this, "tube")
84 		, m_intube(*this, "intube")
85 		, m_extube(*this, "extube")
86 		, m_1mhzbus(*this, "1mhzbus")
87 		, m_modem(*this, "modem")
88 		, m_userport(*this, "userport")
89 		, m_internal(*this, "internal")
90 		, m_exp(*this, "exp")
91 		, m_rtc(*this, "rtc")
92 		, m_i2cmem(*this, "i2cmem")
93 		, m_fdc(*this, "fdc")
94 		, m_wd_fdc(*this, "wd_fdc")
95 		, m_rom(*this, "romslot%u", 0U)
96 		, m_cart(*this, "cartslot%u", 1U)
97 		, m_region_mos(*this, "mos")
98 		, m_region_swr(*this, "swr")
99 		, m_bank1(*this, "bank1")
100 		, m_bank2(*this, "bank2")
101 		, m_bankdev(*this, "bankdev")
102 		, m_bbcconfig(*this, "BBCCONFIG")
103 		, m_motor_led(*this, "motor_led")
104 	{ }
105 
106 	enum class monitor_type
107 	{
108 		COLOUR,
109 		BLACKWHITE,
110 		GREEN,
111 		AMBER
112 	};
113 
114 	DECLARE_FLOPPY_FORMATS(floppy_formats);
115 
116 	uint8_t bbc_ram_r(offs_t offset);
117 	void bbc_ram_w(offs_t offset, uint8_t data);
118 	uint8_t bbc_romsel_r(offs_t offset);
119 	void bbc_romsel_w(offs_t offset, uint8_t data);
120 	uint8_t bbc_paged_r(offs_t offset);
121 	void bbc_paged_w(offs_t offset, uint8_t data);
122 	uint8_t bbc_mos_r(offs_t offset);
123 	void bbc_mos_w(offs_t offset, uint8_t data);
124 	uint8_t bbc_fred_r(offs_t offset);
125 	void bbc_fred_w(offs_t offset, uint8_t data);
126 	uint8_t bbc_jim_r(offs_t offset);
127 	void bbc_jim_w(offs_t offset, uint8_t data);
128 	uint8_t bbcbp_fetch_r(offs_t offset);
129 	void bbcbp_romsel_w(offs_t offset, uint8_t data);
130 	uint8_t bbcbp_paged_r(offs_t offset);
131 	void bbcbp_paged_w(offs_t offset, uint8_t data);
132 	uint8_t bbcm_fetch_r(offs_t offset);
133 	uint8_t bbcm_acccon_r();
134 	void bbcm_acccon_w(uint8_t data);
135 	void bbcm_romsel_w(offs_t offset, uint8_t data);
136 	uint8_t bbcm_paged_r(offs_t offset);
137 	void bbcm_paged_w(offs_t offset, uint8_t data);
138 	uint8_t bbcm_hazel_r(offs_t offset);
139 	void bbcm_hazel_w(offs_t offset, uint8_t data);
140 	uint8_t bbcm_tube_r(offs_t offset);
141 	void bbcm_tube_w(offs_t offset, uint8_t data);
142 	uint8_t bbcmc_paged_r(offs_t offset);
143 	void bbcmc_paged_w(offs_t offset, uint8_t data);
144 	void bbcbp_drive_control_w(uint8_t data);
145 	void bbcm_drive_control_w(uint8_t data);
146 	void serial_ula_w(uint8_t data);
147 	void video_ula_w(offs_t offset, uint8_t data);
bbc_fe_r()148 	uint8_t bbc_fe_r() { return 0xfe; };
149 
150 	DECLARE_VIDEO_START(bbc);
151 
152 	INTERRUPT_GEN_MEMBER(bbcb_keyscan);
153 	TIMER_CALLBACK_MEMBER(tape_timer_cb);
154 	TIMER_CALLBACK_MEMBER(reset_timer_cb);
155 	DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
156 	DECLARE_WRITE_LINE_MEMBER(adlc_irq_w);
157 	DECLARE_WRITE_LINE_MEMBER(bus_nmi_w);
158 	DECLARE_WRITE_LINE_MEMBER(snd_enable_w);
159 	DECLARE_WRITE_LINE_MEMBER(speech_rsq_w);
160 	DECLARE_WRITE_LINE_MEMBER(speech_wsq_w);
161 	DECLARE_WRITE_LINE_MEMBER(kbd_enable_w);
162 	uint8_t via_system_porta_r();
163 	void via_system_porta_w(uint8_t data);
164 	uint8_t via_system_portb_r();
165 	void via_system_portb_w(uint8_t data);
166 	DECLARE_WRITE_LINE_MEMBER(lpstb_w);
167 	DECLARE_WRITE_LINE_MEMBER(bbc_hsync_changed);
168 	DECLARE_WRITE_LINE_MEMBER(bbc_vsync_changed);
169 	DECLARE_WRITE_LINE_MEMBER(bbc_de_changed);
170 	DECLARE_INPUT_CHANGED_MEMBER(reset_palette);
171 	void update_palette(monitor_type monitor_type);
172 
173 	void update_acia_rxd();
174 	void update_acia_dcd();
175 	void update_acia_cts();
176 	DECLARE_WRITE_LINE_MEMBER(write_rts);
177 	DECLARE_WRITE_LINE_MEMBER(write_txd);
178 	DECLARE_WRITE_LINE_MEMBER(write_rxd);
179 	DECLARE_WRITE_LINE_MEMBER(write_dcd);
180 	DECLARE_WRITE_LINE_MEMBER(write_cts);
181 
182 	DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
183 	DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
184 	DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
185 
186 	int get_analogue_input(int channel_number);
187 	void upd7002_eoc(int data);
188 
189 	std::string get_rom_name(uint8_t* header);
190 	void insert_device_rom(memory_region *rom);
191 	void setup_device_roms();
192 
193 	MC6845_UPDATE_ROW(crtc_update_row);
194 
195 	void bbca(machine_config &config);
196 	void bbcb(machine_config &config);
197 	void bbcb_de(machine_config &config);
198 	void bbcb_us(machine_config &config);
199 
200 	void bbca_mem(address_map &map);
201 	void bbc_base(address_map &map);
202 	void bbcb_mem(address_map &map);
203 
204 	void init_bbc();
205 	void init_ltmp();
206 	void init_cfa();
207 
208 protected:
209 	virtual void machine_start() override;
210 	virtual void machine_reset() override;
211 
212 	virtual void video_start() override;
213 	virtual void video_reset() override;
214 
215 	required_device<cpu_device> m_maincpu;
216 	required_device<ram_device> m_ram;
217 	required_device<mc6845_device> m_hd6845;
218 	required_device<screen_device> m_screen;
219 	required_device<input_merger_device> m_irqs;
220 	required_device<palette_device> m_palette;
221 	optional_device<mc6854_device> m_adlc;
222 	optional_device<sn76489a_device> m_sn;
223 	optional_device<samples_device> m_samples;
224 	required_ioport_array<16> m_keyboard;
225 	optional_device<saa5050_device> m_trom;
226 	optional_device<tms5220_device> m_tms;
227 	optional_device<cassette_image_device> m_cassette;
228 	optional_device<acia6850_device> m_acia;
229 	optional_device<clock_device> m_acia_clock;
230 	required_device<ls259_device> m_latch;
231 	optional_device<rs232_port_device> m_rs232;
232 	required_device<via6522_device> m_via6522_0;
233 	optional_device<via6522_device> m_via6522_1;
234 	optional_device<upd7002_device> m_upd7002;
235 	optional_device<bbc_analogue_slot_device> m_analog;
236 	optional_device<bbc_joyport_slot_device> m_joyport;
237 	optional_device<bbc_tube_slot_device> m_tube;
238 	optional_device<bbc_tube_slot_device> m_intube;
239 	optional_device<bbc_tube_slot_device> m_extube;
240 	optional_device<bbc_1mhzbus_slot_device> m_1mhzbus;
241 	optional_device<bbc_modem_slot_device> m_modem;
242 	optional_device<bbc_userport_slot_device> m_userport;
243 	optional_device<bbc_internal_slot_device> m_internal;
244 	optional_device<bbc_exp_slot_device> m_exp;
245 	optional_device<mc146818_device> m_rtc;
246 	optional_device<i2cmem_device> m_i2cmem;
247 	optional_device<bbc_fdc_slot_device> m_fdc;
248 	optional_device<wd_fdc_digital_device_base> m_wd_fdc;
249 	optional_device_array<bbc_romslot_device, 16> m_rom;
250 	optional_device_array<bbc_cartslot_device, 2> m_cart;
251 
252 	required_memory_region m_region_mos;
253 	required_memory_region m_region_swr;
254 	optional_memory_bank m_bank1; //           bbcbp bbcbp128 bbcm
255 	optional_memory_bank m_bank2; //           bbcbp bbcbp128 bbcm
256 	optional_device<address_map_bank_device> m_bankdev; //    bbcm
257 	optional_ioport m_bbcconfig;
258 
259 	output_finder<> m_motor_led;
260 
261 	int m_romsel;           // This is the latch that holds the sideways ROM bank to read
262 	int m_paged_ram;        // BBC B+ memory handling
263 	int m_vdusel;           // BBC B+ memory handling
264 
265 	/*
266 	    ACCCON
267 	    b7 IRR  1=Causes an IRQ to the processor
268 	    b6 TST  1=Selects &FC00-&FEFF read from OS-ROM
269 	    b5 IFJ  1=Internal 1 MHz bus
270 	            0=External 1MHz bus
271 	    b4 ITU  1=Internal Tube
272 	            0=External Tube
273 	    b3 Y    1=Read/Write HAZEL &C000-&DFFF RAM
274 	            0=Read/Write ROM &C000-&DFFF OS-ROM
275 	    b2 X    1=Read/Write LYNNE
276 	            0=Read/WRITE main memory &3000-&8000
277 	    b1 E    1=Causes shadow if VDU code
278 	            0=Main all the time
279 	    b0 D    1=Display LYNNE as screen
280 	            0=Display main RAM screen
281 	    ACCCON is a read/write register
282 	*/
283 
284 	int m_acccon;
285 	int m_acccon_irr;
286 	int m_acccon_tst;
287 	int m_acccon_ifj;
288 	int m_acccon_itu;
289 	int m_acccon_y;
290 	int m_acccon_x;
291 	int m_acccon_e;
292 	int m_acccon_d;
293 
294 	void mc146818_set();
295 	int m_mc146818_as;      // 6522 port b bit 7
296 	int m_mc146818_ce;      // 6522 port b bit 6
297 
298 	int m_via_system_porta;
299 
300 	// interrupt state
301 	int m_adlc_irq;
302 	int m_bus_nmi;
303 
304 	int m_column;           // this is a counter in the keyboard circuit
305 
306 	/***************************************
307 	  BBC 2C199 Serial Interface Cassette
308 	****************************************/
309 
310 	double m_last_dev_val;
311 	int m_wav_len;
312 	int m_len0;
313 	int m_len1;
314 	int m_len2;
315 	int m_len3;
316 	uint8_t m_serproc_data;
317 	int m_rxd_serial;
318 	int m_dcd_serial;
319 	int m_cts_serial;
320 	int m_dcd_cass;
321 	int m_rxd_cass;
322 	int m_cass_out_enabled;
323 	int m_txd;
324 	uint32_t m_nr_high_tones;
325 	int m_cass_out_samples_to_go;
326 	int m_cass_out_bit;
327 	int m_cass_out_phase;
328 	emu_timer *m_tape_timer;
329 
330 
331 	/**************************************
332 	  WD1770 disc control
333 	***************************************/
334 
335 	int m_fdc_irq;
336 	int m_fdc_drq;
337 
338 	/**************************************
339 	  Video Code
340 	***************************************/
341 
342 // this is the real location of the start of the BBC's ram in the emulation
343 // it can be changed if shadow ram is being used to point at the upper 32K of RAM
344 	uint8_t *m_video_ram;
345 	uint8_t m_pixel_bits[256];
346 	int m_hsync;
347 	int m_vsync;
348 
349 	uint8_t m_teletext_latch;
350 	uint8_t m_vula_ctrl;
351 
352 	struct video_nula {
353 		uint8_t palette_mode;
354 		uint8_t horiz_offset;
355 		uint8_t left_blank;
356 		uint8_t disable;
357 		uint8_t attr_mode;
358 		uint8_t attr_text;
359 		uint8_t flash[8];
360 		uint8_t palette_byte;
361 		uint8_t palette_write;
362 	} m_vnula;
363 
364 	int m_pixels_per_byte;
365 	int m_cursor_size;
366 
367 	uint8_t m_vula_palette[16];
368 	uint8_t m_vula_palette_lookup[16];
369 
370 	void setvideoshadow(int vdusel);
371 	void set_pixel_lookup();
372 	uint8_t bus_video_data();
373 	int bbc_keyboard(int data);
374 
375 	void mc6850_receive_clock(int new_clock);
376 	void cassette_motor(bool state);
377 	void update_nmi();
378 	uint16_t calculate_video_address(uint16_t ma, uint8_t ra);
379 
380 private:
381 	emu_timer *m_reset_timer;
382 };
383 
384 
385 class torch_state : public bbc_state
386 {
387 public:
388 	using bbc_state::bbc_state;
imperfect_features()389 	static constexpr feature_type imperfect_features() { return feature::KEYBOARD; }
390 
391 	void torchf(machine_config &config);
392 	void torchh(machine_config &config);
393 	void torch301(machine_config &config);
394 	void torch725(machine_config &config);
395 };
396 
397 
398 class bbcbp_state : public bbc_state
399 {
400 public:
401 	using bbc_state::bbc_state;
402 
403 	void bbcbp(machine_config &config);
404 	void bbcbp128(machine_config &config);
405 	void abc110(machine_config &config);
406 	void acw443(machine_config &config);
407 	void abc310(machine_config &config);
408 	void cfa3000bp(machine_config &config);
409 	void econx25(machine_config &config);
410 	void reutapm(machine_config &config);
411 
412 protected:
413 	virtual void machine_start() override;
414 	virtual void machine_reset() override;
415 
416 	void bbcbp_mem(address_map &map);
417 	void reutapm_mem(address_map &map);
418 	void bbcbp_fetch(address_map &map);
419 };
420 
421 
422 class bbcm_state : public bbc_state
423 {
424 public:
bbcm_state(const machine_config & mconfig,device_type type,const char * tag)425 	bbcm_state(const machine_config &mconfig, device_type type, const char *tag)
426 		: bbc_state(mconfig, type, tag)
427 		, m_power_led(*this, "power_led")
428 	{ }
429 
430 	void bbcm(machine_config &config);
431 	void bbcmt(machine_config &config);
432 	void bbcmet(machine_config &config);
433 	void bbcmaiv(machine_config &config);
434 	void bbcm512(machine_config &config);
435 	void bbcmarm(machine_config &config);
436 	void cfa3000(machine_config &config);
437 	void daisy(machine_config &config);
438 	void discmon(machine_config &config);
439 	void discmate(machine_config &config);
440 	void mpc800(machine_config& config);
441 	void mpc900(machine_config& config);
442 	void mpc900gx(machine_config& config);
443 	void bbcmc(machine_config &config);
444 	void pro128s(machine_config &config);
445 	void autoc15(machine_config &config);
446 
447 	static void mpc_prisma_default(device_t *device);
448 
449 protected:
450 	virtual void machine_start() override;
451 	virtual void machine_reset() override;
452 
453 	void bbcm_mem(address_map &map);
454 	void bbcm_bankdev(address_map &map);
455 	void bbcmet_bankdev(address_map &map);
456 	void bbcmc_mem(address_map &map);
457 	void bbcmc_bankdev(address_map &map);
458 	void autoc15_bankdev(address_map &map);
459 	void bbcm_fetch(address_map &map);
460 
461 	output_finder<> m_power_led;
462 };
463 
464 
465 #endif // MAME_INCLUDES_BBC_H
466