1 // license:BSD-3-Clause
2 // copyright-holders:Barry Rodewald, 68bit
3 /*
4     Gimix 6809-Based Computers
5 
6     Representative group of GIMIX users included:  Government Research and Scientific Organizations, Universities, Industrial, Computer Mainframe and
7     Peripheral Manufacturers and Software Houses.
8 
9     This system is most notable for being the development base of the "Vid Kidz", a pair of programmers (Eugene Jarvis and Larry DeMar) who formerly
10     worked for Williams Electronics on the game, Defender.  They left Willams and continued work on other games eventually making a deal with Williams
11     to continue to design games producing the titles: Stargate, Robotron: 2084 and Blaster.
12 
13     Information Link:  http://www.backglass.org/duncan/gimix/
14 
15     TODO: Hard disk support
16 
17     Usage:
18     System boots into GMXBUG-09
19     To boot Flex, insert the Flex system disk (3.3 or later, must support the DMA disk controller), type U and press enter.
20     To boot OS-9, select ROM version, insert the OS-9 system disk, type O, and press Enter.
21 */
22 
23 #include "emu.h"
24 #include "cpu/m6809/m6809.h"
25 #include "imagedev/floppy.h"
26 #include "machine/input_merger.h"
27 #include "machine/mm58167.h"
28 #include "machine/6840ptm.h"
29 #include "machine/6821pia.h"
30 #include "machine/6850acia.h"
31 #include "bus/rs232/rs232.h"
32 #include "machine/clock.h"
33 #include "machine/wd_fdc.h"
34 #include "machine/bankdev.h"
35 #include "machine/ram.h"
36 #include "formats/flex_dsk.h"
37 #include "formats/os9_dsk.h"
38 #include "softlist.h"
39 
40 #define DMA_DRQ         (m_dma_status & 0x80)
41 #define DMA_INTRQ       (m_dma_status & 0x40)
42 #define DMA_MOTOR_DELAY (m_dma_status & 0x20)
43 #define DMA_ENABLED     (m_dma_status & 0x10)
44 #define DMA_FAULT       (m_dma_status & 0x08)
45 #define DMA_DRIVE_SIZE  (m_dma_status & 0x04)
46 #define DMA_DIP_SENSE   (m_dma_status & 0x01)
47 
48 #define DMA_CONNECT_SEL (m_dma_drive_select & 0x40)
49 #define DMA_DENSITY     (m_dma_drive_select & 0x20)
50 #define DMA_WR_PROTECT  (m_dma_drive_select & 0x10)
51 #define DMA_SEL_DRV3    (m_dma_drive_select & 0x08)
52 #define DMA_SEL_DRV2    (m_dma_drive_select & 0x04)
53 #define DMA_SEL_DRV1    (m_dma_drive_select & 0x02)
54 #define DMA_SEL_DRV0    (m_dma_drive_select & 0x01)
55 
56 #define DMA_IRQ_ENABLE  (m_dma_ctrl & 0x80)
57 #define DMA_SIDE_SEL    (m_dma_ctrl & 0x40)
58 #define DMA_DIRECTION   (m_dma_ctrl & 0x20)
59 #define DMA_ENABLE      (m_dma_ctrl & 0x10)
60 #define DMA_BANK        (m_dma_ctrl & 0x0f)
61 
62 #define DMA_START_ADDR  (((m_dma_ctrl & 0x0f) << 16) | m_dma_start_addr)
63 
64 class gimix_state : public driver_device
65 {
66 public:
gimix_state(const machine_config & mconfig,device_type type,const char * tag)67 	gimix_state(const machine_config &mconfig, device_type type, const char *tag)
68 		: driver_device(mconfig, type, tag)
69 		, m_maincpu(*this, "maincpu")
70 		, m_irqs(*this, "irqs")
71 		, m_fdc(*this, "fdc")
72 		, m_floppy0(*this, "fdc:0")
73 		, m_floppy1(*this, "fdc:1")
74 		, m_floppy2(*this, "fdc:2")
75 		, m_floppy3(*this, "fdc:3")
76 		, m_ram(*this, RAM_TAG)
77 		, m_rom(*this, "roms")
78 		, m_acia1(*this, "acia1")
79 		, m_acia2(*this, "acia2")
80 		, m_acia3(*this, "acia3")
81 		, m_acia4(*this, "acia4")
82 		, m_bank(*this, "bank%u", 1U)
83 		, m_rombank1(*this, "rombank1")
84 		, m_rombank2(*this, "rombank2")
85 		, m_fixedrombank(*this, "fixedrombank")
86 		, m_dma_dip(*this, "dma_s2")
87 	{}
88 
89 	void gimix(machine_config &config);
90 
91 private:
92 	void system_w(offs_t offset, uint8_t data);
93 	DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
94 	DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
95 	uint8_t dma_r(offs_t offset);
96 	void dma_w(offs_t offset, uint8_t data);
97 	uint8_t fdc_r(offs_t offset);
98 	void fdc_w(offs_t offset, uint8_t data);
99 	uint8_t pia_pa_r();
100 	void pia_pa_w(uint8_t data);
101 	uint8_t pia_pb_r();
102 	void pia_pb_w(uint8_t data);
103 
104 	DECLARE_FLOPPY_FORMATS(floppy_formats);
105 
106 	void gimix_banked_mem(address_map &map);
107 	void gimix_mem(address_map &map);
108 
109 	// disassembly override
110 	offs_t os9_dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params);
111 	offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params);
112 
113 	bool m_fpla_sw_latch;
114 	uint8_t m_term_data;
115 	uint8_t m_dma_status;
116 	uint8_t m_dma_ctrl;
117 	uint8_t m_dma_drive_select;
118 	uint16_t m_dma_start_addr;
119 	uint32_t m_dma_current_addr;
120 	uint8_t m_task;
121 	uint8_t m_task_banks[16][16];
122 	uint8_t m_selected_drive;
123 	bool m_floppy0_ready;
124 	bool m_floppy1_ready;
125 	bool m_floppy2_ready;
126 	bool m_floppy3_ready;
127 
128 	uint8_t m_pia1_pa;
129 	uint8_t m_pia1_pb;
130 
131 	virtual void machine_reset() override;
132 	virtual void machine_start() override;
133 	virtual void driver_start() override;
134 
135 	void refresh_memory();
136 
137 	required_device<cpu_device> m_maincpu;
138 	required_device<input_merger_device> m_irqs;
139 	required_device<fd1797_device> m_fdc;
140 	required_device<floppy_connector> m_floppy0;
141 	required_device<floppy_connector> m_floppy1;
142 	required_device<floppy_connector> m_floppy2;
143 	required_device<floppy_connector> m_floppy3;
144 	required_device<ram_device> m_ram;
145 	required_memory_region m_rom;
146 	required_device<acia6850_device> m_acia1;
147 	required_device<acia6850_device> m_acia2;
148 	required_device<acia6850_device> m_acia3;
149 	required_device<acia6850_device> m_acia4;
150 
151 	required_device_array<address_map_bank_device, 16> m_bank;
152 	required_memory_bank m_rombank1;
153 	required_memory_bank m_rombank2;
154 	required_memory_bank m_fixedrombank;
155 
156 	required_ioport m_dma_dip;
157 };
158 
gimix_banked_mem(address_map & map)159 void gimix_state::gimix_banked_mem(address_map &map)
160 {
161 	map(0x00000, 0x0dfff).bankrw("lower_ram");
162 	map(0x0e000, 0x0e001).rw(m_acia1, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
163 	map(0x0e004, 0x0e005).rw(m_acia2, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
164 	//map(0x0e018, 0x0e01b).rw(FUNC(gimix_state::fdc_r), FUNC(gimix_state::fdc_w));  // FD1797 FDC (PIO)
165 	map(0x0e100, 0x0e1ff).ram();
166 	//map(0x0e200, 0x0e20f) // 9511A / 9512 Arithmetic Processor
167 	map(0x0e210, 0x0e21f).rw("timer", FUNC(ptm6840_device::read), FUNC(ptm6840_device::write));
168 	map(0x0e220, 0x0e23f).rw("rtc", FUNC(mm58167_device::read), FUNC(mm58167_device::write));
169 	map(0x0e240, 0x0e3af).ram();
170 	map(0x0e3b0, 0x0e3b3).rw(FUNC(gimix_state::dma_r), FUNC(gimix_state::dma_w));  // DMA controller (custom?)
171 	map(0x0e3b4, 0x0e3b7).rw(FUNC(gimix_state::fdc_r), FUNC(gimix_state::fdc_w));  // FD1797 FDC
172 	map(0x0e400, 0x0e7ff).ram();  // scratchpad RAM
173 	map(0x0e800, 0x0efff).ram();
174 	map(0x0f000, 0x0f7ff).bankr("rombank2");
175 	map(0x0f800, 0x0ffff).bankr("rombank1");
176 	//map(0x10000, 0x1ffff).ram();
177 }
178 
gimix_mem(address_map & map)179 void gimix_state::gimix_mem(address_map &map)
180 {
181 	for (int bank = 0; bank < 16; bank++)
182 	{
183 		map(bank << 12, (bank << 12) | 0x0fff).rw(m_bank[bank], FUNC(address_map_bank_device::read8), FUNC(address_map_bank_device::write8));
184 	}
185 	map(0xff00, 0xffff).bankr("fixedrombank").w(FUNC(gimix_state::system_w));
186 }
187 
188 static INPUT_PORTS_START( gimix )
189 	PORT_START("dma_s2")
190 	PORT_DIPNAME(0x00000100,0x00000000,"5.25\" / 8\" floppy drive 0") PORT_DIPLOCATION("S2:9")
191 	PORT_DIPSETTING(0x00000000,"5.25\"")
192 	PORT_DIPSETTING(0x00000100,"8\"")
193 
194 INPUT_PORTS_END
195 
refresh_memory()196 void gimix_state::refresh_memory()
197 {
198 	for (int bank = 0; bank < 16; bank++)
199 	{
200 		m_bank[bank]->set_bank(m_task_banks[m_task][bank]);
201 	}
202 }
203 
system_w(offs_t offset,uint8_t data)204 void gimix_state::system_w(offs_t offset, uint8_t data)
205 {
206 	if(offset == 0x7f)  // task register
207 	{
208 		if(data & 0x20)  // FPLA software latch
209 		{
210 			m_rombank1->set_entry(2);
211 			m_rombank2->set_entry(3);
212 			m_fixedrombank->set_entry(2);
213 			m_fpla_sw_latch = true;
214 			logerror("SYS: FPLA software latch set\n");
215 		}
216 		else
217 		{
218 			m_rombank1->set_entry(0);
219 			m_rombank2->set_entry(1);
220 			m_fixedrombank->set_entry(0);
221 			m_fpla_sw_latch = false;
222 			logerror("SYS: FPLA software latch reset\n");
223 		}
224 		m_task = data & 0x0f;
225 		refresh_memory();
226 		logerror("SYS: Task set to %02x\n",data & 0x0f);
227 	}
228 	if(offset >= 0xf0)  // Dynamic Address Translation RAM (write only)
229 	{
230 		m_bank[offset-0xf0]->set_bank(data & 0x0f);
231 		m_task_banks[m_task][offset-0xf0] = data & 0x0f;
232 		logerror("SYS: Bank %i set to physical bank %02x\n",offset-0xf0,data);
233 	}
234 }
235 
dma_r(offs_t offset)236 uint8_t gimix_state::dma_r(offs_t offset)
237 {
238 	switch(offset)
239 	{
240 	case 0:
241 		if(m_dma_dip->read() & 0x00000100)
242 			m_dma_status |= 0x01;   // 8"
243 		else
244 			m_dma_status &= ~0x01;  // 5.25"
245 		return m_dma_status;
246 	case 1:
247 		return m_dma_ctrl;
248 	case 2:
249 		return (m_dma_start_addr & 0xff00) >> 8;
250 	case 3:
251 		return (m_dma_start_addr & 0x00ff);
252 	default:
253 		logerror("DMA: Unknown or invalid DMA register %02x read\n",offset);
254 	}
255 	return 0xff;
256 }
257 
dma_w(offs_t offset,uint8_t data)258 void gimix_state::dma_w(offs_t offset, uint8_t data)
259 {
260 	switch(offset)
261 	{
262 	case 0:
263 		logerror("DMA: Drive select %02x\n",data);
264 		m_dma_drive_select = data;
265 		m_fdc->dden_w(DMA_DENSITY ? 1 : 0);
266 		if(data & 0x40)  // 8" / 5.25" connector select
267 		{
268 			// 8 inch
269 			m_dma_status |= 0x04;
270 			m_fdc->set_unscaled_clock(8_MHz_XTAL / 4); // (2MHz)
271 		}
272 		else
273 		{
274 			// 5.25 inch
275 			m_dma_status &= ~0x04;
276 			m_fdc->set_unscaled_clock(8_MHz_XTAL / 8); // (1MHz)
277 		}
278 
279 		if(data & 0x01)
280 		{
281 			m_selected_drive = 1;
282 			m_fdc->set_floppy(m_floppy0->get_device());
283 		}
284 		else if(data & 0x02)
285 		{
286 			m_selected_drive = 2;
287 			m_fdc->set_floppy(m_floppy1->get_device());
288 		}
289 		else if(data & 0x04)
290 		{
291 			m_selected_drive = 3;
292 			m_fdc->set_floppy(m_floppy2->get_device());
293 		}
294 		else if(data & 0x08)
295 		{
296 			m_selected_drive = 4;
297 			m_fdc->set_floppy(m_floppy3->get_device());
298 		}
299 		else
300 		{
301 			m_selected_drive = 0;
302 			m_fdc->set_floppy(nullptr);
303 		}
304 
305 		if(m_selected_drive != 1)
306 		{
307 			m_floppy0->get_device()->mon_w(1);
308 			m_floppy0_ready = false;
309 			logerror("FDC: Floppy drive 0 motor off\n");
310 		}
311 		if(m_selected_drive != 2)
312 		{
313 			m_floppy1->get_device()->mon_w(1);
314 			m_floppy1_ready = false;
315 			logerror("FDC: Floppy drive 1 motor off\n");
316 		}
317 		if(m_selected_drive != 3)
318 		{
319 			m_floppy2->get_device()->mon_w(1);
320 			m_floppy2_ready = false;
321 			logerror("FDC: Floppy drive 2 motor off\n");
322 		}
323 		if(m_selected_drive != 4)
324 		{
325 			m_floppy3->get_device()->mon_w(1);
326 			m_floppy3_ready = false;
327 			logerror("FDC: Floppy drive 3 motor off\n");
328 		}
329 		break;
330 	case 1:
331 		logerror("DMA: DMA control %02x\n",data);
332 		m_dma_ctrl = data;
333 		if(data & 0x10)
334 			m_dma_status |= 0x12;
335 		else
336 			m_dma_status &= ~0x12;
337 		if(data & 0x40)
338 		{
339 			if(m_selected_drive == 1)
340 				m_floppy0->get_device()->ss_w(1);
341 			if(m_selected_drive == 2)
342 				m_floppy1->get_device()->ss_w(1);
343 			if(m_selected_drive == 3)
344 				m_floppy2->get_device()->ss_w(1);
345 			if(m_selected_drive == 4)
346 				m_floppy3->get_device()->ss_w(1);
347 		}
348 		else
349 		{
350 			if(m_selected_drive == 1)
351 				m_floppy0->get_device()->ss_w(0);
352 			if(m_selected_drive == 2)
353 				m_floppy1->get_device()->ss_w(0);
354 			if(m_selected_drive == 3)
355 				m_floppy2->get_device()->ss_w(0);
356 			if(m_selected_drive == 4)
357 				m_floppy3->get_device()->ss_w(0);
358 		}
359 		if((data & 0x80) == 0)
360 			m_irqs->in_w<6>(0);
361 		break;
362 	case 2:
363 		logerror("DMA: DMA start address MSB %02x\n",data);
364 		m_dma_start_addr = (m_dma_start_addr & 0x00ff) | (data << 8);
365 		m_dma_current_addr = DMA_START_ADDR;
366 		break;
367 	case 3:
368 		logerror("DMA: DMA start address LSB %02x\n",data);
369 		m_dma_start_addr = (m_dma_start_addr & 0xff00) | data;
370 		m_dma_current_addr = DMA_START_ADDR;
371 		break;
372 	default:
373 		logerror("DMA: Unknown or invalid DMA register %02x write %02x\n",offset,data);
374 	}
375 }
376 
fdc_r(offs_t offset)377 uint8_t gimix_state::fdc_r(offs_t offset)
378 {
379 	// motors are switched on on FDC access
380 	if(m_selected_drive == 1 && m_floppy0_ready == false)
381 	{
382 		m_floppy0->get_device()->mon_w(0);
383 		m_floppy0_ready = true;
384 		logerror("FDC: Floppy drive 0 motor on\n");
385 	}
386 	if(m_selected_drive == 2 && m_floppy1_ready == false)
387 	{
388 		m_floppy1->get_device()->mon_w(0);
389 		m_floppy1_ready = true;
390 		logerror("FDC: Floppy drive 1 motor on\n");
391 	}
392 	if(m_selected_drive == 3 && m_floppy2_ready == false)
393 	{
394 		m_floppy2->get_device()->mon_w(0);
395 		m_floppy2_ready = true;
396 		logerror("FDC: Floppy drive 2 motor on\n");
397 	}
398 	if(m_selected_drive == 4 && m_floppy3_ready == false)
399 	{
400 		m_floppy3->get_device()->mon_w(0);
401 		m_floppy3_ready = true;
402 		logerror("FDC: Floppy drive 3 motor on\n");
403 	}
404 	return m_fdc->read(offset);
405 }
406 
fdc_w(offs_t offset,uint8_t data)407 void gimix_state::fdc_w(offs_t offset, uint8_t data)
408 {
409 	// motors are switched on on FDC access
410 	if(m_selected_drive == 1)
411 		m_floppy0->get_device()->mon_w(0);
412 	if(m_selected_drive == 2)
413 		m_floppy1->get_device()->mon_w(0);
414 	if(m_selected_drive == 3)
415 		m_floppy2->get_device()->mon_w(0);
416 	if(m_selected_drive == 4)
417 		m_floppy3->get_device()->mon_w(0);
418 	m_fdc->write(offset,data);
419 }
420 
pia_pa_r()421 uint8_t gimix_state::pia_pa_r()
422 {
423 	return m_pia1_pa;
424 }
425 
pia_pa_w(uint8_t data)426 void gimix_state::pia_pa_w(uint8_t data)
427 {
428 	m_pia1_pa = data;
429 	logerror("PIA: Port A write %02x\n",data);
430 }
431 
pia_pb_r()432 uint8_t gimix_state::pia_pb_r()
433 {
434 	return m_pia1_pb;
435 }
436 
pia_pb_w(uint8_t data)437 void gimix_state::pia_pb_w(uint8_t data)
438 {
439 	m_pia1_pb = data;
440 	logerror("PIA: Port B write %02x\n",data);
441 }
442 
443 
WRITE_LINE_MEMBER(gimix_state::fdc_irq_w)444 WRITE_LINE_MEMBER(gimix_state::fdc_irq_w)
445 {
446 	if(state)
447 		m_dma_status |= 0x40;
448 	else
449 		m_dma_status &= ~0x40;
450 
451 	if (DMA_IRQ_ENABLE)
452 		m_irqs->in_w<6>(state);
453 	else
454 		m_irqs->in_w<6>(0);
455 }
456 
WRITE_LINE_MEMBER(gimix_state::fdc_drq_w)457 WRITE_LINE_MEMBER(gimix_state::fdc_drq_w)
458 {
459 	if(state && DMA_ENABLED)
460 	{
461 		m_dma_status |= 0x80;
462 		// do a DMA transfer
463 		if(DMA_DIRECTION)
464 		{
465 			// write to disk
466 			m_fdc->data_w(m_ram->read(m_dma_current_addr));
467 //          logerror("DMA: read from RAM %05x\n",m_dma_current_addr);
468 		}
469 		else
470 		{
471 			// read from disk
472 			m_ram->write(m_dma_current_addr,m_fdc->data_r());
473 //          logerror("DMA: write to RAM %05x\n",m_dma_current_addr);
474 		}
475 		m_dma_current_addr++;
476 	}
477 	else
478 		m_dma_status &= ~0x80;
479 }
480 
machine_reset()481 void gimix_state::machine_reset()
482 {
483 	m_term_data = 0;
484 	m_rombank1->set_entry(0);  // RAM banks are undefined on startup
485 	m_rombank2->set_entry(1);
486 	m_fixedrombank->set_entry(0);
487 	m_fpla_sw_latch = false;
488 	m_dma_status = 0x00;
489 	m_dma_ctrl = 0x00;
490 	m_irqs->in_w<6>(0);
491 	m_task = 0x00;
492 	m_selected_drive = 0;
493 	m_floppy0_ready = false;
494 	m_floppy1_ready = false;
495 	m_floppy2_ready = false;
496 	m_floppy3_ready = false;
497 	membank("lower_ram")->set_base(m_ram->pointer());
498 	if(m_ram->size() > 65536)
499 		membank("upper_ram")->set_base(m_ram->pointer()+0x10000);
500 
501 	// initialise FDC clock based on DIP Switch S2-9 (5.25"/8" drive select)
502 	if(m_dma_dip->read() & 0x00000100)
503 		m_fdc->set_unscaled_clock(8_MHz_XTAL / 4); // 8 inch (2MHz)
504 	else
505 		m_fdc->set_unscaled_clock(8_MHz_XTAL / 8); // 5.25 inch (1MHz)
506 }
507 
machine_start()508 void gimix_state::machine_start()
509 {
510 	uint8_t* ROM = m_rom->base();
511 	m_rombank1->configure_entries(0,4,ROM,0x800);
512 	m_rombank2->configure_entries(0,4,ROM,0x800);
513 	m_fixedrombank->configure_entries(0,4,ROM+0x700,0x800);
514 	m_rombank1->set_entry(0);  // RAM banks are undefined on startup
515 	m_rombank2->set_entry(1);
516 	m_fixedrombank->set_entry(0);
517 	m_fpla_sw_latch = false;
518 	// install any extra RAM
519 	if(m_ram->size() > 65536)
520 	{
521 		for (int bank = 0; bank < 16; bank++)
522 		{
523 			m_bank[bank]->space(AS_PROGRAM).install_readwrite_bank(0x10000,m_ram->size()-1,"upper_ram");
524 		}
525 	}
526 	m_floppy0->get_device()->set_rpm(300);
527 	m_floppy1->get_device()->set_rpm(300);
528 }
529 
driver_start()530 void gimix_state::driver_start()
531 {
532 }
533 
FLOPPY_FORMATS_MEMBER(gimix_state::floppy_formats)534 FLOPPY_FORMATS_MEMBER( gimix_state::floppy_formats )
535 	FLOPPY_MFI_FORMAT,
536 	FLOPPY_FLEX_FORMAT,
537 	FLOPPY_OS9_FORMAT
538 FLOPPY_FORMATS_END
539 
540 static void gimix_floppies(device_slot_interface &device)
541 {
542 	device.option_add("525hd", FLOPPY_525_HD);
543 	device.option_add("8dd", FLOPPY_8_DSDD);
544 }
545 
546 /***************************************************************************
547   DISASSEMBLY OVERRIDE (OS9 syscalls)
548  ***************************************************************************/
549 
550 static const char *const os9syscalls[] =
551 {
552 	"F$Link",          // Link to Module
553 	"F$Load",          // Load Module from File
554 	"F$UnLink",        // Unlink Module
555 	"F$Fork",          // Start New Process
556 	"F$Wait",          // Wait for Child Process to Die
557 	"F$Chain",         // Chain Process to New Module
558 	"F$Exit",          // Terminate Process
559 	"F$Mem",           // Set Memory Size
560 	"F$Send",          // Send Signal to Process
561 	"F$Icpt",          // Set Signal Intercept
562 	"F$Sleep",         // Suspend Process
563 	"F$SSpd",          // Suspend Process
564 	"F$ID",            // Return Process ID
565 	"F$SPrior",        // Set Process Priority
566 	"F$SSWI",          // Set Software Interrupt
567 	"F$PErr",          // Print Error
568 	"F$PrsNam",        // Parse Pathlist Name
569 	"F$CmpNam",        // Compare Two Names
570 	"F$SchBit",        // Search Bit Map
571 	"F$AllBit",        // Allocate in Bit Map
572 	"F$DelBit",        // Deallocate in Bit Map
573 	"F$Time",          // Get Current Time
574 	"F$STime",         // Set Current Time
575 	"F$CRC",           // Generate CRC
576 	"F$GPrDsc",        // get Process Descriptor copy
577 	"F$GBlkMp",        // get System Block Map copy
578 	"F$GModDr",        // get Module Directory copy
579 	"F$CpyMem",        // Copy External Memory
580 	"F$SUser",         // Set User ID number
581 	"F$UnLoad",        // Unlink Module by name
582 	"F$Alarm",         // Color Computer Alarm Call (system wide)
583 	nullptr,
584 	nullptr,
585 	nullptr,
586 	nullptr,
587 	nullptr,
588 	nullptr,
589 	"F$TPS",           // Return System's Ticks Per Second
590 	nullptr,
591 	"F$VIRQ",          // Install/Delete Virtual IRQ
592 	"F$SRqMem",        // System Memory Request
593 	"F$SRtMem",        // System Memory Return
594 	"F$IRQ",           // Enter IRQ Polling Table
595 	"F$IOQu",          // Enter I/O Queue
596 	"F$AProc",         // Enter Active Process Queue
597 	"F$NProc",         // Start Next Process
598 	"F$VModul",        // Validate Module
599 	"F$Find64",        // Find Process/Path Descriptor
600 	"F$All64",         // Allocate Process/Path Descriptor
601 	"F$Ret64",         // Return Process/Path Descriptor
602 	"F$SSvc",          // Service Request Table Initialization
603 	"F$IODel",         // Delete I/O Module
604 	"F$SLink",         // System Link
605 	"F$Boot",          // Bootstrap System
606 	"F$BtMem",         // Bootstrap Memory Request
607 	"F$GProcP",        // Get Process ptr
608 	"F$Move",          // Move Data (low bound first)
609 	"F$AllRAM",        // Allocate RAM blocks
610 	"F$AllImg",        // Allocate Image RAM blocks
611 	"F$DelImg",        // Deallocate Image RAM blocks
612 	"F$SetImg",        // Set Process DAT Image
613 	"F$FreeLB",        // Get Free Low Block
614 	"F$FreeHB",        // Get Free High Block
615 	"F$AllTsk",        // Allocate Process Task number
616 	"F$DelTsk",        // Deallocate Process Task number
617 	"F$SetTsk",        // Set Process Task DAT registers
618 	"F$ResTsk",        // Reserve Task number
619 	"F$RelTsk",        // Release Task number
620 	"F$DATLog",        // Convert DAT Block/Offset to Logical
621 	"F$DATTmp",        // Make temporary DAT image (Obsolete)
622 	"F$LDAXY",         // Load A [X,[Y]]
623 	"F$LDAXYP",        // Load A [X+,[Y]]
624 	"F$LDDDXY",        // Load D [D+X,[Y]]
625 	"F$LDABX",         // Load A from 0,X in task B
626 	"F$STABX",         // Store A at 0,X in task B
627 	"F$AllPrc",        // Allocate Process Descriptor
628 	"F$DelPrc",        // Deallocate Process Descriptor
629 	"F$ELink",         // Link using Module Directory Entry
630 	"F$FModul",        // Find Module Directory Entry
631 	"F$MapBlk",        // Map Specific Block
632 	"F$ClrBlk",        // Clear Specific Block
633 	"F$DelRAM",        // Deallocate RAM blocks
634 	"F$GCMDir",        // Pack module directory
635 	"F$AlHRam",        // Allocate HIGH RAM Blocks
636 	nullptr,
637 	nullptr,
638 	nullptr,
639 	nullptr,
640 	nullptr,
641 	nullptr,
642 	nullptr,
643 	nullptr,
644 	nullptr,
645 	nullptr,
646 	nullptr,
647 	nullptr,
648 	nullptr,
649 	nullptr,
650 	nullptr,
651 	nullptr,
652 	nullptr,
653 	nullptr,
654 	nullptr,
655 	nullptr,
656 	nullptr,
657 	nullptr,
658 	nullptr,
659 	nullptr,
660 	nullptr,
661 	nullptr,
662 	nullptr,
663 	nullptr,
664 	"F$RegDmp",        // Ron Lammardo's debugging register dump call
665 	"F$NVRAM",         // Non Volatile RAM (RTC battery backed static) read/write
666 	nullptr,
667 	nullptr,
668 	nullptr,
669 	nullptr,
670 	nullptr,
671 	nullptr,
672 	nullptr,
673 	nullptr,
674 	nullptr,
675 	nullptr,
676 	nullptr,
677 	nullptr,
678 	nullptr,
679 	nullptr,
680 	"I$Attach",        // Attach I/O Device
681 	"I$Detach",        // Detach I/O Device
682 	"I$Dup",           // Duplicate Path
683 	"I$Create",        // Create New File
684 	"I$Open",          // Open Existing File
685 	"I$MakDir",        // Make Directory File
686 	"I$ChgDir",        // Change Default Directory
687 	"I$Delete",        // Delete File
688 	"I$Seek",          // Change Current Position
689 	"I$Read",          // Read Data
690 	"I$Write",         // Write Data
691 	"I$ReadLn",        // Read Line of ASCII Data
692 	"I$WritLn",        // Write Line of ASCII Data
693 	"I$GetStt",        // Get Path Status
694 	"I$SetStt",        // Set Path Status
695 	"I$Close",         // Close Path
696 	"I$DeletX"         // Delete from current exec dir
697 };
698 
699 
700 //-------------------------------------------------
701 //  os9_dasm_override
702 //-------------------------------------------------
703 
os9_dasm_override(std::ostream & stream,offs_t pc,const util::disasm_interface::data_buffer & opcodes,const util::disasm_interface::data_buffer & params)704 offs_t gimix_state::os9_dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params)
705 {
706 	unsigned call;
707 	offs_t result = 0;
708 
709 	// Microware OS-9 (on the Gimix) and a number of other 6x09 based
710 	// systems used the SWI2 instruction for syscalls.  This checks for a
711 	// SWI2 and looks up the syscall as appropriate.
712 	//
713 	// But only apply this override if the OS9 ROMs are latched on.
714 	if (!m_fpla_sw_latch)
715 		return 0;
716 
717 	if ((opcodes.r8(pc) == 0x10) && (opcodes.r8(pc+1) == 0x3F))
718 	{
719 		call = opcodes.r8(pc+2);
720 		if ((call < ARRAY_LENGTH(os9syscalls)) && (os9syscalls[call] != nullptr))
721 		{
722 			util::stream_format(stream, "OS9   %s", os9syscalls[call]);
723 			result = 3;
724 		}
725 	}
726 	return result;
727 }
728 
729 
dasm_override(std::ostream & stream,offs_t pc,const util::disasm_interface::data_buffer & opcodes,const util::disasm_interface::data_buffer & params)730 offs_t gimix_state::dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer &params)
731 {
732 	return os9_dasm_override(stream, pc, opcodes, params);
733 }
734 
gimix(machine_config & config)735 void gimix_state::gimix(machine_config &config)
736 {
737 	// basic machine hardware
738 	MC6809(config, m_maincpu, 8_MHz_XTAL);
739 	m_maincpu->set_addrmap(AS_PROGRAM, &gimix_state::gimix_mem);
740 	m_maincpu->set_dasm_override(FUNC(gimix_state::dasm_override));
741 
742 	INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
743 
744 	/* rtc */
745 	mm58167_device &rtc(MM58167(config, "rtc", 32.768_kHz_XTAL));
746 	rtc.irq().set(m_irqs, FUNC(input_merger_device::in_w<0>));
747 
748 	/* timer */
749 	ptm6840_device &ptm(PTM6840(config, "timer", 2'000'000));  // clock is a guess
750 	// PCB pictures show both the RTC and timer set to generate IRQs (are jumper configurable)
751 	ptm.irq_callback().set(m_irqs, FUNC(input_merger_device::in_w<1>));
752 
753 	/* floppy disks */
754 	FD1797(config, m_fdc, 8_MHz_XTAL / 4);
755 	m_fdc->intrq_wr_callback().set(FUNC(gimix_state::fdc_irq_w));
756 	m_fdc->drq_wr_callback().set(FUNC(gimix_state::fdc_drq_w));
757 	m_fdc->set_force_ready(true);
758 	FLOPPY_CONNECTOR(config, "fdc:0", gimix_floppies, "525hd", gimix_state::floppy_formats).enable_sound(true);
759 	FLOPPY_CONNECTOR(config, "fdc:1", gimix_floppies, "525hd", gimix_state::floppy_formats).enable_sound(true);
760 	FLOPPY_CONNECTOR(config, "fdc:2", gimix_floppies, "525hd", gimix_state::floppy_formats).enable_sound(true);
761 	FLOPPY_CONNECTOR(config, "fdc:3", gimix_floppies, "525hd", gimix_state::floppy_formats).enable_sound(true);
762 
763 	/* parallel ports */
764 	pia6821_device &pia1(PIA6821(config, "pia1", 2'000'000));
765 	pia1.writepa_handler().set(FUNC(gimix_state::pia_pa_w));
766 	pia1.writepb_handler().set(FUNC(gimix_state::pia_pb_w));
767 	pia1.readpa_handler().set(FUNC(gimix_state::pia_pa_r));
768 	pia1.readpb_handler().set(FUNC(gimix_state::pia_pb_r));
769 
770 	PIA6821(config, "pia2", 2'000'000);
771 
772 	/* serial ports */
773 	ACIA6850(config, m_acia1, 2'000'000);
774 	m_acia1->txd_handler().set("serial1", FUNC(rs232_port_device::write_txd));
775 	m_acia1->rts_handler().set("serial1", FUNC(rs232_port_device::write_rts));
776 	m_acia1->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<2>));
777 
778 	ACIA6850(config, m_acia2, 2'000'000);
779 	m_acia2->txd_handler().set("serial2", FUNC(rs232_port_device::write_txd));
780 	m_acia2->rts_handler().set("serial2", FUNC(rs232_port_device::write_rts));
781 	m_acia2->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<3>));
782 
783 	ACIA6850(config, m_acia3, 2'000'000);
784 	m_acia3->txd_handler().set("serial3", FUNC(rs232_port_device::write_txd));
785 	m_acia3->rts_handler().set("serial3", FUNC(rs232_port_device::write_rts));
786 	m_acia3->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<4>));
787 
788 	ACIA6850(config, m_acia4, 2'000'000);
789 	m_acia4->txd_handler().set("serial4", FUNC(rs232_port_device::write_txd));
790 	m_acia4->rts_handler().set("serial4", FUNC(rs232_port_device::write_rts));
791 	m_acia4->irq_handler().set(m_irqs, FUNC(input_merger_device::in_w<5>));
792 
793 	rs232_port_device &serial1(RS232_PORT(config, "serial1", default_rs232_devices, nullptr));
794 	serial1.rxd_handler().set(m_acia1, FUNC(acia6850_device::write_rxd));
795 	serial1.cts_handler().set(m_acia1, FUNC(acia6850_device::write_cts));
796 
797 	rs232_port_device &serial2(RS232_PORT(config, "serial2", default_rs232_devices, "terminal"));
798 	serial2.rxd_handler().set(m_acia2, FUNC(acia6850_device::write_rxd));
799 	serial2.cts_handler().set(m_acia2, FUNC(acia6850_device::write_cts));
800 
801 	rs232_port_device &serial3(RS232_PORT(config, "serial3", default_rs232_devices, nullptr));
802 	serial3.rxd_handler().set(m_acia3, FUNC(acia6850_device::write_rxd));
803 	serial3.cts_handler().set(m_acia3, FUNC(acia6850_device::write_cts));
804 
805 	rs232_port_device &serial4(RS232_PORT(config, "serial4", default_rs232_devices, nullptr));
806 	serial4.rxd_handler().set(m_acia4, FUNC(acia6850_device::write_rxd));
807 	serial4.cts_handler().set(m_acia4, FUNC(acia6850_device::write_cts));
808 
809 	clock_device &acia_clock(CLOCK(config, "acia_clock", 9600 * 16));
810 	acia_clock.signal_handler().set(m_acia1, FUNC(acia6850_device::write_txc));
811 	acia_clock.signal_handler().append(m_acia1, FUNC(acia6850_device::write_rxc));
812 	acia_clock.signal_handler().append(m_acia2, FUNC(acia6850_device::write_txc));
813 	acia_clock.signal_handler().append(m_acia2, FUNC(acia6850_device::write_rxc));
814 
815 	/* banking */
816 	for (int bank = 0; bank < 16; bank++)
817 	{
818 		ADDRESS_MAP_BANK(config, m_bank[bank]).set_map(&gimix_state::gimix_banked_mem).set_options(ENDIANNESS_LITTLE, 8, 32, 0x1000);
819 	}
820 
821 	/* internal ram */
822 	RAM(config, RAM_TAG).set_default_size("128K").set_extra_options("56K,256K,512K");
823 
824 	SOFTWARE_LIST(config, "flop_list").set_original("gimix");
825 }
826 
827 ROM_START( gimix )
828 	ROM_REGION( 0x10000, "roms", 0)
829 /* CPU board U4: gimixf8.bin  - checksum 68DB - 2716 - GMXBUG09 V2.1 | (c)1981 GIMIX | $F800 I2716 */
830 	ROM_LOAD( "gimixf8.u4",  0x000000, 0x000800, CRC(7d60f838) SHA1(eb7546e8bbf50d33e181f3e86c3e4c5c9032cab2) )
831 /* CPU board U5: gimixv14.bin - checksum 97E2 - 2716 - GIMIX 6809 | AUTOBOOT | V1.4 I2716 */
832 	ROM_LOAD( "gimixv14.u5", 0x000800, 0x000800, CRC(f795b8b9) SHA1(eda2de51cc298d94b36605437d900ce971b3b276) )
833 
834 	ROM_SYSTEM_BIOS(0, "os9l1v11", "OS9 Level 1 version 1.1")
835 /* CPU board U6: os9p1-l1v11.bin - checksum 2C84 - 2716 - OS-9tmL1 V1 | GIMIX P1 " (c)1982 MSC
836    CPU board U7: os9p2-l1v11.bin - checksum 7694 - 2716 - OS-9tmL1 V1 | GIMIX P2-68 | (c)1982 MSC */
837 	ROMX_LOAD( "os9p1-l1v11.u6", 0x001000, 0x000800, CRC(0d6527a0) SHA1(1435a22581c6e9e0ae338071a72eed646f429530), ROM_BIOS(0))
838 	ROMX_LOAD( "os9p2-l1v11.u7", 0x001800, 0x000800, CRC(b3c65feb) SHA1(19d1ea1e84473b25c95cbb8449e6b9828567e998), ROM_BIOS(0))
839 
840 	ROM_SYSTEM_BIOS(1, "os9l1v12", "OS9 Level 1 version 1.2")
841 	ROMX_LOAD( "os9p1-l1v12.u6", 0x001000, 0x000800, CRC(4de6e313) SHA1(b32cbc07418a147fd33a4404a5c2f68c25616c0d), ROM_BIOS(1))
842 	ROMX_LOAD( "os9p2-l1v12.u7", 0x001800, 0x000800, CRC(22f5f128) SHA1(8abf5cd2a52c0b8286f717f9ddf7feca61d1f46d), ROM_BIOS(1))
843 
844 /* Hard drive controller board 2 (XEBEC board) 11H: gimixhd.bin - checksum 2436 - 2732 - 104521D */
845 	ROM_REGION( 0x10000, "xebec", 0)
846 	ROM_LOAD( "gimixhd.h11",  0x000000, 0x001000, CRC(35c12201) SHA1(51ac9052f9757d79c7f5bd3aa5d8421e98cfcc37) )
847 ROM_END
848 
849 COMP( 1980, gimix, 0, 0, gimix, gimix, gimix_state, empty_init, "Gimix", "Gimix 6809 System", MACHINE_NO_SOUND_HW )
850