1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /*
4 
5     Amstrad PC1512
6 
7     http://www.seasip.info/AmstradXT
8     http://stason.org/TULARC/pc/hard-drives-hdd/tandon/TM262-21MB-5-25-HH-MFM-ST506.html
9 
10 */
11 
12 /*
13 
14     TODO:
15 
16     - adjust mouse speed
17     - pc1512 V3 VDU check fails
18     - Amstrad SM2400 internal modem
19     - Amstrad RP4 diagnostic ISA card (PC1512)
20     - Amstrad RP5-2 diagnostic ISA card (PC1640)
21     - 40291/8908 B ROM on PC1640 HD30 controller card
22 
23 */
24 
25 /*
26 HARD DISC INSTALLATION INSTRUCTIONS
27 
28 Applies to both ten and twenty megabyte versions.
29 
30 1. Turn on machine
31 2. Insert disc 1 (the red disc) and press a key.
32 3. Type fdisk (RETURN)
33 4. At each prompt press the RETURN key (another three times).
34 5. The A> will now appear so now type format c:/s (RETURN).
35 6. Now push the Y key (RETURN).
36 7. The hard disc will now begin to format, if you have a 10Mb machine then it will count up to 305
37    cylinders. If you have a 20 Mb machine then 610 cylinders will be counted.
38 8. Once this is done, take out disc 1 and insert disc 5 (the maroon disc).
39 9. Now type config(RETURN). This procedure will copy all five discs (order 5,1,2,3,4) onto the hard disc.
40    Once finished the screen will show some information about the size of the disc and the number of files and
41    directories present.
42 10. To now use the hard disc remove the floppy disc from the drive and store in a safe place with the other
43     four discs then restart the computer by pushing Alt Ctrl and Del.
44 11. After a short while the AMSTRAD PC info will come up and tell you when the machine was last used
45     and then after a little longer the screen will clear and will display this message,
46 
47 F1=DOSPLUS.SYS
48 F2=DOS.SYS
49 
50 Select operating system:
51 
52 If you choose F1 then DOS Plus and GEM will be booted, or if you press F2 then MS-DOS will be booted.
53 
54 PC1512-HD10: ?
55 PC1512-HD20: Tandon TM-262 [-chs 615,4,17 -ss 512]
56 */
57 
58 /*
59 HARD DISC INSTALLATION ON PC1640
60 
61 PC1640 hard disc comes ready installed with the necessary software. That is discs 1 to 4 that are
62 supplied ready with the machine.
63 
64 Howevere in the case of a disc failure it may be necessary to reinstall the supplied software.
65 
66 This is done in the following way:
67 1. Put disc one into drive A: and boot up the system
68 2. Put disc four into drive A: and type CD\SUPPLEME and press return.
69 3. Type HDFORMAT and press return.
70 4. Answer YES to the screen prompt.
71 5. When HDFORMAT is completed remove disc four and replace with disc one.
72 6. Type CD\ and press return.
73 7. Type FDISK and press return.
74 8. Press return key every time you are asked a question.
75 9. With disc one still in drive A: type FORMAT C:/S and press return.
76 10. When formatting is finished replace disc one with disc four.
77 11. Type CD\SUPPLEME and press return.
78 12. Type CONFIG and press return.
79 
80 After typing CONFIG the machine will proceed to copy the four system discs to the hard disc.
81 After copying each disc you will be prompted to insert the next disc.
82 You do not noeed to know in which order to insert the discs because the machine will tell you which disc is
83 needed next.
84 
85 The system is now installed and should be tested by rebooting the machine.
86 
87 It should be noted that if the hard disc is ok but the software has been corrupted or deleted you can
88 reinstall the software without reformatting.
89 This is done by following steps 11 and 12.
90 
91 PC1640-HD20: Amstrad 40095 (Alps DRMD20A12A), Tandon TM-262 [-chs 615,4,17 -ss 512]
92 PC1640-HD30: Western Digital 95038 [-chs 615,6,17 -ss 512]
93 */
94 
95 #include "emu.h"
96 #include "includes/pc1512.h"
97 #include "bus/rs232/rs232.h"
98 #include "bus/isa/ega.h"
99 #include "screen.h"
100 #include "softlist.h"
101 #include "speaker.h"
102 
103 
104 //**************************************************************************
105 //  SYSTEM STATUS REGISTER
106 //**************************************************************************
107 
108 //-------------------------------------------------
109 //  system_r -
110 //-------------------------------------------------
111 
system_r(offs_t offset)112 uint8_t pc1512_base_state::system_r(offs_t offset)
113 {
114 	uint8_t data = 0;
115 
116 	switch (offset)
117 	{
118 	case 0:
119 		if (BIT(m_port61, 7))
120 		{
121 			/*
122 
123 			    bit     description
124 
125 			    0       1
126 			    1       8087 NDP installed
127 			    2       1
128 			    3       1
129 			    4       DDM0
130 			    5       DDM1
131 			    6       second floppy disk drive installed
132 			    7       0
133 
134 			*/
135 
136 			data = m_status1;
137 		}
138 		else
139 		{
140 			data = m_kbd;
141 			m_kb_bits = 0;
142 			m_kb->data_w(1);
143 			m_pic->ir1_w(CLEAR_LINE);
144 		}
145 		break;
146 
147 	case 1:
148 		data = m_port61;
149 		break;
150 
151 	case 2:
152 		/*
153 
154 		    bit     description
155 
156 		    0       RAM0 / RAM4
157 		    1       RAM1
158 		    2       RAM2
159 		    3       RAM3
160 		    4       undefined
161 		    5       8253 PIT OUT2 output
162 		    6       external parity error (I/OCHCK from expansion bus)
163 		    7       on-board system RAM parity error
164 
165 		*/
166 
167 		if (BIT(m_port61, 2))
168 			data = m_status2 & 0x0f;
169 		else
170 			data = m_status2 >> 4;
171 
172 		data |= m_pit2 << 5;
173 		break;
174 	}
175 
176 	return data;
177 }
178 
179 
180 //-------------------------------------------------
181 //  system_w -
182 //-------------------------------------------------
183 
system_w(offs_t offset,uint8_t data)184 void pc1512_base_state::system_w(offs_t offset, uint8_t data)
185 {
186 	switch (offset)
187 	{
188 	case 1:
189 		/*
190 
191 		    bit     description
192 
193 		    0       8253 GATE 2 (speaker modulate)
194 		    1       speaker drive
195 		    2       enable port C LSB / disable MSB
196 		    3       undefined
197 		    4       disable parity checking of on-board RAM
198 		    5       prevent external parity errors from causing NMI
199 		    6       enable incoming Keyboard Clock
200 		    7       enable Status-1/Disable Keyboard Code on Port A
201 
202 		*/
203 
204 		m_port61 = data;
205 
206 		m_pit->write_gate2(BIT(data, 0));
207 
208 		m_speaker_drive = BIT(data, 1);
209 		update_speaker();
210 
211 		m_kb->clock_w(BIT(data, 6));
212 
213 		if (BIT(data, 7))
214 		{
215 			m_kb_bits = 0;
216 			m_kb->data_w(1);
217 			m_pic->ir1_w(CLEAR_LINE);
218 		}
219 		break;
220 
221 	case 4:
222 		/*
223 
224 		    bit     description
225 
226 		    0
227 		    1       PA1 - 8087 NDP installed
228 		    2
229 		    3
230 		    4       PA4 - DDM0
231 		    5       PA5 - DDM1
232 		    6       PA6 - Second Floppy disk drive installed
233 		    7
234 
235 		*/
236 
237 		if (BIT(data, 7))
238 			m_status1 = data ^ 0x8d;
239 		else
240 			m_status1 = data;
241 		break;
242 
243 	case 5:
244 		/*
245 
246 		    bit     description
247 
248 		    0       PC0 (LSB) - RAM0
249 		    1       PC1 (LSB) - RAM1
250 		    2       PC2 (LSB) - RAM2
251 		    3       PC3 (LSB) - RAM3
252 		    4       PC0 (MSB) - RAM4
253 		    5       PC1 (MSB) - Undefined
254 		    6       PC2 (MSB) - Undefined
255 		    7       PC3 (MSB) - Undefined
256 
257 		*/
258 
259 		m_status2 = data;
260 		break;
261 
262 	case 6:
263 		machine_reset();
264 		break;
265 	}
266 }
267 
268 
269 
270 //**************************************************************************
271 //  MOUSE
272 //**************************************************************************
273 
274 //-------------------------------------------------
275 //  mouse_r -
276 //-------------------------------------------------
277 
mouse_r(offs_t offset)278 uint8_t pc1512_base_state::mouse_r(offs_t offset)
279 {
280 	uint8_t data = 0;
281 
282 	switch (offset)
283 	{
284 	case 0:
285 		data = m_mouse_x;
286 		break;
287 
288 	case 2:
289 		data = m_mouse_y;
290 		break;
291 	}
292 
293 	return data;
294 }
295 
296 
297 //-------------------------------------------------
298 //  mouse_w -
299 //-------------------------------------------------
300 
mouse_w(offs_t offset,uint8_t data)301 void pc1512_base_state::mouse_w(offs_t offset, uint8_t data)
302 {
303 	switch (offset)
304 	{
305 	case 0:
306 		m_mouse_x = 0;
307 		break;
308 
309 	case 2:
310 		m_mouse_y = 0;
311 		break;
312 	}
313 }
314 
315 
316 
317 //**************************************************************************
318 //  DIRECT MEMORY ACCESS
319 //**************************************************************************
320 
321 //-------------------------------------------------
322 //  dma_page_w -
323 //-------------------------------------------------
324 
dma_page_w(offs_t offset,uint8_t data)325 void pc1512_base_state::dma_page_w(offs_t offset, uint8_t data)
326 {
327 	/*
328 
329 	    bit     description
330 
331 	    0       Address bit A16
332 	    1       Address bit A17
333 	    2       Address bit A18
334 	    3       Address bit A19
335 	    4
336 	    5
337 	    6
338 	    7
339 
340 	*/
341 
342 	switch (offset)
343 	{
344 	case 1:
345 		m_dma_page[2] = data & 0x0f;
346 		break;
347 
348 	case 2:
349 		m_dma_page[3] = data & 0x0f;
350 		break;
351 
352 	case 3:
353 		m_dma_page[0] = m_dma_page[1] = data & 0x0f;
354 		break;
355 	}
356 }
357 
358 
359 
360 //**************************************************************************
361 //  INTERRUPTS
362 //**************************************************************************
363 
364 //-------------------------------------------------
365 //  nmi_mask_w -
366 //-------------------------------------------------
367 
nmi_mask_w(uint8_t data)368 void pc1512_base_state::nmi_mask_w(uint8_t data)
369 {
370 	m_nmi_enable = BIT(data, 7);
371 }
372 
373 
374 
375 //**************************************************************************
376 //  PRINTER
377 //**************************************************************************
378 
379 //-------------------------------------------------
380 //  printer_r -
381 //-------------------------------------------------
382 
printer_r(offs_t offset)383 uint8_t pc1512_base_state::printer_r(offs_t offset)
384 {
385 	uint8_t data = 0;
386 
387 	switch (offset)
388 	{
389 	case 0:
390 		data = m_printer_data;
391 		break;
392 
393 	case 1:
394 		/*
395 
396 		    bit     description
397 
398 		    0       LK1 fitted
399 		    1       LK2 fitted
400 		    2       LK3 fitted
401 		    3       printer error
402 		    4       printer selected
403 		    5       paper out
404 		    6       printer acknowledge
405 		    7       printer busy
406 
407 		*/
408 
409 		data |= m_lk->read() & 0x07;
410 
411 		data |= m_centronics_fault << 3;
412 		data |= m_centronics_select << 4;
413 		data |= m_centronics_perror << 5;
414 		data |= m_centronics_ack << 6;
415 		data |= m_centronics_busy << 7;
416 		break;
417 
418 	case 2:
419 		/*
420 
421 		    bit     description
422 
423 		    0       Data Strobe
424 		    1       Select Auto Feed
425 		    2       Reset Printer
426 		    3       Select Printer
427 		    4       Enable Int on ACK
428 		    5       1
429 		    6
430 		    7
431 
432 		*/
433 
434 		data = m_printer_control | 0x20;
435 		break;
436 	}
437 
438 	return data;
439 }
440 
441 
442 //-------------------------------------------------
443 //  printer_r -
444 //-------------------------------------------------
445 
printer_r(offs_t offset)446 uint8_t pc1640_state::printer_r(offs_t offset)
447 {
448 	uint8_t data = 0;
449 
450 	switch (offset)
451 	{
452 	case 2:
453 		/*
454 
455 		    bit     description
456 
457 		    0       Data Strobe
458 		    1       Select Auto Feed
459 		    2       Reset Printer
460 		    3       Select Printer
461 		    4       Enable Int on ACK
462 		    5       OPT
463 		    6       SW6
464 		    7       SW7
465 
466 		*/
467 
468 		/*
469 		Bit D5 is the option (OPT) bit and can return one of three different pieces of
470 		information. Although not documented as such on the PC1512, Bit D5 was always a
471 		"1", however on the PC1640 it will always be a zero if immediately prior to the
472 		read of channel 037Ah the software performs an I/O read of an I/O channel
473 		implemented on the PC1512 main board, having address line A7 high (for example,
474 		the CGA channels). This is a simple test for software to detect whether it is
475 		running on a PC1512 or a PC1640. A PC1512 will give a 1, whereas a PC1640 will
476 		give a 0.
477 
478 		In addition to being a test of machine type the OPT bit, D5, can also reflect
479 		the state of either SW9 or SW10. The OPT bit will reflect the state of switch
480 		SW9 by an I/O read operation to an I/O channel not implemented on the main
481 		board and having address lines A14 and A7 both low (for example channel 0278h)
482 		immediately prior to the reading of channel 037Ah. The OPT bit is set to the
483 		state of switch SW10 by an I/O read operation to an I/O channel not implemented
484 		on the main board having address lines A14 high and A7 low (for example channel
485 		4278h). Software testing OPT bit should disable interrupts before the initial
486 		(dummy) channel read and the I/O read of channel 037A in order to avoid
487 		additional (interrupt based) I/O operations between the setting and the testing
488 		of the information read back in the OPT bit. For switches SW9 and SW10, a logic
489 		"1" is returned when the switch is on the "on" position and a logic "0" if the
490 		switch is in the "off" position.
491 		*/
492 		data = m_printer_control;
493 		data |= m_opt << 5;
494 		data |= (m_sw->read() & 0x60) << 1;
495 		break;
496 
497 	default:
498 		data = pc1512_base_state::printer_r(offset);
499 		break;
500 	}
501 
502 	return data;
503 }
504 
505 
506 //-------------------------------------------------
507 //  printer_w -
508 //-------------------------------------------------
509 
printer_w(offs_t offset,uint8_t data)510 void pc1512_base_state::printer_w(offs_t offset, uint8_t data)
511 {
512 	switch (offset)
513 	{
514 	case 0:
515 		m_printer_data = data;
516 		m_cent_data_out->write(data);
517 		break;
518 
519 	case 2:
520 		/*
521 
522 		    bit     description
523 
524 		    0       Data Strobe
525 		    1       Select Auto Feed
526 		    2       Reset Printer
527 		    3       Select Printer
528 		    4       Enable Int on ACK
529 		    5
530 		    6
531 		    7
532 
533 		*/
534 
535 		m_printer_control = data & 0x1f;
536 
537 		m_centronics->write_strobe(BIT(data, 0));
538 		m_centronics->write_autofd(BIT(data, 1));
539 		m_centronics->write_init(BIT(data, 2));
540 
541 		m_ack_int_enable = BIT(data, 4);
542 		update_ack();
543 		break;
544 	}
545 }
546 
547 
548 //**************************************************************************
549 //  PC1640 I/O ACCESS
550 //**************************************************************************
551 
552 //-------------------------------------------------
553 //  io_r -
554 //-------------------------------------------------
555 
io_r(offs_t offset)556 uint8_t pc1640_state::io_r(offs_t offset)
557 {
558 	uint8_t data = 0;
559 	offs_t addr = offset & 0x3ff;
560 	bool decoded = false;
561 
562 	if      (                 addr <= 0x00f) { data = m_dmac->read(offset & 0x0f); decoded = true; }
563 	else if (addr >= 0x020 && addr <= 0x021) { data = m_pic->read(offset & 0x01); decoded = true; }
564 	else if (addr >= 0x040 && addr <= 0x043) { data = m_pit->read(offset & 0x03); decoded = true; }
565 	else if (addr >= 0x060 && addr <= 0x06f) { data = system_r(offset & 0x0f); decoded = true; }
566 	else if (addr >= 0x070 && addr <= 0x073) { data = m_rtc->read(offset & 0x01); decoded = true; }
567 	else if (addr >= 0x078 && addr <= 0x07f) { data = mouse_r(offset & 0x07); decoded = true; }
568 	else if (addr >= 0x378 && addr <= 0x37b) { data = printer_r(offset & 0x03); decoded = true; }
569 	else if (addr >= 0x3b0 && addr <= 0x3df) { decoded = true; }
570 	else if (addr >= 0x3f4 && addr <= 0x3f4) { data = m_fdc->msr_r(); decoded = true; }
571 	else if (addr >= 0x3f5 && addr <= 0x3f5) { data = m_fdc->fifo_r(); decoded = true; }
572 	else if (addr >= 0x3f8 && addr <= 0x3ff) { data = m_uart->ins8250_r(offset & 0x07); decoded = true; }
573 
574 	if (decoded)
575 	{
576 		if (BIT(offset, 7))
577 		{
578 			m_opt = 0;
579 			//logerror("OPT 0\n");
580 		}
581 	}
582 	else if (!BIT(offset, 7))
583 	{
584 		uint16_t sw = m_sw->read();
585 
586 		if (!BIT(offset, 14))
587 		{
588 			m_opt = BIT(sw, 8);
589 			logerror("OPT SW9 %u\n", m_opt);
590 		}
591 		else
592 		{
593 			m_opt = BIT(sw, 9);
594 			logerror("OPT SW10 %u\n", m_opt);
595 		}
596 	}
597 
598 	return data;
599 }
600 
601 
602 
603 //**************************************************************************
604 //  ADDRESS MAPS
605 //**************************************************************************
606 
607 //-------------------------------------------------
608 //  ADDRESS_MAP( pc1512_mem )
609 //-------------------------------------------------
610 
pc1512_mem(address_map & map)611 void pc1512_state::pc1512_mem(address_map &map)
612 {
613 	map(0x00000, 0x9ffff).ram();
614 	map(0xb8000, 0xbbfff).rw(m_vdu, FUNC(ams40041_device::video_ram_r), FUNC(ams40041_device::video_ram_w));
615 	map(0xfc000, 0xfffff).rom().region(I8086_TAG, 0);
616 }
617 
618 
619 //-------------------------------------------------
620 //  ADDRESS_MAP( pc1512_io )
621 //-------------------------------------------------
622 
pc1512_io(address_map & map)623 void pc1512_state::pc1512_io(address_map &map)
624 {
625 	// [RH] 29 Aug 2016: I can find no evidence to indicate that Amstrad had only 10 I/O lines, as the
626 	// schematic calls for a stock 8086 and the I/O and data lines are multiplexed onto the same bus,
627 	// plus address lines 20-10 are towards the middle of a standard ISA slot. If it turns out that this
628 	// is not in fact accurate to hardware, please add this back in.
629 	// map.global_mask(0x3ff);
630 	map(0x000, 0x00f).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
631 	map(0x020, 0x021).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
632 	map(0x040, 0x043).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write));
633 	map(0x060, 0x06f).rw(FUNC(pc1512_state::system_r), FUNC(pc1512_state::system_w));
634 	map(0x070, 0x071).mirror(0x02).rw(m_rtc, FUNC(mc146818_device::read), FUNC(mc146818_device::write));
635 	map(0x078, 0x07f).rw(FUNC(pc1512_state::mouse_r), FUNC(pc1512_state::mouse_w));
636 	map(0x080, 0x083).w(FUNC(pc1512_state::dma_page_w));
637 	map(0x0a1, 0x0a1).w(FUNC(pc1512_state::nmi_mask_w));
638 	map(0x378, 0x37b).rw(FUNC(pc1512_state::printer_r), FUNC(pc1512_state::printer_w));
639 	map(0x3d0, 0x3df).rw(m_vdu, FUNC(ams40041_device::vdu_r), FUNC(ams40041_device::vdu_w));
640 	map(0x3f2, 0x3f2).w(FUNC(pc1512_state::drive_select_w));
641 	map(0x3f4, 0x3f5).m(m_fdc, FUNC(upd765a_device::map));
642 	map(0x3f8, 0x3ff).rw(m_uart, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
643 }
644 
645 
646 //-------------------------------------------------
647 //  ADDRESS_MAP( pc1640_mem )
648 //-------------------------------------------------
649 
pc1640_mem(address_map & map)650 void pc1640_state::pc1640_mem(address_map &map)
651 {
652 	map(0x00000, 0x9ffff).ram();
653 	map(0xf0000, 0xf3fff).mirror(0xc000).rom().region(I8086_TAG, 0);
654 }
655 
656 
657 //-------------------------------------------------
658 //  ADDRESS_MAP( pc1640_io )
659 //-------------------------------------------------
660 
pc1640_io(address_map & map)661 void pc1640_state::pc1640_io(address_map &map)
662 {
663 	map(0x0000, 0xffff).r(FUNC(pc1640_state::io_r));
664 
665 	map(0x000, 0x00f).w(m_dmac, FUNC(am9517a_device::write));
666 	map(0x020, 0x021).w(m_pic, FUNC(pic8259_device::write));
667 	map(0x040, 0x043).w(m_pit, FUNC(pit8253_device::write));
668 	map(0x060, 0x06f).w(FUNC(pc1640_state::system_w));
669 	map(0x070, 0x071).mirror(0x02).w(m_rtc, FUNC(mc146818_device::write));
670 	map(0x078, 0x07f).w(FUNC(pc1640_state::mouse_w));
671 	map(0x080, 0x083).w(FUNC(pc1640_state::dma_page_w));
672 	map(0x0a1, 0x0a1).w(FUNC(pc1640_state::nmi_mask_w));
673 	map(0x378, 0x37b).w(FUNC(pc1640_state::printer_w));
674 	map(0x3f2, 0x3f2).w(FUNC(pc1640_state::drive_select_w));
675 	map(0x3f5, 0x3f5).w(m_fdc, FUNC(upd765a_device::fifo_w));
676 	map(0x3f8, 0x3ff).w(m_uart, FUNC(ins8250_device::ins8250_w));
677 }
678 
679 
680 
681 //**************************************************************************
682 //  INPUT PORTS
683 //**************************************************************************
684 
685 //-------------------------------------------------
686 //  INPUT_PORTS( pc1512 )
687 //-------------------------------------------------
688 
689 static INPUT_PORTS_START( pc1512 )
690 	PORT_START("LK")
DEF_STR(Language)691 	PORT_DIPNAME( 0x07, 0x07, DEF_STR( Language ) )
692 	PORT_DIPSETTING(    0x07, DEF_STR( English ) )
693 	PORT_DIPSETTING(    0x06, DEF_STR( German ) )
694 	PORT_DIPSETTING(    0x05, DEF_STR( French ) )
695 	PORT_DIPSETTING(    0x04, DEF_STR( Spanish ) )
696 	PORT_DIPSETTING(    0x03, "Danish" )
697 	PORT_DIPSETTING(    0x02, "Swedish" )
698 	PORT_DIPSETTING(    0x01, DEF_STR( Italian ) )
699 	PORT_DIPSETTING(    0x00, "Diagnostic Mode" )
700 	PORT_DIPNAME( 0x08, 0x08, "Memory Size")
701 	PORT_DIPSETTING( 0x08, "512 KB" )
702 	PORT_DIPSETTING( 0x00, "640 KB" )
703 	PORT_DIPNAME( 0x10, 0x10, "ROM Size")
704 	PORT_DIPSETTING( 0x10, "16 KB" )
705 	PORT_DIPSETTING( 0x00, "32 KB" )
706 	PORT_DIPNAME( 0x60, 0x60, "Character Set")
707 	PORT_DIPSETTING( 0x60, "Default (Codepage 437)" )
708 	PORT_DIPSETTING( 0x40, "Portuguese (Codepage 865)" )
709 	PORT_DIPSETTING( 0x20, "Norwegian (Codepage 860)" )
710 	PORT_DIPSETTING( 0x00, "Greek")
711 	PORT_DIPNAME( 0x80, 0x80, "Floppy Ready Line")
712 	PORT_DIPSETTING( 0x80, "Connected" )
713 	PORT_DIPSETTING( 0x00, "Not connected" )
714 INPUT_PORTS_END
715 
716 
717 //-------------------------------------------------
718 //  INPUT_PORTS( pc1640 )
719 //-------------------------------------------------
720 
721 static INPUT_PORTS_START( pc1640 )
722 	PORT_START("LK")
723 	PORT_DIPNAME( 0x07, 0x07, DEF_STR( Language ) )
724 	PORT_DIPSETTING(    0x07, DEF_STR( English ) )
725 	PORT_DIPSETTING(    0x06, DEF_STR( German ) )
726 	PORT_DIPSETTING(    0x05, DEF_STR( French ) )
727 	PORT_DIPSETTING(    0x04, DEF_STR( Spanish ) )
728 	PORT_DIPSETTING(    0x03, "Danish" )
729 	PORT_DIPSETTING(    0x02, "Swedish" )
730 	PORT_DIPSETTING(    0x01, DEF_STR( Italian ) )
731 	PORT_DIPSETTING(    0x00, "Diagnostic Mode" )
732 
733 	PORT_START("SW")
734 	PORT_DIPNAME( 0x0f, 0x09, "Initial Display Mode" ) PORT_DIPLOCATION("SW:1,2,3,4") PORT_CONDITION("SW", 0x200, EQUALS, 0x200)
735 	PORT_DIPSETTING(    0x0b, "Internal MD, External CGA80" )
736 	PORT_DIPSETTING(    0x0a, "Internal MD, External CGA40" )
737 	PORT_DIPSETTING(    0x09, "Internal ECD350, External MDA/HERC" )
738 	PORT_DIPSETTING(    0x08, "Internal ECD200, External MDA/HERC" )
739 	PORT_DIPSETTING(    0x07, "Internal CD80, External MDA/HERC" )
740 	PORT_DIPSETTING(    0x06, "Internal CD40, External MDA/HERC" )
741 	PORT_DIPSETTING(    0x05, "External CGA80, Internal MD" )
742 	PORT_DIPSETTING(    0x04, "External CGA40, Internal MD" )
743 	PORT_DIPSETTING(    0x03, "External MDA/HERC, Internal ECD350" )
744 	PORT_DIPSETTING(    0x02, "External MDA/HERC, Internal ECD200" )
745 	PORT_DIPSETTING(    0x01, "External MDA/HERC, Internal CD80" )
746 	PORT_DIPSETTING(    0x00, "External MDA/HERC, Internal CD40" )
747 	PORT_DIPNAME( 0x10, 0x10, "MC6845 Mode" ) PORT_DIPLOCATION("SW:5") PORT_CONDITION("SW", 0x200, EQUALS, 0x200)
748 	PORT_DIPSETTING(    0x10, "EGA" )
749 	PORT_DIPSETTING(    0x00, "CGA/MDA/HERC" )
750 	PORT_DIPNAME( 0x60, 0x00, "Font" ) PORT_DIPLOCATION("SW:6,7") PORT_CONDITION("SW", 0x300, EQUALS, 0x300)
751 	PORT_DIPSETTING(    0x00, DEF_STR( English ) )
752 	PORT_DIPSETTING(    0x60, "Danish" )
753 	PORT_DIPSETTING(    0x40, "Portuguese" )
754 	PORT_DIPSETTING(    0x20, "Greek" )
755 	PORT_DIPNAME( 0x60, 0x60, "Default Display Mode" ) PORT_DIPLOCATION("SW:6,7") PORT_CONDITION("SW", 0x200, EQUALS, 0x000)
756 	PORT_DIPSETTING(    0x60, "External EGA" )
757 	PORT_DIPSETTING(    0x40, "External CGA in 40 Column Mode" )
758 	PORT_DIPSETTING(    0x20, "External CGA in 80 Column Mode" )
759 	PORT_DIPSETTING(    0x00, "External Monochrome Adapter" )
760 	PORT_DIPNAME( 0x80, 0x00, "Monitor" ) PORT_DIPLOCATION("SW:8") PORT_CONDITION("SW", 0x200, EQUALS, 0x200)
761 	PORT_DIPSETTING(    0x80, "CD (Standard RGB)" )
762 	PORT_DIPSETTING(    0x00, "ECD (Enhanced RGB)" )
763 	PORT_DIPNAME( 0x100, 0x100, "Foreign Fonts" ) PORT_DIPLOCATION("SW:9") PORT_CONDITION("SW", 0x200, EQUALS, 0x200)
764 	PORT_DIPSETTING(     0x100, "Enabled" )
765 	PORT_DIPSETTING(     0x000, "Disabled" )
766 	PORT_DIPNAME( 0x200, 0x200, "Internal Graphics Adapter" ) PORT_DIPLOCATION("SW:10")
767 	PORT_DIPSETTING(     0x200, "Enabled" )
768 	PORT_DIPSETTING(     0x000, "Disabled" )
769 INPUT_PORTS_END
770 
771 
772 
773 //**************************************************************************
774 //  DEVICE CONFIGURATION
775 //**************************************************************************
776 
777 //-------------------------------------------------
778 //  PC1512_KEYBOARD_INTERFACE( kb_intf )
779 //-------------------------------------------------
780 
781 WRITE_LINE_MEMBER( pc1512_base_state::kbdata_w )
782 {
783 	m_kbdata = state;
784 }
785 
WRITE_LINE_MEMBER(pc1512_base_state::kbclk_w)786 WRITE_LINE_MEMBER( pc1512_base_state::kbclk_w )
787 {
788 	if (!BIT(m_port61, 7) && m_kbclk && !state)
789 	{
790 		m_kbd <<= 1;
791 		m_kbd |= m_kbdata;
792 		m_kb_bits++;
793 
794 		if (m_kb_bits == 8)
795 		{
796 			m_kb->data_w(0);
797 			m_pic->ir1_w(ASSERT_LINE);
798 		}
799 	}
800 
801 	m_kbclk = state;
802 }
803 
mouse_x_w(uint8_t data)804 void pc1512_base_state::mouse_x_w(uint8_t data)
805 {
806 	if (data > m_mouse_x_old)
807 		m_mouse_x+=3;
808 	else
809 		m_mouse_x-=3;
810 
811 	m_mouse_x_old = data;
812 }
813 
mouse_y_w(uint8_t data)814 void pc1512_base_state::mouse_y_w(uint8_t data)
815 {
816 	if (data > m_mouse_y_old)
817 		m_mouse_y-=3;
818 	else
819 		m_mouse_y+=3;
820 
821 	m_mouse_y_old = data;
822 }
823 
824 //-------------------------------------------------
825 //  I8237_INTERFACE( dmac_intf )
826 //-------------------------------------------------
827 
update_fdc_tc()828 void pc1512_base_state::update_fdc_tc()
829 {
830 	if (m_nden)
831 		m_fdc->tc_w(m_neop);
832 	else
833 		m_fdc->tc_w(false);
834 }
835 
WRITE_LINE_MEMBER(pc1512_base_state::hrq_w)836 WRITE_LINE_MEMBER( pc1512_base_state::hrq_w )
837 {
838 	m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
839 
840 	m_dmac->hack_w(state);
841 }
842 
WRITE_LINE_MEMBER(pc1512_base_state::eop_w)843 WRITE_LINE_MEMBER( pc1512_base_state::eop_w )
844 {
845 	if (m_dma_channel == 2)
846 	{
847 		m_neop = !state;
848 		update_fdc_tc();
849 	}
850 }
851 
memr_r(offs_t offset)852 uint8_t pc1512_base_state::memr_r(offs_t offset)
853 {
854 	address_space &program = m_maincpu->space(AS_PROGRAM);
855 	offs_t page_offset = m_dma_page[m_dma_channel] << 16;
856 
857 	return program.read_byte(page_offset + offset);
858 }
859 
memw_w(offs_t offset,uint8_t data)860 void pc1512_base_state::memw_w(offs_t offset, uint8_t data)
861 {
862 	address_space &program = m_maincpu->space(AS_PROGRAM);
863 	offs_t page_offset = m_dma_page[m_dma_channel] << 16;
864 
865 	program.write_byte(page_offset + offset, data);
866 }
867 
ior1_r()868 uint8_t pc1512_base_state::ior1_r()
869 {
870 	return m_bus->dack_r(1);
871 }
872 
ior2_r()873 uint8_t pc1512_base_state::ior2_r()
874 {
875 	if (m_nden)
876 		return m_fdc->dma_r();
877 	else
878 		return m_bus->dack_r(2);
879 }
880 
ior3_r()881 uint8_t pc1512_base_state::ior3_r()
882 {
883 	return m_bus->dack_r(3);
884 }
885 
iow0_w(uint8_t data)886 void pc1512_base_state::iow0_w(uint8_t data)
887 {
888 	m_dreq0 = 0;
889 	m_dmac->dreq0_w(m_dreq0);
890 }
891 
iow1_w(uint8_t data)892 void pc1512_base_state::iow1_w(uint8_t data)
893 {
894 	m_bus->dack_w(1, data);
895 }
896 
iow2_w(uint8_t data)897 void pc1512_base_state::iow2_w(uint8_t data)
898 {
899 	if (m_nden)
900 		m_fdc->dma_w(data);
901 	else
902 		m_bus->dack_w(2, data);
903 }
904 
iow3_w(uint8_t data)905 void pc1512_base_state::iow3_w(uint8_t data)
906 {
907 	m_bus->dack_w(3, data);
908 }
909 
WRITE_LINE_MEMBER(pc1512_base_state::dack0_w)910 WRITE_LINE_MEMBER( pc1512_base_state::dack0_w )
911 {
912 	if (!state) m_dma_channel = 0;
913 }
914 
WRITE_LINE_MEMBER(pc1512_base_state::dack1_w)915 WRITE_LINE_MEMBER( pc1512_base_state::dack1_w )
916 {
917 	if (!state) m_dma_channel = 1;
918 }
919 
WRITE_LINE_MEMBER(pc1512_base_state::dack2_w)920 WRITE_LINE_MEMBER( pc1512_base_state::dack2_w )
921 {
922 	if (!state) m_dma_channel = 2;
923 }
924 
WRITE_LINE_MEMBER(pc1512_base_state::dack3_w)925 WRITE_LINE_MEMBER( pc1512_base_state::dack3_w )
926 {
927 	if (!state) m_dma_channel = 3;
928 }
929 
930 //-------------------------------------------------
931 //  pit8253_config pit_intf
932 //-------------------------------------------------
933 
update_speaker()934 void pc1512_base_state::update_speaker()
935 {
936 	m_speaker->level_w(m_speaker_drive & m_pit2);
937 }
938 
WRITE_LINE_MEMBER(pc1512_base_state::pit1_w)939 WRITE_LINE_MEMBER( pc1512_base_state::pit1_w )
940 {
941 	if (!m_pit1 && state && !m_dreq0)
942 	{
943 		m_dreq0 = 1;
944 		m_dmac->dreq0_w(m_dreq0);
945 	}
946 
947 	m_pit1 = state;
948 }
949 
WRITE_LINE_MEMBER(pc1512_base_state::pit2_w)950 WRITE_LINE_MEMBER( pc1512_base_state::pit2_w )
951 {
952 	m_pit2 = state;
953 	update_speaker();
954 }
955 
956 //-------------------------------------------------
957 //  upd765_interface fdc_intf
958 //-------------------------------------------------
959 
update_fdc_int()960 void pc1512_base_state::update_fdc_int()
961 {
962 	if (m_nden)
963 		m_pic->ir6_w(m_dint);
964 	else
965 		m_pic->ir6_w(CLEAR_LINE);
966 }
967 
update_fdc_drq()968 void pc1512_base_state::update_fdc_drq()
969 {
970 	if (m_nden)
971 		m_dmac->dreq2_w(m_ddrq);
972 	else
973 		m_dmac->dreq2_w(0);
974 }
975 
WRITE_LINE_MEMBER(pc1512_base_state::fdc_int_w)976 WRITE_LINE_MEMBER( pc1512_base_state::fdc_int_w )
977 {
978 	m_dint = state;
979 	update_fdc_int();
980 }
981 
WRITE_LINE_MEMBER(pc1512_base_state::fdc_drq_w)982 WRITE_LINE_MEMBER( pc1512_base_state::fdc_drq_w )
983 {
984 	m_ddrq = state;
985 	update_fdc_drq();
986 }
987 
drive_select_w(uint8_t data)988 void pc1512_base_state::drive_select_w(uint8_t data)
989 {
990 	m_fdc->set_floppy((data & 0x03) < 2 ? m_floppy[data & 0x03]->get_device() : nullptr);
991 	for (int n = 0; n < 2; n++)
992 	{
993 		floppy_image_device *img = m_floppy[n]->get_device();
994 		if (img != nullptr)
995 			 img->mon_w((data & 0x03) == n && BIT(data, n + 4) ? 0 : 1);
996 	}
997 
998 	m_fdc->reset_w(!BIT(data, 2));
999 	m_nden = BIT(data, 3);
1000 	update_fdc_int();
1001 	update_fdc_drq();
1002 }
1003 
1004 //-------------------------------------------------
1005 //  centronics_interface centronics_intf
1006 //-------------------------------------------------
1007 
update_ack()1008 void pc1512_base_state::update_ack()
1009 {
1010 	if (m_ack_int_enable)
1011 		m_pic->ir7_w(m_centronics_ack);
1012 	else
1013 		m_pic->ir7_w(CLEAR_LINE);
1014 }
1015 
WRITE_LINE_MEMBER(pc1512_base_state::write_centronics_ack)1016 WRITE_LINE_MEMBER( pc1512_base_state::write_centronics_ack )
1017 {
1018 	m_centronics_ack = state;
1019 	update_ack();
1020 }
1021 
WRITE_LINE_MEMBER(pc1512_base_state::write_centronics_busy)1022 WRITE_LINE_MEMBER( pc1512_base_state::write_centronics_busy )
1023 {
1024 	m_centronics_busy = state;
1025 }
1026 
WRITE_LINE_MEMBER(pc1512_base_state::write_centronics_perror)1027 WRITE_LINE_MEMBER( pc1512_base_state::write_centronics_perror )
1028 {
1029 	m_centronics_perror = state;
1030 }
1031 
WRITE_LINE_MEMBER(pc1512_base_state::write_centronics_select)1032 WRITE_LINE_MEMBER( pc1512_base_state::write_centronics_select )
1033 {
1034 	m_centronics_select = state;
1035 }
1036 
WRITE_LINE_MEMBER(pc1512_base_state::write_centronics_fault)1037 WRITE_LINE_MEMBER( pc1512_base_state::write_centronics_fault )
1038 {
1039 	m_centronics_fault = state;
1040 }
1041 
1042 
1043 //-------------------------------------------------
1044 //  isa8bus_interface isabus_intf
1045 //-------------------------------------------------
1046 
pc1640_isa8_cards(device_slot_interface & device)1047 void pc1640_isa8_cards(device_slot_interface &device)
1048 {
1049 	device.option_add_internal("iga", ISA8_PC1640_IGA);
1050 }
1051 
FLOPPY_FORMATS_MEMBER(pc1512_base_state::floppy_formats)1052 FLOPPY_FORMATS_MEMBER( pc1512_base_state::floppy_formats )
1053 	FLOPPY_PC_FORMAT
1054 FLOPPY_FORMATS_END
1055 
1056 static void pc1512_floppies(device_slot_interface &device)
1057 {
1058 	device.option_add("525dd", FLOPPY_525_DD); // Tandon TM65-2L
1059 }
1060 
1061 
1062 
1063 //**************************************************************************
1064 //  MACHINE INITIALIZATION
1065 //**************************************************************************
1066 
machine_start()1067 void pc1512_base_state::machine_start()
1068 {
1069 	save_item(NAME(m_pit1));
1070 	save_item(NAME(m_pit2));
1071 	save_item(NAME(m_status1));
1072 	save_item(NAME(m_status2));
1073 	save_item(NAME(m_port61));
1074 	save_item(NAME(m_nmi_enable));
1075 	save_item(NAME(m_kbd));
1076 	save_item(NAME(m_kb_bits));
1077 	save_item(NAME(m_kbclk));
1078 	save_item(NAME(m_kbdata));
1079 	save_item(NAME(m_mouse_x));
1080 	save_item(NAME(m_mouse_y));
1081 	save_item(NAME(m_mouse_x_old));
1082 	save_item(NAME(m_mouse_y_old));
1083 	save_item(NAME(m_dma_page));
1084 	save_item(NAME(m_dma_channel));
1085 	save_item(NAME(m_dreq0));
1086 	save_item(NAME(m_nden));
1087 	save_item(NAME(m_dint));
1088 	save_item(NAME(m_ddrq));
1089 	save_item(NAME(m_neop));
1090 	save_item(NAME(m_ack_int_enable));
1091 	save_item(NAME(m_centronics_ack));
1092 	save_item(NAME(m_centronics_busy));
1093 	save_item(NAME(m_centronics_perror));
1094 	save_item(NAME(m_centronics_select));
1095 	save_item(NAME(m_centronics_fault));
1096 	save_item(NAME(m_printer_data));
1097 	save_item(NAME(m_printer_control));
1098 	save_item(NAME(m_speaker_drive));
1099 }
1100 
machine_start()1101 void pc1512_state::machine_start()
1102 {
1103 	pc1512_base_state::machine_start();
1104 
1105 	// set RAM size
1106 	size_t ram_size = m_ram->size();
1107 
1108 	if (ram_size < 640 * 1024)
1109 	{
1110 		address_space &program = m_maincpu->space(AS_PROGRAM);
1111 		program.unmap_readwrite(ram_size, 0x9ffff);
1112 	}
1113 }
1114 
machine_reset()1115 void pc1512_base_state::machine_reset()
1116 {
1117 	m_nmi_enable = 0;
1118 	drive_select_w(0);
1119 
1120 	m_kb_bits = 0;
1121 	m_kb->data_w(1);
1122 	m_pic->ir1_w(CLEAR_LINE);
1123 }
1124 
machine_reset()1125 void pc1512_state::machine_reset()
1126 {
1127 	pc1512_base_state::machine_reset();
1128 
1129 	m_pit2 = 1;
1130 }
1131 
1132 
1133 //-------------------------------------------------
1134 //  MACHINE_START( pc1640 )
1135 //-------------------------------------------------
1136 
machine_start()1137 void pc1640_state::machine_start()
1138 {
1139 	pc1512_base_state::machine_start();
1140 
1141 	// state saving
1142 	save_item(NAME(m_opt));
1143 }
1144 
1145 
1146 //**************************************************************************
1147 //  MACHINE DRIVERS
1148 //**************************************************************************
1149 
1150 //-------------------------------------------------
1151 //  machine_config( pc1512 )
1152 //-------------------------------------------------
1153 
pc1512(machine_config & config)1154 void pc1512_state::pc1512(machine_config &config)
1155 {
1156 	I8086(config, m_maincpu, 24_MHz_XTAL / 3);
1157 	m_maincpu->set_addrmap(AS_PROGRAM, &pc1512_state::pc1512_mem);
1158 	m_maincpu->set_addrmap(AS_IO, &pc1512_state::pc1512_io);
1159 	m_maincpu->set_irq_acknowledge_callback(I8259A2_TAG, FUNC(pic8259_device::inta_cb));
1160 
1161 	// video
1162 	screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER));
1163 	screen.set_raw(28.636363_MHz_XTAL, 912, 0, 910, 262, 0, 260);
1164 	screen.set_screen_update(m_vdu, FUNC(ams40041_device::screen_update));
1165 
1166 	AMS40041(config, m_vdu, 28.636363_MHz_XTAL);
1167 	m_vdu->set_screen(SCREEN_TAG);
1168 	m_vdu->set_show_border_area(true);
1169 
1170 	// sound
1171 	SPEAKER(config, "mono").front_center();
1172 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.80);
1173 
1174 	// devices
1175 	PC1512_KEYBOARD(config, m_kb, 0);
1176 	m_kb->clock_wr_callback().set(FUNC(pc1512_state::kbclk_w));
1177 	m_kb->data_wr_callback().set(FUNC(pc1512_state::kbdata_w));
1178 
1179 	pc1512_mouse_port_device &mouse(PC1512_MOUSE_PORT(config, "mous", pc1512_mouse_port_devices, "mouse"));
1180 	mouse.x_wr_callback().set(FUNC(pc1512_base_state::mouse_x_w));
1181 	mouse.y_wr_callback().set(FUNC(pc1512_base_state::mouse_y_w));
1182 	mouse.m1_wr_callback().set(m_kb, FUNC(pc1512_keyboard_device::m1_w));
1183 	mouse.m2_wr_callback().set(m_kb, FUNC(pc1512_keyboard_device::m2_w));
1184 
1185 	AM9517A(config, m_dmac, 24_MHz_XTAL / 6);
1186 	m_dmac->out_hreq_callback().set(FUNC(pc1512_state::hrq_w));
1187 	m_dmac->out_eop_callback().set(FUNC(pc1512_state::eop_w));
1188 	m_dmac->in_memr_callback().set(FUNC(pc1512_state::memr_r));
1189 	m_dmac->out_memw_callback().set(FUNC(pc1512_state::memw_w));
1190 	m_dmac->in_ior_callback<1>().set(FUNC(pc1512_state::ior1_r));
1191 	m_dmac->in_ior_callback<2>().set(FUNC(pc1512_state::ior2_r));
1192 	m_dmac->in_ior_callback<3>().set(FUNC(pc1512_state::ior3_r));
1193 	m_dmac->out_iow_callback<0>().set(FUNC(pc1512_state::iow0_w));
1194 	m_dmac->out_iow_callback<1>().set(FUNC(pc1512_state::iow1_w));
1195 	m_dmac->out_iow_callback<2>().set(FUNC(pc1512_state::iow2_w));
1196 	m_dmac->out_iow_callback<3>().set(FUNC(pc1512_state::iow3_w));
1197 	m_dmac->out_dack_callback<0>().set(FUNC(pc1512_state::dack0_w));
1198 	m_dmac->out_dack_callback<1>().set(FUNC(pc1512_state::dack1_w));
1199 	m_dmac->out_dack_callback<2>().set(FUNC(pc1512_state::dack2_w));
1200 	m_dmac->out_dack_callback<3>().set(FUNC(pc1512_state::dack3_w));
1201 
1202 	PIC8259(config, m_pic);
1203 	m_pic->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1204 
1205 	PIT8253(config, m_pit);
1206 	m_pit->set_clk<0>(28.636363_MHz_XTAL / 24);
1207 	m_pit->out_handler<0>().set(m_pic, FUNC(pic8259_device::ir0_w));
1208 	m_pit->set_clk<1>(28.636363_MHz_XTAL / 24);
1209 	m_pit->out_handler<1>().set(FUNC(pc1512_state::pit1_w));
1210 	m_pit->set_clk<2>(28.636363_MHz_XTAL / 24);
1211 	m_pit->out_handler<2>().set(FUNC(pc1512_state::pit2_w));
1212 
1213 	MC146818(config, m_rtc, 32.768_kHz_XTAL);
1214 	m_rtc->irq().set(m_pic, FUNC(pic8259_device::ir2_w));
1215 
1216 	UPD765A(config, m_fdc, 24_MHz_XTAL / 6, false, false);
1217 	// SED9420CAC (dedicated 16 MHz XTAL) is used as read data separator only
1218 	m_fdc->intrq_wr_callback().set(FUNC(pc1512_state::fdc_int_w));
1219 	m_fdc->drq_wr_callback().set(FUNC(pc1512_state::fdc_drq_w));
1220 	FLOPPY_CONNECTOR(config, m_floppy[0], pc1512_floppies, "525dd", pc1512_base_state::floppy_formats);
1221 	FLOPPY_CONNECTOR(config, m_floppy[1], pc1512_floppies, nullptr, pc1512_base_state::floppy_formats);
1222 
1223 	INS8250(config, m_uart, 1.8432_MHz_XTAL);
1224 	m_uart->out_tx_callback().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
1225 	m_uart->out_dtr_callback().set(RS232_TAG, FUNC(rs232_port_device::write_dtr));
1226 	m_uart->out_rts_callback().set(RS232_TAG, FUNC(rs232_port_device::write_rts));
1227 	m_uart->out_int_callback().set(m_pic, FUNC(pic8259_device::ir4_w));
1228 
1229 	CENTRONICS(config, m_centronics, centronics_devices, "printer");
1230 	m_centronics->ack_handler().set(FUNC(pc1512_state::write_centronics_ack));
1231 	m_centronics->busy_handler().set(FUNC(pc1512_state::write_centronics_busy));
1232 	m_centronics->perror_handler().set(FUNC(pc1512_state::write_centronics_perror));
1233 	m_centronics->select_handler().set(FUNC(pc1512_state::write_centronics_select));
1234 	m_centronics->fault_handler().set(FUNC(pc1512_state::write_centronics_fault));
1235 
1236 	OUTPUT_LATCH(config, m_cent_data_out);
1237 	m_centronics->set_output_latch(*m_cent_data_out);
1238 
1239 	rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
1240 	rs232.rxd_handler().set(m_uart, FUNC(ins8250_uart_device::rx_w));
1241 	rs232.dcd_handler().set(m_uart, FUNC(ins8250_uart_device::dcd_w));
1242 	rs232.dsr_handler().set(m_uart, FUNC(ins8250_uart_device::dsr_w));
1243 	rs232.ri_handler().set(m_uart, FUNC(ins8250_uart_device::ri_w));
1244 	rs232.cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));
1245 
1246 	// ISA8 bus
1247 	isa8_device &isa(ISA8(config, ISA_BUS_TAG, 0));
1248 	isa.set_memspace(m_maincpu, AS_PROGRAM);
1249 	isa.set_iospace(m_maincpu, AS_IO);
1250 	isa.irq2_callback().set(m_pic, FUNC(pic8259_device::ir2_w));
1251 	isa.irq3_callback().set(m_pic, FUNC(pic8259_device::ir3_w));
1252 	isa.irq4_callback().set(m_pic, FUNC(pic8259_device::ir4_w));
1253 	isa.irq5_callback().set(m_pic, FUNC(pic8259_device::ir5_w));
1254 	isa.irq6_callback().set(m_pic, FUNC(pic8259_device::ir6_w));
1255 	isa.irq7_callback().set(m_pic, FUNC(pic8259_device::ir7_w));
1256 	isa.drq1_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq1_w));
1257 	isa.drq2_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq2_w));
1258 	isa.drq3_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq3_w));
1259 	ISA8_SLOT(config, "isa1", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false); // FIXME: determine ISA clock
1260 	ISA8_SLOT(config, "isa2", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false);
1261 	ISA8_SLOT(config, "isa3", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false);
1262 
1263 	// internal ram
1264 	RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("544K,576K,608K,640K");
1265 
1266 	// software list
1267 	SOFTWARE_LIST(config, "flop_list").set_original("pc1512_flop");
1268 	SOFTWARE_LIST(config, "hdd_list").set_original("pc1512_hdd");
1269 }
1270 
1271 
1272 //-------------------------------------------------
1273 //  machine_config( pc1512dd )
1274 //-------------------------------------------------
1275 
pc1512dd(machine_config & config)1276 void pc1512_state::pc1512dd(machine_config &config)
1277 {
1278 	pc1512(config);
1279 	m_floppy[1]->set_default_option("525dd");
1280 }
1281 
1282 
1283 //-------------------------------------------------
1284 //  machine_config( pc1512hd )
1285 //-------------------------------------------------
1286 
pc1512hd(machine_config & config)1287 void pc1512_state::pc1512hd(machine_config &config)
1288 {
1289 	pc1512(config);
1290 	//subdevice<isa8_slot_device>("isa1")->set_default_option("wdxt_gen");
1291 	subdevice<isa8_slot_device>("isa1")->set_default_option("hdc");
1292 }
1293 
1294 
1295 //-------------------------------------------------
1296 //  machine_config( pc1640 )
1297 //-------------------------------------------------
1298 
pc1640(machine_config & config)1299 void pc1640_state::pc1640(machine_config &config)
1300 {
1301 	I8086(config, m_maincpu, 24_MHz_XTAL / 3);
1302 	m_maincpu->set_addrmap(AS_PROGRAM, &pc1640_state::pc1640_mem);
1303 	m_maincpu->set_addrmap(AS_IO, &pc1640_state::pc1640_io);
1304 	m_maincpu->set_irq_acknowledge_callback(I8259A2_TAG, FUNC(pic8259_device::inta_cb));
1305 
1306 	// sound
1307 	SPEAKER(config, "mono").front_center();
1308 	SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.80);
1309 
1310 	// devices
1311 	PC1512_KEYBOARD(config, m_kb, 0);
1312 	m_kb->clock_wr_callback().set(FUNC(pc1512_base_state::kbclk_w));
1313 	m_kb->data_wr_callback().set(FUNC(pc1512_base_state::kbdata_w));
1314 
1315 	pc1512_mouse_port_device &mouse(PC1512_MOUSE_PORT(config, "mous", pc1512_mouse_port_devices, "mouse"));
1316 	mouse.x_wr_callback().set(FUNC(pc1512_base_state::mouse_x_w));
1317 	mouse.y_wr_callback().set(FUNC(pc1512_base_state::mouse_y_w));
1318 	mouse.m1_wr_callback().set(m_kb, FUNC(pc1512_keyboard_device::m1_w));
1319 	mouse.m2_wr_callback().set(m_kb, FUNC(pc1512_keyboard_device::m2_w));
1320 
1321 	AM9517A(config, m_dmac, 24_MHz_XTAL / 6);
1322 	m_dmac->out_hreq_callback().set(FUNC(pc1640_state::hrq_w));
1323 	m_dmac->out_eop_callback().set(FUNC(pc1640_state::eop_w));
1324 	m_dmac->in_memr_callback().set(FUNC(pc1640_state::memr_r));
1325 	m_dmac->out_memw_callback().set(FUNC(pc1640_state::memw_w));
1326 	m_dmac->in_ior_callback<1>().set(FUNC(pc1640_state::ior1_r));
1327 	m_dmac->in_ior_callback<2>().set(FUNC(pc1640_state::ior2_r));
1328 	m_dmac->in_ior_callback<3>().set(FUNC(pc1640_state::ior3_r));
1329 	m_dmac->out_iow_callback<0>().set(FUNC(pc1640_state::iow0_w));
1330 	m_dmac->out_iow_callback<1>().set(FUNC(pc1640_state::iow1_w));
1331 	m_dmac->out_iow_callback<2>().set(FUNC(pc1640_state::iow2_w));
1332 	m_dmac->out_iow_callback<3>().set(FUNC(pc1640_state::iow3_w));
1333 	m_dmac->out_dack_callback<0>().set(FUNC(pc1640_state::dack0_w));
1334 	m_dmac->out_dack_callback<1>().set(FUNC(pc1640_state::dack1_w));
1335 	m_dmac->out_dack_callback<2>().set(FUNC(pc1640_state::dack2_w));
1336 	m_dmac->out_dack_callback<3>().set(FUNC(pc1640_state::dack3_w));
1337 
1338 	PIC8259(config, m_pic);
1339 	m_pic->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
1340 
1341 	PIT8253(config, m_pit);
1342 	m_pit->set_clk<0>(28.636363_MHz_XTAL / 24);
1343 	m_pit->out_handler<0>().set(m_pic, FUNC(pic8259_device::ir0_w));
1344 	m_pit->set_clk<1>(28.636363_MHz_XTAL / 24);
1345 	m_pit->out_handler<1>().set(FUNC(pc1512_base_state::pit1_w));
1346 	m_pit->set_clk<2>(28.636363_MHz_XTAL / 24);
1347 	m_pit->out_handler<2>().set(FUNC(pc1512_base_state::pit2_w));
1348 
1349 	MC146818(config, m_rtc, 32.768_kHz_XTAL);
1350 	m_rtc->irq().set(m_pic, FUNC(pic8259_device::ir2_w));
1351 
1352 	UPD765A(config, m_fdc, 24_MHz_XTAL / 6, false, false);
1353 	// FDC91C36 (clocked by CK8K) is used as read data separator only
1354 	m_fdc->intrq_wr_callback().set(FUNC(pc1512_base_state::fdc_int_w));
1355 	m_fdc->drq_wr_callback().set(FUNC(pc1512_base_state::fdc_drq_w));
1356 	FLOPPY_CONNECTOR(config, m_floppy[0], pc1512_floppies, "525dd", pc1512_base_state::floppy_formats);
1357 	FLOPPY_CONNECTOR(config, m_floppy[1], pc1512_floppies, nullptr, pc1512_base_state::floppy_formats);
1358 
1359 	INS8250(config, m_uart, 1.8432_MHz_XTAL);
1360 	m_uart->out_tx_callback().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
1361 	m_uart->out_dtr_callback().set(RS232_TAG, FUNC(rs232_port_device::write_dtr));
1362 	m_uart->out_rts_callback().set(RS232_TAG, FUNC(rs232_port_device::write_rts));
1363 	m_uart->out_int_callback().set(m_pic, FUNC(pic8259_device::ir4_w));
1364 
1365 	CENTRONICS(config, m_centronics, centronics_devices, "printer");
1366 	m_centronics->ack_handler().set(FUNC(pc1512_state::write_centronics_ack));
1367 	m_centronics->busy_handler().set(FUNC(pc1512_state::write_centronics_busy));
1368 	m_centronics->perror_handler().set(FUNC(pc1512_state::write_centronics_perror));
1369 	m_centronics->select_handler().set(FUNC(pc1512_state::write_centronics_select));
1370 	m_centronics->fault_handler().set(FUNC(pc1512_state::write_centronics_fault));
1371 
1372 	OUTPUT_LATCH(config, m_cent_data_out);
1373 	m_centronics->set_output_latch(*m_cent_data_out);
1374 
1375 	rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
1376 	rs232.rxd_handler().set(m_uart, FUNC(ins8250_uart_device::rx_w));
1377 	rs232.dcd_handler().set(m_uart, FUNC(ins8250_uart_device::dcd_w));
1378 	rs232.dsr_handler().set(m_uart, FUNC(ins8250_uart_device::dsr_w));
1379 	rs232.ri_handler().set(m_uart, FUNC(ins8250_uart_device::ri_w));
1380 	rs232.cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));
1381 
1382 	// ISA8 bus
1383 	isa8_device &isa(ISA8(config, ISA_BUS_TAG, 0));
1384 	isa.set_memspace(m_maincpu, AS_PROGRAM);
1385 	isa.set_iospace(m_maincpu, AS_IO);
1386 	isa.irq2_callback().set(m_pic, FUNC(pic8259_device::ir2_w));
1387 	isa.irq3_callback().set(m_pic, FUNC(pic8259_device::ir3_w));
1388 	isa.irq4_callback().set(m_pic, FUNC(pic8259_device::ir4_w));
1389 	isa.irq5_callback().set(m_pic, FUNC(pic8259_device::ir5_w));
1390 	isa.irq6_callback().set(m_pic, FUNC(pic8259_device::ir6_w));
1391 	isa.irq7_callback().set(m_pic, FUNC(pic8259_device::ir7_w));
1392 	isa.drq1_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq1_w));
1393 	isa.drq2_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq2_w));
1394 	isa.drq3_callback().set(I8237A5_TAG, FUNC(am9517a_device::dreq3_w));
1395 	ISA8_SLOT(config, "isa1", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false); // FIXME: determine ISA bus clock
1396 	ISA8_SLOT(config, "isa2", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false);
1397 	ISA8_SLOT(config, "isa3", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false);
1398 	ISA8_SLOT(config, "isa4", 0, ISA_BUS_TAG, pc_isa8_cards, nullptr, false);
1399 	ISA8_SLOT(config, "isa5", 0, ISA_BUS_TAG, pc1640_isa8_cards, "iga", false);
1400 
1401 	// internal ram
1402 	RAM(config, RAM_TAG).set_default_size("640K");
1403 
1404 	// software list
1405 	SOFTWARE_LIST(config, "flop_list").set_original("pc1640_flop");
1406 	SOFTWARE_LIST(config, "hdd_list").set_original("pc1640_hdd");
1407 }
1408 
1409 
1410 //-------------------------------------------------
1411 //  machine_config( pc1640dd )
1412 //-------------------------------------------------
1413 
pc1640dd(machine_config & config)1414 void pc1640_state::pc1640dd(machine_config &config)
1415 {
1416 	pc1640(config);
1417 	m_floppy[1]->set_default_option("525dd");
1418 }
1419 
1420 
1421 //-------------------------------------------------
1422 //  machine_config( pc1640hd )
1423 //-------------------------------------------------
1424 
pc1640hd(machine_config & config)1425 void pc1640_state::pc1640hd(machine_config &config)
1426 {
1427 	pc1640(config);
1428 	//subdevice<isa8_slot_device>("isa1")->set_default_option("wdxt_gen");
1429 	subdevice<isa8_slot_device>("isa1")->set_default_option("hdc");
1430 }
1431 
1432 
1433 
1434 //**************************************************************************
1435 //  ROMS
1436 //**************************************************************************
1437 
1438 //-------------------------------------------------
1439 //  ROM( pc1512 )
1440 //-------------------------------------------------
1441 
1442 ROM_START( pc1512 )
1443 	ROM_REGION16_LE( 0x4000, I8086_TAG, 0)
1444 	ROM_SYSTEM_BIOS( 0, "v1", "Version 1" )
1445 	ROMX_LOAD( "40044.ic132", 0x0000, 0x2000, CRC(f72f1582) SHA1(7781d4717917262805d514b331ba113b1e05a247), ROM_SKIP(1) | ROM_BIOS(0) )
1446 	ROMX_LOAD( "40043.ic129", 0x0001, 0x2000, CRC(668fcc94) SHA1(74002f5cc542df442eec9e2e7a18db3598d8c482), ROM_SKIP(1) | ROM_BIOS(0) )
1447 	ROM_SYSTEM_BIOS( 1, "v2", "Version 2" )
1448 	ROMX_LOAD( "40044v2.ic132", 0x0000, 0x2000, CRC(1aec54fa) SHA1(b12fd73cfc35a240ed6da4dcc4b6c9910be611e0), ROM_SKIP(1) | ROM_BIOS(1) )
1449 	ROMX_LOAD( "40043v2.ic129", 0x0001, 0x2000, CRC(d2d4d2de) SHA1(c376fd1ad23025081ae16c7949e88eea7f56e1bb), ROM_SKIP(1) | ROM_BIOS(1) )
1450 	ROM_SYSTEM_BIOS( 2, "v3", "Version 3" )
1451 	ROMX_LOAD( "40044-2.ic132", 0x0000, 0x2000, CRC(ea527e6e) SHA1(b77fa44767a71a0b321a88bb0a394f1125b7c220), ROM_SKIP(1) | ROM_BIOS(2) )
1452 	ROMX_LOAD( "40043-2.ic129", 0x0001, 0x2000, CRC(532c3854) SHA1(18a17b710f9eb079d9d7216d07807030f904ceda), ROM_SKIP(1) | ROM_BIOS(2) )
1453 
1454 	ROM_REGION( 0x2000, AMS40041_TAG, 0 )
1455 	ROMX_LOAD( "40045.ic127", 0x0000, 0x2000, CRC(dd5e030f) SHA1(7d858bbb2e8d6143aa67ab712edf5f753c2788a7), ROM_BIOS(0) )
1456 	ROMX_LOAD( "40078.ic127", 0x0000, 0x2000, CRC(ae9c0d04) SHA1(bc8dc4dcedeea5bc1c04986b1f105ad93cb2ebcd), ROM_BIOS(1) )
1457 	ROMX_LOAD( "40078.ic127", 0x0000, 0x2000, CRC(ae9c0d04) SHA1(bc8dc4dcedeea5bc1c04986b1f105ad93cb2ebcd), ROM_BIOS(2) )
1458 ROM_END
1459 
1460 #define rom_pc1512dd    rom_pc1512
1461 #define rom_pc1512hd10  rom_pc1512
1462 #define rom_pc1512hd20  rom_pc1512
1463 
1464 
1465 //-------------------------------------------------
1466 //  ROM( pc1640 )
1467 //-------------------------------------------------
1468 
1469 ROM_START( pc1640 )
1470 	ROM_REGION16_LE( 0x4000, I8086_TAG, 0)
1471 	ROM_SYSTEM_BIOS( 0, "8809", "Week 9/1988" )
1472 	ROMX_LOAD( "40044-1 8809.ic132", 0x0000, 0x2000, CRC(f1c074f3) SHA1(a055ea7e933d137623c22fe24004e870653c7952), ROM_SKIP(1) | ROM_BIOS(0) ) // 8809 B
1473 	ROMX_LOAD( "40043-1 8809.ic129", 0x0001, 0x2000, CRC(e40a1513) SHA1(447eff2057e682e51b1c7593cb6fad0e53879fa8), ROM_SKIP(1) | ROM_BIOS(0) ) // 8809 B
1474 	ROM_SYSTEM_BIOS( 1, "8738", "Week 38/1987" )
1475 	ROMX_LOAD( "40044 8738.ic132", 0x0000, 0x2000, CRC(43832ea7) SHA1(eea4a8836f966940a88c88de6c5cc14852545f7d), ROM_SKIP(1) | ROM_BIOS(1) ) // 8738 D F
1476 	ROMX_LOAD( "40043 8738.ic129", 0x0001, 0x2000, CRC(768498f9) SHA1(ac48cb892417d7998d604f3b79756140c554f476), ROM_SKIP(1) | ROM_BIOS(1) ) // 8738 D F
1477 	ROM_SYSTEM_BIOS( 2, "88xx", "Week ?/1988" )
1478 	ROMX_LOAD( "40044 88xx.ic132", 0x0000, 0x2000, CRC(6090f782) SHA1(e21ae524d5b4d00696d293dbd4fe4d7bca22e277), ROM_SKIP(1) | ROM_BIOS(2) )
1479 	ROMX_LOAD( "40043 88xx.ic129", 0x0001, 0x2000, CRC(9219d0aa) SHA1(dde1a46c8f83e413d7070f1356fc91b9f595a8b6), ROM_SKIP(1) | ROM_BIOS(2) )
1480 ROM_END
1481 
1482 #define rom_pc1640dd    rom_pc1640
1483 #define rom_pc1640hd20  rom_pc1640
1484 #define rom_pc1640hd30  rom_pc1640
1485 
1486 
1487 
1488 //**************************************************************************
1489 //  SYSTEM DRIVERS
1490 //**************************************************************************
1491 
1492 //    YEAR  NAME        PARENT  COMPAT  MACHINE   INPUT   CLASS         INIT        COMPANY        FULLNAME       FLAGS
1493 COMP( 1986, pc1512,     0,      0,      pc1512,   pc1512, pc1512_state, empty_init, "Amstrad plc", "PC1512 SD",   MACHINE_SUPPORTS_SAVE )
1494 COMP( 1986, pc1512dd,   pc1512, 0,      pc1512dd, pc1512, pc1512_state, empty_init, "Amstrad plc", "PC1512 DD",   MACHINE_SUPPORTS_SAVE )
1495 COMP( 1986, pc1512hd10, pc1512, 0,      pc1512hd, pc1512, pc1512_state, empty_init, "Amstrad plc", "PC1512 HD10", MACHINE_SUPPORTS_SAVE )
1496 COMP( 1986, pc1512hd20, pc1512, 0,      pc1512hd, pc1512, pc1512_state, empty_init, "Amstrad plc", "PC1512 HD20", MACHINE_SUPPORTS_SAVE )
1497 COMP( 1987, pc1640,     0,      0,      pc1640,   pc1640, pc1640_state, empty_init, "Amstrad plc", "PC1640 SD",   MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
1498 COMP( 1987, pc1640dd,   pc1640, 0,      pc1640dd, pc1640, pc1640_state, empty_init, "Amstrad plc", "PC1640 DD",   MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
1499 COMP( 1987, pc1640hd20, pc1640, 0,      pc1640hd, pc1640, pc1640_state, empty_init, "Amstrad plc", "PC1640 HD20", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
1500 COMP( 1987, pc1640hd30, pc1640, 0,      pc1640hd, pc1640, pc1640_state, empty_init, "Amstrad plc", "PC1640 HD30", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
1501