2 NEC PC-9801 Emulator 'ePC-9801'
3 NEC PC-9801E/F/M Emulator 'ePC-9801E'
4 NEC PC-9801U Emulator 'ePC-9801U'
5 NEC PC-9801VF Emulator 'ePC-9801VF'
6 NEC PC-9801VM Emulator 'ePC-9801VM'
7 NEC PC-9801VX Emulator 'ePC-9801VX'
8 NEC PC-9801RA Emulator 'ePC-9801RA'
9 NEC PC-98XA Emulator 'ePC-98XA'
10 NEC PC-98XL Emulator 'ePC-98XL'
11 NEC PC-98RL Emulator 'ePC-98RL'
12 NEC PC-98DO Emulator 'ePC-98DO'
14 Author : Takeda.Toshiya
21 #include "../../emu.h"
22 #include "../device.h"
25 #if defined(SUPPORT_OLD_BUZZER)
29 #if defined(USE_HARD_DISK)
30 #include "../harddisk.h"
37 #if defined(HAS_I386) || defined(HAS_I486)
39 #elif defined(HAS_I86) || defined(HAS_V30)
46 #include "../memory.h"
49 #if !defined(SUPPORT_OLD_BUZZER)
50 #include "../pcm1bit.h"
52 //#include "../pcpr201.h"
53 #include "../prnfile.h"
54 #if defined(SUPPORT_SASI_IF) || defined(SUPPORT_SCSI_IF)
55 #include "../scsi_hdd.h"
56 #include "../scsi_host.h"
58 #include "../tms3631.h"
59 #include "../upd1990a.h"
60 #include "../upd7220.h"
61 #include "../upd765a.h"
62 #include "../ym2203.h"
65 #include "../debugger.h"
68 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
79 #if defined(SUPPORT_SASI_IF)
81 #include "sasi_bios.h"
83 #if defined(SUPPORT_SCSI_IF)
86 #if defined(SUPPORT_IDE_IF)
90 #if defined(SUPPORT_CMT_IF)
93 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
96 using PC9801::DISPLAY;
99 using PC9801::FMSOUND;
100 using PC9801::JOYSTICK;
101 using PC9801::KEYBOARD;
102 using PC9801::MEMBUS;
104 #if defined(SUPPORT_SASI_IF)
108 #if defined(SUPPORT_SCSI_IF)
111 #if defined(SUPPORT_IDE_IF)
115 #if defined(SUPPORT_320KB_FDD_IF)
116 #include "../pc80s31k.h"
119 #if defined(SUPPORT_CMT_IF)
123 #if defined(_PC98DO) || defined(_PC98DOPLUS)
124 #include "../pc80s31k.h"
126 #include "../pc8801/pc88.h"
129 #if defined(_PC98DO) || defined(_PC98DOPLUS)
132 // ----------------------------------------------------------------------------
134 // ----------------------------------------------------------------------------
136 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
139 #if defined(_PC98DO) || defined(_PC98DOPLUS)
140 boot_mode = config.boot_mode;
142 int cpu_clocks = CPU_CLOCKS;
143 #if defined(PIT_CLOCK_8MHZ)
144 pit_clock_8mhz = true;
146 pit_clock_8mhz = false;
148 #if defined(_PC9801E)
149 if(config.cpu_type != 0) {
151 cpu_clocks = 4992030;
152 pit_clock_8mhz = false;
154 #elif defined(_PC9801VM) || defined(_PC98DO) || defined(_PC98DOPLUS) || defined(_PC9801VX) || defined(_PC98XL)
155 if(config.cpu_type != 0) {
156 // 10MHz/16MHz -> 8MHz
157 cpu_clocks = 7987248;
158 pit_clock_8mhz = true;
160 #elif defined(_PC9801RA) || defined(_PC98RL)
161 if(config.cpu_type != 0) {
163 cpu_clocks = 15974496;
164 pit_clock_8mhz = true;
167 int pit_clocks = pit_clock_8mhz ? 1996812 : 2457600;
169 sound_type = config.sound_type;
172 first_device = last_device = NULL;
173 dummy = new DEVICE(this, emu); // must be 1st device
174 event = new EVENT(this, emu); // must be 2nd device
176 #if defined(SUPPORT_OLD_BUZZER)
177 beep = new BEEP(this, emu);
179 beep = new PCM1BIT(this, emu);
181 dma = new I8237(this, emu);
183 dma->set_context_debugger(new DEBUGGER(this, emu));
185 #if defined(SUPPORT_CMT_IF)
186 sio_cmt = new I8251(this, emu); // for cmt
187 sio_cmt->set_device_name(_T("8251 SIO (CMT)"));
189 sio_rs = new I8251(this, emu); // for rs232c
190 sio_rs->set_device_name(_T("8251 SIO (RS-232C)"));
191 sio_kbd = new I8251(this, emu); // for keyboard
192 sio_kbd->set_device_name(_T("8251 SIO (Keyboard)"));
193 pit = new I8253(this, emu);
194 #if defined(SUPPORT_320KB_FDD_IF)
195 pio_fdd = new I8255(this, emu); // for 320kb fdd i/f
196 pio_fdd->set_device_name(_T("8255 PIO (320KB I/F)"));
198 pio_mouse = new I8255(this, emu); // for mouse
199 pio_mouse->set_device_name(_T("8255 PIO (Mouse)"));
200 pio_sys = new I8255(this, emu); // for system port
201 pio_sys->set_device_name(_T("8255 PIO (System)"));
202 pio_prn = new I8255(this, emu); // for printer
203 pio_prn->set_device_name(_T("8255 PIO (Printer)"));
204 pic = new I8259(this, emu);
205 #if defined(HAS_I386) || defined(HAS_I486)
206 cpu = new I386(this, emu); // 80386, 80486
207 #elif defined(HAS_I86) || defined(HAS_V30)
208 cpu = new I286(this, emu);// 8086, V30, 80286
210 cpu = new I286(this, emu);
213 cpu->set_device_name(_T("CPU(i8086)"));
214 #elif defined(HAS_I386)
215 cpu->set_device_name(_T("CPU(i386)"));
216 #elif defined(HAS_I486)
217 cpu->set_device_name(_T("CPU(i486)"));
218 #elif defined(HAS_PENTIUM)
219 cpu->set_device_name(_T("CPU(Pentium)"));
220 #elif defined(HAS_V33A)
221 cpu->set_device_name(_T("CPU(V33A)"));
222 #elif defined(HAS_V30)
223 cpu->set_device_name(_T("CPU(V30)"));
225 cpu->set_device_name(_T("CPU(i286)"));
227 io = new IO(this, emu);
228 rtcreg = new LS244(this, emu);
229 rtcreg->set_device_name(_T("74LS244 (RTC)"));
230 //memory = new MEMORY(this, emu);
231 memory = new MEMBUS(this, emu);
232 not_busy = new NOT(this, emu);
233 not_busy->set_device_name(_T("NOT Gate (Printer Busy)"));
234 #if defined(HAS_I86) || defined(HAS_V30)
235 not_prn = new NOT(this, emu);
236 not_prn->set_device_name(_T("NOT Gate (Printer IRQ)"));
238 rtc = new UPD1990A(this, emu);
239 #if defined(SUPPORT_2HD_FDD_IF)
240 fdc_2hd = new UPD765A(this, emu);
241 fdc_2hd->set_device_name(_T("uPD765A FDC (2HD I/F)"));
243 #if defined(SUPPORT_2DD_FDD_IF)
244 fdc_2dd = new UPD765A(this, emu);
245 fdc_2dd->set_device_name(_T("uPD765A FDC (2DD I/F)"));
247 #if defined(SUPPORT_2HD_2DD_FDD_IF)
248 fdc = new UPD765A(this, emu);
249 fdc->set_device_name(_T("uPD765A FDC (2HD/2DD I/F)"));
251 noise_seek = new NOISE(this, emu);
252 noise_head_down = new NOISE(this, emu);
253 noise_head_up = new NOISE(this, emu);
254 #if defined(SUPPORT_SASI_IF)
255 sasi_host = new SCSI_HOST(this, emu);
256 sasi_hdd = new SASI_HDD(this, emu);
257 sasi_hdd->set_device_name(_T("SASI Hard Disk Drive"));
258 sasi_hdd->scsi_id = 0;
259 sasi_hdd->bytes_per_sec = 625 * 1024; // 625KB/s
260 for(int i = 0; i < USE_HARD_DISK; i++) {
261 sasi_hdd->set_disk_handler(i, new HARDDISK(emu));
263 sasi_hdd->set_context_interface(sasi_host);
264 sasi_host->set_context_target(sasi_hdd);
266 #if defined(SUPPORT_SCSI_IF)
267 scsi_host = new SCSI_HOST(this, emu);
268 for(int i = 0; i < USE_HARD_DISK; i++) {
269 scsi_hdd[i] = new SCSI_HDD(this, emu);
270 scsi_hdd[i]->set_device_name(_T("SCSI Hard Disk Drive #%d"), i + 1);
271 scsi_hdd[i]->scsi_id = i;
272 scsi_hdd[i]->set_disk_handler(0, new HARDDISK(emu));
273 scsi_hdd[i]->set_context_interface(scsi_host);
274 scsi_host->set_context_target(scsi_hdd[i]);
277 gdc_chr = new UPD7220(this, emu);
278 gdc_chr->set_device_name(_T("uPD7220 GDC (Character)"));
279 gdc_gfx = new UPD7220(this, emu);
280 gdc_gfx->set_device_name(_T("uPD7220 GDC (Graphics)"));
282 if(sound_type == 0 || sound_type == 1) {
283 opn = new YM2203(this, emu);
285 opn->set_context_debugger(new DEBUGGER(this, emu));
287 #ifdef SUPPORT_PC98_OPNA
288 opn->set_device_name(_T("YM2608 OPNA (PC-9801-86)"));
289 opn->is_ym2608 = true;
291 opn->set_device_name(_T("YM2203 OPN (PC-9801-26)"));
292 opn->is_ym2608 = false;
294 fmsound = new FMSOUND(this, emu);
295 joystick = new JOYSTICK(this, emu);
296 } else if(sound_type == 2 || sound_type == 3) {
297 tms3631 = new TMS3631(this, emu);
298 tms3631->set_device_name(_T("TMS3631 SSG (PC-9801-14)"));
299 pit_14 = new I8253(this, emu);
300 pit_14->set_device_name(_T("8253 PIT (PC-9801-14)"));
301 pio_14 = new I8255(this, emu);
302 pio_14->set_device_name(_T("8255 PIO (PC-9801-14)"));
303 maskreg_14 = new LS244(this, emu);
304 maskreg_14->set_device_name(_T("74LS244 (PC-9801-14)"));
306 if(config.printer_type == 0) {
307 printer = new PRNFILE(this, emu);
308 // } else if(config.printer_type == 1) {
309 // printer = new PCPR201(this, emu);
314 #if defined(SUPPORT_CMT_IF)
315 cmt = new CMT(this, emu);
317 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
318 cpureg = new CPUREG(this, emu);
320 display = new DISPLAY(this, emu);
321 dmareg = new DMAREG(this, emu);
322 floppy = new FLOPPY(this, emu);
323 keyboard = new KEYBOARD(this, emu);
324 mouse = new MOUSE(this, emu);
325 #if defined(SUPPORT_SASI_IF)
326 sasi = new SASI(this, emu);
327 sasi_bios = new BIOS(this, emu);
329 #if defined(SUPPORT_SCSI_IF)
330 scsi = new SCSI(this, emu);
332 #if defined(SUPPORT_IDE_IF)
333 ide = new IDE(this, emu);
336 #if defined(SUPPORT_320KB_FDD_IF)
338 pio_sub = new I8255(this, emu);
339 pio_sub->set_device_name(_T("8255 PIO (320KB FDD)"));
340 pc80s31k = new PC80S31K(this, emu);
341 pc80s31k->set_device_name(_T("PC-80S31K (320KB FDD)"));
342 fdc_sub = new UPD765A(this, emu);
343 fdc_sub->set_device_name(_T("uPD765A FDC (320KB FDD)"));
344 cpu_sub = new Z80(this, emu);
345 cpu_sub->set_device_name(_T("Z80 CPU (320KB FDD)"));
357 9 (INT3) PC-9801-27 (SASI), PC-9801-55 (SCSI), or IDE
358 10 (INT41) FDC (640KB I/F)
359 11 (INT42) FDC (1MB I/F)
360 12 (INT5) PC-9801-26(K) or PC-9801-14
367 event->set_context_cpu(cpu, cpu_clocks);
368 #if defined(SUPPORT_320KB_FDD_IF)
369 event->set_context_cpu(cpu_sub, 4000000);
371 event->set_context_sound(beep);
372 if(sound_type == 0 || sound_type == 1) {
373 event->set_context_sound(opn);
374 } else if(sound_type == 2 || sound_type == 3) {
375 event->set_context_sound(tms3631);
377 event->set_context_sound(noise_seek);
378 event->set_context_sound(noise_head_down);
379 event->set_context_sound(noise_head_up);
381 dma->set_context_memory(memory);
383 // dma ch.1: memory refresh
384 #if defined(SUPPORT_2HD_FDD_IF)
385 dma->set_context_ch2(fdc_2hd);
386 dma->set_context_tc2(fdc_2hd, SIG_UPD765A_TC, 1);
388 #if defined(SUPPORT_2DD_FDD_IF)
389 dma->set_context_ch3(fdc_2dd);
390 dma->set_context_tc3(fdc_2dd, SIG_UPD765A_TC, 1);
392 #if defined(SUPPORT_2HD_2DD_FDD_IF)
393 #if !defined(SUPPORT_HIRESO)
394 dma->set_context_ch2(fdc);
395 dma->set_context_ch3(fdc);
396 dma->set_context_tc2(fdc, SIG_UPD765A_TC, 1);
397 dma->set_context_tc3(fdc, SIG_UPD765A_TC, 1);
399 dma->set_context_ch1(fdc);
400 dma->set_context_tc1(fdc, SIG_UPD765A_TC, 1);
403 // sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
404 sio_kbd->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 1);
405 pit->set_context_ch0(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 1);
406 #if defined(SUPPORT_OLD_BUZZER)
407 // pit ch.1: memory refresh
410 pit->set_context_ch1(beep, SIG_PCM1BIT_SIGNAL, 1);
413 pit->set_constant_clock(0, pit_clocks);
414 pit->set_constant_clock(1, pit_clocks);
415 pit->set_constant_clock(2, pit_clocks);
416 pio_mouse->set_context_port_c(mouse, SIG_MOUSE_PORT_C, 0xf0, 0);
417 #if defined(SUPPORT_HIRESO)
418 // sysport port.c bit7,5: sysport port.b bit4,3
419 pio_sys->set_context_port_c(pio_sys, SIG_I8255_PORT_B, 0x80, -3); // SHUT0
420 pio_sys->set_context_port_c(pio_sys, SIG_I8255_PORT_B, 0x20, -2); // SHUT1
422 // sysport port.c bit6: printer strobe
423 #if defined(SUPPORT_OLD_BUZZER)
424 pio_sys->set_context_port_c(beep, SIG_BEEP_MUTE, 0x08, 0);
426 pio_sys->set_context_port_c(beep, SIG_PCM1BIT_MUTE, 0x08, 0);
428 // sysport port.c bit2: enable txrdy interrupt
429 // sysport port.c bit1: enable txempty interrupt
430 // sysport port.c bit0: enable rxrdy interrupt
431 pio_prn->set_context_port_a(printer, SIG_PRINTER_DATA, 0xff, 0);
432 pio_prn->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x80, 0);
433 if(config.printer_type == 0) {
434 PRNFILE *prnfile = (PRNFILE *)printer;
435 prnfile->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
436 // } else if(config.printer_type == 1) {
437 // PRNFILE *pcpr201 = (PCPR201 *)printer;
438 // pcpr201->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
440 not_busy->set_context_out(pio_prn, SIG_I8255_PORT_B, 4);
441 #if defined(HAS_I86) || defined(HAS_V30)
442 pio_prn->set_context_port_c(not_prn, SIG_NOT_INPUT, 8, 0);
443 not_prn->set_context_out(pic, SIG_I8259_CHIP1 | SIG_I8259_IR0, 1);
445 rtcreg->set_context_output(rtc, SIG_UPD1990A_CMD, 0x07, 0);
446 rtcreg->set_context_output(rtc, SIG_UPD1990A_DIN, 0x20, 0);
447 rtcreg->set_context_output(rtc, SIG_UPD1990A_STB, 0x08, 0);
448 rtcreg->set_context_output(rtc, SIG_UPD1990A_CLK, 0x10, 0);
449 pic->set_context_cpu(cpu);
450 rtc->set_context_dout(pio_sys, SIG_I8255_PORT_B, 1);
452 if(sound_type == 0 || sound_type == 1) {
453 opn->set_context_irq(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
454 opn->set_context_port_b(joystick, SIG_JOYSTICK_SELECT, 0xc0, 0);
455 fmsound->set_context_opn(opn);
456 joystick->set_context_opn(opn);
457 } else if(sound_type == 2 || sound_type == 3) {
458 pio_14->set_context_port_a(tms3631, SIG_TMS3631_ENVELOP1, 0xff, 0);
459 pio_14->set_context_port_b(tms3631, SIG_TMS3631_ENVELOP2, 0xff, 0);
460 pio_14->set_context_port_c(tms3631, SIG_TMS3631_DATAREG, 0xff, 0);
461 maskreg_14->set_context_output(tms3631, SIG_TMS3631_MASKREG, 0xff, 0);
462 pit_14->set_constant_clock(2, 1996800 / 8);
463 pit_14->set_context_ch2(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
466 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
467 cpureg->set_context_cpu(cpu);
469 display->set_context_pic(pic);
470 display->set_context_gdc_chr(gdc_chr, gdc_chr->get_ra());
471 display->set_context_gdc_gfx(gdc_gfx, gdc_gfx->get_ra(), gdc_gfx->get_cs());
472 dmareg->set_context_dma(dma);
473 keyboard->set_context_sio(sio_kbd);
474 memory->set_context_display(display);
475 mouse->set_context_pic(pic);
476 mouse->set_context_pio(pio_mouse);
478 #if defined(SUPPORT_2HD_FDD_IF)
479 fdc_2hd->set_context_irq(floppy, SIG_FLOPPY_2HD_IRQ, 1);
480 fdc_2hd->set_context_drq(floppy, SIG_FLOPPY_2HD_DRQ, 1);
481 fdc_2hd->set_context_noise_seek(noise_seek);
482 fdc_2hd->set_context_noise_head_down(noise_head_down);
483 fdc_2hd->set_context_noise_head_up(noise_head_up);
484 fdc_2hd->raise_irq_when_media_changed = true;
485 floppy->set_context_fdc_2hd(fdc_2hd);
487 #if defined(SUPPORT_2DD_FDD_IF)
488 fdc_2dd->set_context_irq(floppy, SIG_FLOPPY_2DD_IRQ, 1);
489 fdc_2dd->set_context_drq(floppy, SIG_FLOPPY_2DD_DRQ, 1);
490 fdc_2dd->set_context_noise_seek(noise_seek);
491 fdc_2dd->set_context_noise_head_down(noise_head_down);
492 fdc_2dd->set_context_noise_head_up(noise_head_up);
493 fdc_2dd->raise_irq_when_media_changed = true;
494 floppy->set_context_fdc_2dd(fdc_2dd);
496 #if defined(SUPPORT_2HD_2DD_FDD_IF)
497 fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
498 fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
499 fdc->set_context_noise_seek(noise_seek);
500 fdc->set_context_noise_head_down(noise_head_down);
501 fdc->set_context_noise_head_up(noise_head_up);
502 fdc->raise_irq_when_media_changed = true;
503 floppy->set_context_fdc(fdc);
505 floppy->set_context_dma(dma);
506 floppy->set_context_pic(pic);
508 #if defined(SUPPORT_SASI_IF)
509 #if !defined(SUPPORT_HIRESO)
510 sasi_host->set_context_irq(pio_sys, SIG_I8255_PORT_B, 0x10);
512 sasi_host->set_context_irq(sasi, SIG_SASI_IRQ, 1);
513 sasi_host->set_context_drq(sasi, SIG_SASI_DRQ, 1);
515 dma->set_context_ch3(sasi_host);
516 dma->set_context_tc3(sasi, SIG_SASI_TC, 1);
518 dma->set_context_ch0(sasi_host);
519 dma->set_context_tc0(sasi, SIG_SASI_TC, 1);
521 sasi->set_context_host(sasi_host);
522 sasi->set_context_hdd(sasi_hdd);
523 sasi->set_context_dma(dma);
524 sasi->set_context_pic(pic);
526 sasi_bios->set_context_sasi(sasi);
527 sasi_bios->set_context_memory(memory);
528 sasi_bios->set_context_cpu(cpu);
529 sasi_bios->set_context_pic(pic);
530 cpu->set_context_bios(sasi_bios);
533 #if defined(SUPPORT_SCSI_IF)
534 dma->set_context_ch0(scsi);
535 scsi->set_context_dma(dma);
536 scsi->set_context_pic(pic);
538 #if defined(SUPPORT_IDE_IF)
539 dma->set_context_ch0(ide);
540 ide->set_context_dma(dma);
541 ide->set_context_pic(pic);
544 #if defined(SUPPORT_CMT_IF)
545 sio_cmt->set_context_out(cmt, SIG_CMT_OUT);
546 // sio_cmt->set_context_txrdy(cmt, SIG_CMT_TXRDY, 1);
547 // sio_cmt->set_context_rxrdy(cmt, SIG_CMT_RXRDY, 1);
548 // sio_cmt->set_context_txe(cmt, SIG_CMT_TXEMP, 1);
549 cmt->set_context_sio(sio_cmt);
553 cpu->set_context_mem(memory);
554 cpu->set_context_io(io);
555 cpu->set_context_intr(pic);
556 #ifdef SINGLE_MODE_DMA
557 cpu->set_context_dma(dma);
560 cpu->set_context_debugger(new DEBUGGER(this, emu));
563 #if defined(SUPPORT_320KB_FDD_IF)
565 pc80s31k->set_context_cpu(cpu_sub);
566 pc80s31k->set_context_fdc(fdc_sub);
567 pc80s31k->set_context_pio(pio_sub);
568 pio_fdd->set_context_port_a(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
569 pio_fdd->set_context_port_b(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
570 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
571 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
572 pio_fdd->clear_ports_by_cmdreg = true;
573 pio_sub->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
574 pio_sub->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
575 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
576 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
577 pio_sub->clear_ports_by_cmdreg = true;
578 fdc_sub->set_context_irq(cpu_sub, SIG_CPU_IRQ, 1);
579 fdc_sub->set_context_noise_seek(noise_seek);
580 fdc_sub->set_context_noise_head_down(noise_head_down);
581 fdc_sub->set_context_noise_head_up(noise_head_up);
582 cpu_sub->set_context_mem(pc80s31k);
583 cpu_sub->set_context_io(pc80s31k);
584 cpu_sub->set_context_intr(pc80s31k);
586 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
591 io->set_iomap_alias_rw(0x0000, pic, 0);
592 io->set_iomap_alias_rw(0x0002, pic, 1);
593 io->set_iomap_alias_rw(0x0008, pic, 2);
594 io->set_iomap_alias_rw(0x000a, pic, 3);
596 io->set_iomap_alias_rw(0x0001, dma, 0x00);
597 io->set_iomap_alias_rw(0x0003, dma, 0x01);
598 io->set_iomap_alias_rw(0x0005, dma, 0x02);
599 io->set_iomap_alias_rw(0x0007, dma, 0x03);
600 io->set_iomap_alias_rw(0x0009, dma, 0x04);
601 io->set_iomap_alias_rw(0x000b, dma, 0x05);
602 io->set_iomap_alias_rw(0x000d, dma, 0x06);
603 io->set_iomap_alias_rw(0x000f, dma, 0x07);
604 io->set_iomap_alias_rw(0x0011, dma, 0x08);
605 io->set_iomap_alias_w (0x0013, dma, 0x09);
606 io->set_iomap_alias_w (0x0015, dma, 0x0a);
607 io->set_iomap_alias_w (0x0017, dma, 0x0b);
608 io->set_iomap_alias_w (0x0019, dma, 0x0c);
609 io->set_iomap_alias_rw(0x001b, dma, 0x0d);
610 io->set_iomap_alias_w (0x001d, dma, 0x0e);
611 io->set_iomap_alias_w (0x001f, dma, 0x0f);
612 io->set_iomap_single_w(0x0021, dmareg);
613 io->set_iomap_single_w(0x0023, dmareg);
614 io->set_iomap_single_w(0x0025, dmareg);
615 io->set_iomap_single_w(0x0027, dmareg);
616 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
617 io->set_iomap_single_w(0x0029, dmareg);
619 #if defined(SUPPORT_32BIT_ADDRESS)
620 io->set_iomap_single_w(0x0e05, dmareg);
621 io->set_iomap_single_w(0x0e07, dmareg);
622 io->set_iomap_single_w(0x0e09, dmareg);
623 io->set_iomap_single_w(0x0e0b, dmareg);
626 io->set_iomap_single_w(0x0020, rtcreg);
628 io->set_iomap_alias_rw(0x0030, sio_rs, 0);
629 io->set_iomap_alias_rw(0x0032, sio_rs, 1);
631 io->set_iomap_alias_rw(0x0031, pio_sys, 0);
632 io->set_iomap_alias_rw(0x0033, pio_sys, 1);
633 io->set_iomap_alias_rw(0x0035, pio_sys, 2);
634 io->set_iomap_alias_w (0x0037, pio_sys, 3);
636 io->set_iomap_alias_rw(0x0040, pio_prn, 0);
637 io->set_iomap_alias_rw(0x0042, pio_prn, 1);
638 io->set_iomap_alias_rw(0x0044, pio_prn, 2);
639 io->set_iomap_alias_w (0x0046, pio_prn, 3);
641 io->set_iomap_alias_rw(0x0041, sio_kbd, 0);
642 io->set_iomap_alias_rw(0x0043, sio_kbd, 1);
644 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
645 io->set_iomap_single_w(0x0050, cpureg);
646 io->set_iomap_single_w(0x0052, cpureg);
649 #if defined(SUPPORT_320KB_FDD_IF)
650 io->set_iomap_alias_rw(0x0051, pio_fdd, 0);
651 io->set_iomap_alias_rw(0x0053, pio_fdd, 1);
652 io->set_iomap_alias_rw(0x0055, pio_fdd, 2);
653 io->set_iomap_alias_w (0x0057, pio_fdd, 3);
656 io->set_iomap_alias_rw(0x0060, gdc_chr, 0);
657 io->set_iomap_alias_rw(0x0062, gdc_chr, 1);
659 io->set_iomap_single_w(0x64, display);
660 io->set_iomap_single_w(0x68, display);
661 #if defined(SUPPORT_16_COLORS)
662 io->set_iomap_single_w(0x6a, display);
664 io->set_iomap_single_w(0x6c, display);
665 io->set_iomap_single_w(0x6e, display);
667 io->set_iomap_single_w(0x70, display);
668 io->set_iomap_single_w(0x72, display);
669 io->set_iomap_single_w(0x74, display);
670 io->set_iomap_single_w(0x76, display);
671 io->set_iomap_single_w(0x78, display);
672 io->set_iomap_single_w(0x7a, display);
673 #if defined(SUPPORT_GRCG)
674 #if !defined(SUPPORT_HIRESO)
675 io->set_iomap_single_w(0x007c, display);
676 io->set_iomap_single_w(0x007e, display);
678 io->set_iomap_single_w(0x00a4, display);
679 io->set_iomap_single_w(0x00a6, display);
683 #if defined(SUPPORT_SASI_IF)
684 io->set_iomap_single_rw(0x0080, sasi);
685 io->set_iomap_single_rw(0x0082, sasi);
687 #if defined(SUPPORT_SCSI_IF)
688 io->set_iomap_single_rw(0x0cc0, scsi);
689 io->set_iomap_single_rw(0x0cc2, scsi);
690 io->set_iomap_single_rw(0x0cc4, scsi);
692 #if defined(SUPPORT_IDE_IF)
693 io->set_iomap_single_rw(0x0640, ide);
694 io->set_iomap_single_rw(0x0642, ide);
695 io->set_iomap_single_rw(0x0644, ide);
696 io->set_iomap_single_rw(0x0646, ide);
697 io->set_iomap_single_rw(0x0648, ide);
698 io->set_iomap_single_rw(0x064a, ide);
699 io->set_iomap_single_rw(0x064c, ide);
700 io->set_iomap_single_rw(0x064e, ide);
701 io->set_iomap_single_rw(0x074c, ide);
702 io->set_iomap_single_rw(0x074e, ide);
705 io->set_iomap_alias_rw(0x00a0, gdc_gfx, 0);
706 io->set_iomap_alias_rw(0x00a2, gdc_gfx, 1);
708 #if defined(SUPPORT_2ND_VRAM) && !defined(SUPPORT_HIRESO)
709 io->set_iomap_single_rw(0x00a4, display);
710 io->set_iomap_single_rw(0x00a6, display);
712 io->set_iomap_single_rw(0xa8, display);
713 io->set_iomap_single_rw(0xaa, display);
714 io->set_iomap_single_rw(0xac, display);
715 io->set_iomap_single_rw(0xae, display);
717 // io->set_iomap_single_w(0xa1, display);
718 // io->set_iomap_single_w(0xa3, display);
719 // io->set_iomap_single_w(0xa5, display);
720 io->set_iomap_single_rw(0xa1, display);
721 io->set_iomap_single_rw(0xa3, display);
722 io->set_iomap_single_rw(0xa5, display);
723 io->set_iomap_single_rw(0xa9, display);
724 #if defined(SUPPORT_EGC)
725 io->set_iomap_range_rw(0x04a0, 0x04af, display);
728 io->set_iomap_alias_rw(0x0071, pit, 0);
729 io->set_iomap_alias_rw(0x0073, pit, 1);
730 io->set_iomap_alias_rw(0x0075, pit, 2);
731 io->set_iomap_alias_w (0x0077, pit, 3);
733 io->set_iomap_single_rw(0x0090, floppy);
734 io->set_iomap_single_rw(0x0092, floppy);
735 io->set_iomap_single_rw(0x0094, floppy);
736 io->set_iomap_single_rw(0x0096, floppy);
737 #if defined(SUPPORT_2HD_2DD_FDD_IF)
738 #if !defined(SUPPORT_HIRESO)
739 io->set_iomap_single_rw(0x00be, floppy);
741 //#if !defined(_PC98XA) && !defined(_PC98XL)
742 io->set_iomap_single_w (0x00be, floppy);
746 #if !defined(SUPPORT_HIRESO)
747 io->set_iomap_single_rw(0x00c8, floppy);
748 io->set_iomap_single_rw(0x00ca, floppy);
749 io->set_iomap_single_rw(0x00cc, floppy);
750 io->set_iomap_single_rw(0x00ce, floppy);
753 #if defined(SUPPORT_CMT_IF)
754 io->set_iomap_alias_rw(0x0091, sio_cmt, 0);
755 io->set_iomap_alias_rw(0x0093, sio_cmt, 1);
756 io->set_iomap_single_w(0x0095, cmt);
757 io->set_iomap_single_w(0x0097, cmt);
760 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
761 io->set_iomap_single_rw(0x00f0, cpureg);
762 io->set_iomap_single_rw(0x00f2, cpureg);
764 #if defined(SUPPORT_32BIT_ADDRESS)
765 io->set_iomap_single_rw(0x00f6, cpureg);
768 if(sound_type == 0 || sound_type == 1) {
769 io->set_iomap_single_rw(0x0188, fmsound);
770 io->set_iomap_single_rw(0x018a, fmsound);
771 #ifdef SUPPORT_PC98_OPNA
772 io->set_iomap_single_rw(0x018c, fmsound);
773 io->set_iomap_single_rw(0x018e, fmsound);
774 io->set_iomap_single_rw(0xa460, fmsound);
776 } else if(sound_type == 2 || sound_type == 3) {
777 io->set_iomap_alias_rw(0x0088, pio_14, 0);
778 io->set_iomap_alias_rw(0x008a, pio_14, 1);
779 io->set_iomap_alias_rw(0x008c, pio_14, 2);
780 io->set_iomap_alias_w(0x008e, pio_14, 3);
781 io->set_iovalue_single_r(0x008e, 0x08);
782 io->set_iomap_single_w(0x0188, maskreg_14);
783 io->set_iomap_single_w(0x018a, maskreg_14);
784 io->set_iomap_alias_rw(0x018c, pit_14, 2);
785 io->set_iomap_alias_w(0x018e, pit_14, 3);
786 // io->set_iovalue_single_r(0x018e, 0x00); // INT0
787 // io->set_iovalue_single_r(0x018e, 0x40); // INT41
788 io->set_iovalue_single_r(0x018e, 0x80); // INT5
789 // io->set_iovalue_single_r(0x018e, 0xc0); // INT6
792 //#if !defined(SUPPORT_HIRESO)
793 // io->set_iovalue_single_r(0x0431, 0x04); // bit2: 1 = Normal mode, 0 = Hireso mode
795 // io->set_iovalue_single_r(0x0431, 0x00);
797 #if defined(SUPPORT_ITF_ROM)
798 io->set_iomap_single_w(0x043d, memory);
800 #if !defined(SUPPORT_HIRESO)
801 io->set_iomap_single_w(0x043f, memory);
803 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
804 #if !defined(_PC98XA)
805 io->set_iomap_single_rw(0x0439, memory);
807 #if !defined(SUPPORT_HIRESO)
808 io->set_iomap_single_rw(0x0461, memory);
809 io->set_iomap_single_rw(0x0463, memory);
811 io->set_iomap_single_rw(0x0091, memory);
812 io->set_iomap_single_rw(0x0093, memory);
814 io->set_iomap_single_r(0x0567, memory);
816 #if defined(SUPPORT_32BIT_ADDRESS)
817 io->set_iomap_single_w(0x053d, memory);
820 #if !(defined(_PC9801) || defined(_PC9801E) || defined(SUPPORT_HIRESO))
821 io->set_iomap_alias_rw(0x3fd9, pit, 0);
822 io->set_iomap_alias_rw(0x3fdb, pit, 1);
823 io->set_iomap_alias_rw(0x3fdd, pit, 2);
824 io->set_iomap_alias_w (0x3fdf, pit, 3);
827 #if !defined(SUPPORT_HIRESO)
828 io->set_iomap_alias_rw(0x7fd9, pio_mouse, 0);
829 io->set_iomap_alias_rw(0x7fdb, pio_mouse, 1);
830 io->set_iomap_alias_rw(0x7fdd, pio_mouse, 2);
831 io->set_iomap_alias_w (0x7fdf, pio_mouse, 3);
832 io->set_iomap_single_rw(0xbfdb, mouse);
834 io->set_iomap_alias_rw(0x0061, pio_mouse, 0);
835 io->set_iomap_alias_rw(0x0063, pio_mouse, 1);
836 io->set_iomap_alias_rw(0x0065, pio_mouse, 2);
837 io->set_iomap_alias_rw(0x0067, pio_mouse, 3);
840 #if defined(_PC98DO) || defined(_PC98DOPLUS)
841 pc88event = new EVENT(this, emu);
842 pc88event->set_device_name(_T("Event Manager (PC-8801)"));
843 pc88event->set_frames_per_sec(60);
844 pc88event->set_lines_per_frame(260);
846 pc88 = new PC88(this, emu);
847 pc88->set_context_event_manager(pc88event);
848 pc88sio = new I8251(this, emu);
849 pc88sio->set_device_name(_T("8251 SIO (PC-8801)"));
850 pc88sio->set_context_event_manager(pc88event);
851 pc88pio = new I8255(this, emu);
852 pc88pio->set_device_name(_T("8255 PIO (PC-8801)"));
853 pc88pio->set_context_event_manager(pc88event);
854 pc88pcm = new PCM1BIT(this, emu);
855 pc88pcm->set_device_name(_T("1-Bit PCM Sound (PC-8801)"));
856 pc88pcm->set_context_event_manager(pc88event);
857 pc88rtc = new UPD1990A(this, emu);
858 pc88rtc->set_device_name(_T("uPD1990A RTC (PC-8801)"));
859 pc88rtc->set_context_event_manager(pc88event);
860 pc88opn1 = new YM2203(this, emu);
862 pc88opn1->set_context_debugger(new DEBUGGER(this, emu));
864 #ifdef SUPPORT_PC88_OPNA
865 pc88opn1->set_device_name(_T("YM2608 OPNA (PC-8801)"));
866 pc88opn1->is_ym2608 = true;
868 pc88opn1->set_device_name(_T("YM2203 OPN (PC-8801)"));
869 pc88opn1->is_ym2608 = false;
871 pc88opn1->set_context_event_manager(pc88event);
872 pc88cpu = new Z80(this, emu);
873 pc88cpu->set_device_name(_T("Z80 CPU (PC-8801)"));
874 pc88cpu->set_context_event_manager(pc88event);
876 if(config.printer_type == 0) {
877 pc88prn = new PRNFILE(this, emu);
878 pc88prn->set_context_event_manager(pc88event);
879 // } else if(config.printer_type == 1) {
880 // pc88prn = new PCPR201(this, emu);
881 // pc88prn->set_context_event_manager(pc88event);
886 pc88sub = new PC80S31K(this, emu);
887 pc88sub->set_device_name(_T("PC-80S31K (PC-8801 Sub)"));
888 pc88sub->set_context_event_manager(pc88event);
889 pc88pio_sub = new I8255(this, emu);
890 pc88pio_sub->set_device_name(_T("8255 PIO (PC-8801 Sub)"));
891 pc88pio_sub->set_context_event_manager(pc88event);
892 pc88fdc_sub = new UPD765A(this, emu);
893 pc88fdc_sub->set_device_name(_T("uPD765A FDC (PC-8801 Sub)"));
894 pc88fdc_sub->set_context_event_manager(pc88event);
895 pc88noise_seek = new NOISE(this, emu);
896 pc88noise_seek->set_context_event_manager(pc88event);
897 pc88noise_head_down = new NOISE(this, emu);
898 pc88noise_head_down->set_context_event_manager(pc88event);
899 pc88noise_head_up = new NOISE(this, emu);
900 pc88noise_head_up->set_context_event_manager(pc88event);
901 pc88cpu_sub = new Z80(this, emu);
902 pc88cpu_sub->set_device_name(_T("Z80 CPU (PC-8801 Sub)"));
903 pc88cpu_sub->set_context_event_manager(pc88event);
905 pc88event->set_context_cpu(pc88cpu, (config.cpu_type == 1) ? 3993624 : 7987248);
906 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
907 pc88event->set_context_sound(pc88opn1);
908 pc88event->set_context_sound(pc88pcm);
909 pc88event->set_context_sound(pc88noise_seek);
910 pc88event->set_context_sound(pc88noise_head_down);
911 pc88event->set_context_sound(pc88noise_head_up);
913 pc88->set_context_cpu(pc88cpu);
914 pc88->set_context_opn1(pc88opn1);
915 pc88->set_context_pcm(pc88pcm);
916 pc88->set_context_pio(pc88pio);
917 pc88->set_context_prn(pc88prn);
918 pc88->set_context_rtc(pc88rtc);
919 pc88->set_context_sio(pc88sio);
920 pc88cpu->set_context_mem(pc88);
921 pc88cpu->set_context_io(pc88);
922 pc88cpu->set_context_intr(pc88);
924 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
926 pc88opn1->set_context_irq(pc88, SIG_PC88_OPN1_IRQ, 1);
927 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
928 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
930 pc88sub->set_context_cpu(pc88cpu_sub);
931 pc88sub->set_context_fdc(pc88fdc_sub);
932 pc88sub->set_context_pio(pc88pio_sub);
933 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
934 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
935 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
936 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
937 pc88pio->clear_ports_by_cmdreg = true;
938 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
939 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
940 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
941 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
942 pc88pio_sub->clear_ports_by_cmdreg = true;
943 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
944 pc88fdc_sub->set_context_noise_seek(pc88noise_seek);
945 pc88fdc_sub->set_context_noise_head_down(pc88noise_head_down);
946 pc88fdc_sub->set_context_noise_head_up(pc88noise_head_up);
947 pc88cpu_sub->set_context_mem(pc88sub);
948 pc88cpu_sub->set_context_io(pc88sub);
949 pc88cpu_sub->set_context_intr(pc88sub);
951 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
955 // initialize all devices
956 #if defined(__GIT_REPO_VERSION)
957 strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
959 for(DEVICE* device = first_device; device; device = device->next_device) {
960 device->initialize();
963 #if defined(_PC9801) || defined(_PC9801E)
964 fdc_2hd->get_disk_handler(0)->drive_num = 0;
965 fdc_2hd->get_disk_handler(1)->drive_num = 1;
966 fdc_2dd->get_disk_handler(0)->drive_num = 2;
967 fdc_2dd->get_disk_handler(1)->drive_num = 3;
968 fdc_sub->get_disk_handler(0)->drive_num = 4;
969 fdc_sub->get_disk_handler(1)->drive_num = 5;
970 #elif defined(_PC9801VF) || defined(_PC9801U)
971 fdc_2dd->get_disk_handler(0)->drive_num = 0;
972 fdc_2dd->get_disk_handler(1)->drive_num = 1;
973 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
974 fdc->get_disk_handler(0)->drive_num = 0;
975 fdc->get_disk_handler(1)->drive_num = 1;
976 pc88fdc_sub->get_disk_handler(0)->drive_num = 2;
977 pc88fdc_sub->get_disk_handler(1)->drive_num = 3;
979 fdc->get_disk_handler(0)->drive_num = 0;
980 fdc->get_disk_handler(1)->drive_num = 1;
982 #if defined(USE_HARD_DISK)
983 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
984 if(!(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv]))) {
985 #if defined(SUPPORT_SASI_IF)
986 create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("SASI%d.DAT"), drv);
988 #if defined(SUPPORT_SCSI_IF)
989 create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("SCSI%d.DAT"), drv);
991 #if defined(SUPPORT_IDE_IF)
992 create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("IDE%d.DAT"), drv);
1001 // delete all devices
1002 for(DEVICE* device = first_device; device;) {
1003 DEVICE *next_device = device->next_device;
1006 device = next_device;
1010 DEVICE* VM::get_device(int id)
1012 for(DEVICE* device = first_device; device; device = device->next_device) {
1013 if(device->this_device_id == id) {
1020 // ----------------------------------------------------------------------------
1021 // drive virtual machine
1022 // ----------------------------------------------------------------------------
1026 // reset all devices
1027 for(DEVICE* device = first_device; device; device = device->next_device) {
1030 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1031 for(DEVICE* device = first_device; device; device = device->next_device) {
1036 // initial device settings
1037 uint8_t port_a, port_b, port_c;
1039 port_a = 0xf0; // Clear mouse buttons and counters
1041 #if defined(_PC98XA)
1042 port_b |= (uint8_t)((RAM_SIZE - 0x100000) / 0x40000);
1044 #if defined(SUPPORT_HIRESO)
1045 port_b |= 0x80; // DIP SW 1-4, 1 = External FDD #3/#4, 0 = #1/#2
1047 port_b |= 0x40; // DIP SW 3-6, 1 = Enable internal RAM 80000h-9FFFFh
1048 #if defined(_PC98RL)
1049 port_b |= 0x10; // DIP SW 3-3, 1 = DMA ch.0 for SASI-HDD
1051 #if defined(USE_CPU_TYPE)
1052 if(config.cpu_type != 0) {
1053 #if !defined(SUPPORT_HIRESO)
1054 port_b |= 0x02; // SPDSW, 1 = 10MHz, 0 = 12MHz
1056 port_b |= 0x01; // SPDSW, 1 = 8/16MHz, 0 = 10/20MHz
1062 #if defined(SUPPORT_HIRESO)
1063 // port_c |= 0x08; // MODSW, 1 = Normal Mode, 0 = Hirezo Mode
1065 #if defined(HAS_V30) || defined(HAS_V33)
1066 port_c |= 0x04; // DIP SW 3-8, 1 = V30, 0 = 80x86
1068 pio_mouse->write_signal(SIG_I8255_PORT_A, port_a, 0xff);
1069 pio_mouse->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1070 pio_mouse->write_signal(SIG_I8255_PORT_C, port_c, 0xff);
1073 port_a |= 0x80; // DIP SW 2-8, 1 = GDC 2.5MHz, 0 = GDC 5MHz
1074 port_a |= 0x40; // DIP SW 2-7, 1 = Do not control FD motor
1075 port_a |= 0x20; // DIP SW 2-6, 1 = Enable internal HD
1076 // port_a |= 0x10; // DIP SW 2-5, 1 = Initialize emory switch
1077 // port_a |= 0x08; // DIP SW 2-4, 1 = 20 lines, 0 = 25 lines
1078 // port_a |= 0x04; // DIP SW 2-3, 1 = 40 columns, 0 = 80 columns
1079 port_a |= 0x02; // DIP SW 2-2, 1 = BASIC mode, 0 = Terminal mode
1080 port_a |= 0x01; // DIP SW 2-1, 1 = Normal mode, 0 = LT mode
1082 port_b |= 0x80; // RS-232C CI#, 1 = OFF
1083 port_b |= 0x40; // RS-232C CS#, 1 = OFF
1084 port_b |= 0x20; // RS-232C CD#, 1 = OFF
1085 #if !defined(SUPPORT_HIRESO)
1086 // port_b |= 0x10; // INT3, 1 = Active, 0 = Inactive
1087 port_b |= 0x08; // DIP SW 1-1, 1 = Hiresolution CRT, 0 = Standard CRT
1089 port_b |= 0x10; // SHUT0
1090 port_b |= 0x08; // SHUT1
1092 // port_b |= 0x04; // IMCK, 1 = Parity error occurs in internal RAM
1093 // port_b |= 0x02; // EMCK, 1 = Parity error occurs in external RAM
1094 // port_b |= 0x01; // CDAT
1096 port_c |= 0x80; // SHUT0
1097 port_c |= 0x40; // PSTBM, 1 = Mask printer's PSTB#
1098 port_c |= 0x20; // SHUT1
1099 port_c |= 0x10; // MCHKEN, 1 = Enable parity check for RAM
1100 port_c |= 0x08; // BUZ, 1 = Stop buzzer
1101 port_c |= 0x04; // TXRE, 1 = Enable IRQ from RS-232C 8251A TXRDY
1102 port_c |= 0x02; // TXEE, 1 = Enable IRQ from RS-232C 8251A TXEMPTY
1103 port_c |= 0x01; // RXRE, 1 = Enable IRQ from RS-232C 8251A RXRDY
1104 pio_sys->write_signal(SIG_I8255_PORT_A, port_a, 0xff);
1105 pio_sys->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1106 pio_sys->write_signal(SIG_I8255_PORT_C, port_c, 0xff);
1109 #if defined(_PC9801)
1110 // port_b |= 0x80; // TYP1, 0 = PC-9801 (first)
1111 // port_b |= 0x40; // TYP0, 0
1112 #elif defined(_PC9801U)
1113 port_b |= 0x80; // TYP1, 1 = PC-9801U
1114 port_b |= 0x40; // TYP0, 1
1116 port_b |= 0x80; // TYP1, 1 = Other PC-9801 series
1117 // port_b |= 0x40; // TYP0, 0
1119 if(pit_clock_8mhz) {
1120 port_b |= 0x20; // MOD, 1 = System clock 8MHz, 0 = 5/10MHz
1122 port_b |= 0x10; // DIP SW 1-3, 1 = Don't use LCD
1123 #if !defined(SUPPORT_16_COLORS)
1124 port_b |= 0x08; // DIP SW 1-8, 1 = Standard graphic mode, 0 = Enhanced graphic mode
1126 port_b |= 0x04; // Printer BUSY#, 1 = Inactive, 0 = Active (BUSY)
1127 #if defined(HAS_V30) || defined(HAS_V33)
1128 port_b |= 0x02; // CPUT, 1 = V30/V33, 0 = 80x86
1130 #if defined(_PC9801VF) || defined(_PC9801U)
1131 port_b |= 0x01; // VF, 1 = PC-9801VF/U
1133 pio_prn->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1135 #if defined(SUPPORT_320KB_FDD_IF)
1136 pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
1137 pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
1138 pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
1140 #if defined(SUPPORT_2DD_FDD_IF)
1141 fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1); // 2DD FDC RDY is pulluped
1144 if(sound_type == 0 || sound_type == 1) {
1145 // opn->write_signal(SIG_YM2203_PORT_A, 0x3f, 0xff); // PC-9801-26(K) INT0
1146 // opn->write_signal(SIG_YM2203_PORT_A, 0xbf, 0xff); // PC-9801-26(K) INT41
1147 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff); // PC-9801-26(K) INT5
1148 // opn->write_signal(SIG_YM2203_PORT_A, 0x7f, 0xff); // PC-9801-26(K) INT6
1151 #if defined(SUPPORT_OLD_BUZZER)
1152 beep->write_signal(SIG_BEEP_ON, 1, 1);
1153 beep->write_signal(SIG_BEEP_MUTE, 1, 1);
1155 beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
1156 beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
1159 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1160 pc88opn1->set_reg(0x29, 3); // for Misty Blue
1161 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
1162 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
1168 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1169 if(boot_mode != 0) {
1176 double VM::get_frame_rate()
1178 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1179 if(config.boot_mode != 0) {
1180 return pc88event->get_frame_rate();
1183 return event->get_frame_rate();
1186 // ----------------------------------------------------------------------------
1188 // ----------------------------------------------------------------------------
1191 DEVICE *VM::get_cpu(int index)
1193 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1194 if(index == 0 && boot_mode == 0) {
1196 } else if(index == 1 && boot_mode != 0) {
1198 } else if(index == 2 && boot_mode != 0) {
1204 #if defined(SUPPORT_320KB_FDD_IF)
1205 } else if(index == 1) {
1214 // ----------------------------------------------------------------------------
1216 // ----------------------------------------------------------------------------
1218 void VM::draw_screen()
1220 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1221 if(boot_mode != 0) {
1222 pc88->draw_screen();
1225 display->draw_screen();
1228 // ----------------------------------------------------------------------------
1230 // ----------------------------------------------------------------------------
1232 void VM::initialize_sound(int rate, int samples)
1234 // init sound manager
1235 event->initialize_sound(rate, samples);
1238 #if defined(SUPPORT_OLD_BUZZER)
1239 beep->initialize_sound(rate, 2400, 8000);
1241 beep->initialize_sound(rate, 8000);
1243 if(sound_type == 0 || sound_type == 1) {
1244 if(opn->is_ym2608) {
1245 opn->initialize_sound(rate, 7987248, samples, 0, 0);
1247 opn->initialize_sound(rate, 3993624, samples, 0, 0);
1249 } else if(sound_type == 2 || sound_type == 3) {
1250 tms3631->initialize_sound(rate, 8000);
1253 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1254 // init sound manager
1255 pc88event->initialize_sound(rate, samples);
1258 if(pc88opn1->is_ym2608) {
1259 pc88opn1->initialize_sound(rate, 7987248, samples, 0, 0);
1261 pc88opn1->initialize_sound(rate, 3993624, samples, 0, 0);
1263 pc88pcm->initialize_sound(rate, 8000);
1267 uint16_t* VM::create_sound(int* extra_frames)
1269 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1270 if(boot_mode != 0) {
1271 return pc88event->create_sound(extra_frames);
1274 return event->create_sound(extra_frames);
1277 int VM::get_sound_buffer_ptr()
1279 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1280 if(boot_mode != 0) {
1281 return pc88event->get_sound_buffer_ptr();
1284 return event->get_sound_buffer_ptr();
1287 #ifdef USE_SOUND_VOLUME
1288 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
1291 if(sound_type == 0 || sound_type == 1) {
1292 opn->set_volume(0, decibel_l, decibel_r);
1294 } else if(ch-- == 0) {
1295 if(sound_type == 0 || sound_type == 1) {
1296 opn->set_volume(1, decibel_l, decibel_r);
1298 #if defined(SUPPORT_PC98_OPNA)
1299 } else if(ch-- == 0) {
1300 if(sound_type == 0 || sound_type == 1) {
1301 opn->set_volume(2, decibel_l, decibel_r);
1303 } else if(ch-- == 0) {
1304 if(sound_type == 0 || sound_type == 1) {
1305 opn->set_volume(3, decibel_l, decibel_r);
1308 } else if(ch-- == 0) {
1309 if(sound_type == 2 || sound_type == 3) {
1310 tms3631->set_volume(0, decibel_l, decibel_r);
1312 } else if(ch-- == 0) {
1313 beep->set_volume(0, decibel_l, decibel_r);
1314 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1315 } else if(ch-- == 0) {
1316 pc88opn1->set_volume(0, decibel_l, decibel_r);
1317 } else if(ch-- == 0) {
1318 pc88opn1->set_volume(1, decibel_l, decibel_r);
1319 #if defined(SUPPORT_PC88_OPNA)
1320 } else if(ch-- == 0) {
1321 pc88opn1->set_volume(2, decibel_l, decibel_r);
1322 } else if(ch-- == 0) {
1323 pc88opn1->set_volume(3, decibel_l, decibel_r);
1325 } else if(ch-- == 0) {
1326 pc88pcm->set_volume(0, decibel_l, decibel_r);
1328 } else if(ch-- == 0) {
1329 noise_seek->set_volume(0, decibel_l, decibel_r);
1330 noise_head_down->set_volume(0, decibel_l, decibel_r);
1331 noise_head_up->set_volume(0, decibel_l, decibel_r);
1332 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1333 pc88noise_seek->set_volume(0, decibel_l, decibel_r);
1334 pc88noise_head_down->set_volume(0, decibel_l, decibel_r);
1335 pc88noise_head_up->set_volume(0, decibel_l, decibel_r);
1341 // ----------------------------------------------------------------------------
1343 // ----------------------------------------------------------------------------
1345 void VM::key_down(int code, bool repeat)
1347 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1348 if(boot_mode != 0) {
1349 pc88->key_down(code, repeat);
1352 keyboard->key_down(code, repeat);
1355 void VM::key_up(int code)
1357 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1358 if(boot_mode != 0) {
1359 // pc88->key_up(code);
1362 keyboard->key_up(code);
1365 bool VM::get_caps_locked()
1367 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1368 if(boot_mode != 0) {
1369 return pc88->get_caps_locked();
1372 return keyboard->get_caps_locked();
1375 bool VM::get_kana_locked()
1377 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1378 if(boot_mode != 0) {
1379 return pc88->get_kana_locked();
1382 return keyboard->get_kana_locked();
1385 // ----------------------------------------------------------------------------
1387 // ----------------------------------------------------------------------------
1389 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1391 UPD765A *controller = get_floppy_disk_controller(drv);
1393 if(controller != NULL) {
1394 controller->open_disk(drv & 1, file_path, bank);
1398 void VM::close_floppy_disk(int drv)
1400 UPD765A *controller = get_floppy_disk_controller(drv);
1402 if(controller != NULL) {
1403 controller->close_disk(drv & 1);
1407 bool VM::is_floppy_disk_inserted(int drv)
1409 DISK *handler = get_floppy_disk_handler(drv);
1411 if(handler != NULL) {
1412 return handler->inserted;
1417 void VM::is_floppy_disk_protected(int drv, bool value)
1419 DISK *handler = get_floppy_disk_handler(drv);
1421 if(handler != NULL) {
1422 handler->write_protected = value;
1426 bool VM::is_floppy_disk_protected(int drv)
1428 DISK *handler = get_floppy_disk_handler(drv);
1430 if(handler != NULL) {
1431 return handler->write_protected;
1436 uint32_t VM::is_floppy_disk_accessed()
1438 uint32_t status = 0;
1440 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1441 if(boot_mode != 0) {
1442 status = pc88fdc_sub->read_signal(0) & 3;
1444 status = fdc->read_signal(0) & 3;
1447 for(int drv = 0; drv < USE_FLOPPY_DISK; drv += 2) {
1448 UPD765A *controller = get_floppy_disk_controller(drv);
1450 if(controller != NULL) {
1451 status |= (controller->read_signal(0) & 3) << drv;
1458 UPD765A *VM::get_floppy_disk_controller(int drv)
1460 #if defined(_PC9801) || defined(_PC9801E)
1461 if(drv == 0 || drv == 1) {
1463 } else if(drv == 2 || drv == 3) {
1465 } else if(drv == 4 || drv == 5) {
1468 #elif defined(_PC9801VF) || defined(_PC9801U)
1469 if(drv == 0 || drv == 1) {
1472 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1473 if(drv == 0 || drv == 1) {
1475 } else if(drv == 2 || drv == 3) {
1479 if(drv == 0 || drv == 1) {
1486 DISK *VM::get_floppy_disk_handler(int drv)
1488 UPD765A *controller = get_floppy_disk_controller(drv);
1490 if(controller != NULL) {
1491 return controller->get_disk_handler(drv & 1);
1496 #if defined(USE_HARD_DISK)
1497 void VM::open_hard_disk(int drv, const _TCHAR* file_path)
1499 if(drv < USE_HARD_DISK) {
1500 #if defined(SUPPORT_SASI_IF)
1501 sasi_hdd->open(drv, file_path, 256);
1503 #if defined(SUPPORT_SCSI_IF)
1504 scsi_hdd[drv]->open(0, file_path, 512);
1506 #if defined(SUPPORT_IDE_IF)
1507 ide_hdd[drv]->open(0, file_path, 512);
1512 void VM::close_hard_disk(int drv)
1514 if(drv < USE_HARD_DISK) {
1515 #if defined(SUPPORT_SASI_IF)
1516 sasi_hdd->close(drv);
1518 #if defined(SUPPORT_SCSI_IF)
1519 scsi_hdd[drv]->close(0);
1521 #if defined(SUPPORT_IDE_IF)
1522 ide_hdd[drv]->close(0);
1527 bool VM::is_hard_disk_inserted(int drv)
1529 if(drv < USE_HARD_DISK) {
1530 #if defined(SUPPORT_SASI_IF)
1531 return sasi_hdd->mounted(drv);
1533 #if defined(SUPPORT_SCSI_IF)
1534 return scsi_hdd[drv]->mounted(0);
1536 #if defined(SUPPORT_IDE_IF)
1537 return ide_hdd[drv]->mounted(0);
1543 uint32_t VM::is_hard_disk_accessed()
1545 uint32_t status = 0;
1547 for(int drv = 0; drv < USE_HARD_DISK; drv++) {
1548 #if defined(SUPPORT_SASI_IF)
1549 if(sasi_hdd->accessed(drv)) {
1553 #if defined(SUPPORT_SCSI_IF)
1554 if(scsi_hdd[drv]->accessed(0)) {
1558 #if defined(SUPPORT_IDE_IF)
1559 if(ide_hdd[drv]->accessed(0)) {
1568 #if defined(USE_TAPE)
1569 void VM::play_tape(int drv, const _TCHAR* file_path)
1571 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1572 pc88->play_tape(file_path);
1574 cmt->play_tape(file_path);
1578 void VM::rec_tape(int drv, const _TCHAR* file_path)
1580 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1581 pc88->rec_tape(file_path);
1583 cmt->rec_tape(file_path);
1587 void VM::close_tape(int drv)
1589 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1596 bool VM::is_tape_inserted(int drv)
1598 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1599 return pc88->is_tape_inserted();
1601 return cmt->is_tape_inserted();
1606 bool VM::is_frame_skippable()
1608 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1609 if(boot_mode != 0) {
1610 // return pc88event->is_frame_skippable();
1611 return pc88->is_frame_skippable();
1614 return event->is_frame_skippable();
1617 void VM::update_config()
1619 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1620 if(boot_mode != config.boot_mode) {
1621 // boot mode is changed !!!
1622 boot_mode = config.boot_mode;
1626 for(DEVICE* device = first_device; device; device = device->next_device) {
1627 device->update_config();
1631 #define STATE_VERSION 16
1633 bool VM::process_state(FILEIO* state_fio, bool loading)
1635 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1638 for(DEVICE* device = first_device; device; device = device->next_device) {
1639 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
1640 // const char *name = typeid(*device).name();
1641 // But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
1642 const char *name = device->get_device_name();
1643 int len = strlen(name);
1644 if(!state_fio->StateCheckInt32(len)) {
1646 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
1650 if(!state_fio->StateCheckBuffer(name, len, 1)) {
1652 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
1656 if(!device->process_state(state_fio, loading)) {
1658 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
1663 state_fio->StateValue(pit_clock_8mhz);
1664 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1665 state_fio->StateValue(boot_mode);
1667 state_fio->StateValue(sound_type);