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 ¶ms);
111 offs_t dasm_override(std::ostream &stream, offs_t pc, const util::disasm_interface::data_buffer &opcodes, const util::disasm_interface::data_buffer ¶ms);
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 ¶ms)
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 ¶ms)
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