2 NEC PC-9801 Emulator 'ePC-9801'
3 NEC PC-9801E/F/M Emulator 'ePC-9801E'
4 NEC PC-98DO Emulator 'ePC-98DO'
6 Author : Takeda.Toshiya
12 #include "../../emu.h"
13 #include "../device.h"
17 #if defined(SUPPORT_OLD_BUZZER)
33 #include "../memory.h"
34 #if defined(HAS_I86) || defined(HAS_V30)
37 #if !defined(SUPPORT_OLD_BUZZER)
38 #include "../pcm1bit.h"
40 #include "../upd1990a.h"
41 #include "../upd7220.h"
42 #include "../upd765a.h"
43 #include "../ym2203.h"
46 #include "../debugger.h"
57 #if defined(SUPPORT_320KB_FDD_IF)
58 #include "../pc80s31k.h"
61 #if defined(SUPPORT_CMT_IF)
66 #include "../pc80s31k.h"
68 #include "../pc8801/pc88.h"
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
75 VM::VM(EMU* parent_emu) : emu(parent_emu)
79 boot_mode = config.boot_mode;
81 int cpu_clocks = CPU_CLOCKS;
82 #if defined(PIT_CLOCK_8MHZ)
83 pit_clock_8mhz = true;
85 pit_clock_8mhz = false;
88 cpu_type = config.cpu_type;
89 if(config.cpu_type != 0) {
92 pit_clock_8mhz = false;
94 #elif defined(_PC9801VM) || defined(_PC98DO)
95 cpu_type = config.cpu_type;
96 if(config.cpu_type != 0) {
99 pit_clock_8mhz = true;
102 int pit_clocks = pit_clock_8mhz ? 1996812 : 2457600;
105 first_device = last_device = NULL;
106 dummy = new DEVICE(this, emu); // must be 1st device
107 event = new EVENT(this, emu); // must be 2nd device
109 #if defined(SUPPORT_OLD_BUZZER)
110 beep = new BEEP(this, emu);
112 beep = new PCM1BIT(this, emu);
114 dma = new I8237(this, emu);
115 #if defined(SUPPORT_CMT_IF)
116 sio_cmt = new I8251(this, emu); // for cmt
118 sio_rs = new I8251(this, emu); // for rs232c
119 sio_kbd = new I8251(this, emu); // for keyboard
120 pit = new I8253(this, emu);
121 #if defined(SUPPORT_320KB_FDD_IF)
122 pio_fdd = new I8255(this, emu); // for 320kb fdd i/f
124 pio_mouse = new I8255(this, emu); // for mouse
125 pio_sys = new I8255(this, emu); // for system port
126 pio_prn = new I8255(this, emu); // for printer
127 pic = new I8259(this, emu);
129 cpu = new I86(this, emu);
131 cpu = new I286(this, emu);
133 io = new IO(this, emu);
134 dmareg1 = new LS244(this, emu);
135 dmareg2 = new LS244(this, emu);
136 dmareg3 = new LS244(this, emu);
137 dmareg0 = new LS244(this, emu);
138 rtcreg = new LS244(this, emu);
139 memory = new MEMORY(this, emu);
140 #if defined(HAS_I86) || defined(HAS_V30)
141 g_not = new NOT(this, emu);
143 rtc = new UPD1990A(this, emu);
144 #if defined(SUPPORT_2HD_FDD_IF)
145 fdc_2hd = new UPD765A(this, emu);
147 #if defined(SUPPORT_2DD_FDD_IF)
148 fdc_2dd = new UPD765A(this, emu);
150 #if defined(SUPPORT_2HD_2DD_FDD_IF)
151 fdc = new UPD765A(this, emu);
153 gdc_chr = new UPD7220(this, emu);
154 gdc_gfx = new UPD7220(this, emu);
155 opn = new YM2203(this, emu);
157 #if defined(SUPPORT_CMT_IF)
158 cmt = new CMT(this, emu);
160 display = new DISPLAY(this, emu);
161 floppy = new FLOPPY(this, emu);
162 fmsound = new FMSOUND(this, emu);
163 joystick = new JOYSTICK(this, emu);
164 keyboard = new KEYBOARD(this, emu);
165 mouse = new MOUSE(this, emu);
166 printer = new PRINTER(this, emu);
168 #if defined(SUPPORT_320KB_FDD_IF)
170 pio_sub = new I8255(this, emu);
171 pc80s31k = new PC80S31K(this, emu);
172 fdc_sub = new UPD765A(this, emu);
173 cpu_sub = new Z80(this, emu);
195 event->set_context_cpu(cpu, cpu_clocks);
196 #if defined(SUPPORT_320KB_FDD_IF)
197 event->set_context_cpu(cpu_sub, 4000000);
199 event->set_context_sound(beep);
200 event->set_context_sound(opn);
201 #if defined(SUPPORT_CMT_IF)
202 event->set_context_sound(cmt);
205 //event->set_context_sound(pc88);
207 dma->set_context_memory(memory);
209 // dma ch.1: memory refresh
210 #if defined(SUPPORT_2HD_FDD_IF)
211 dma->set_context_ch2(fdc_2hd);
213 #if defined(SUPPORT_2DD_FDD_IF)
214 dma->set_context_ch3(fdc_2dd);
216 #if defined(SUPPORT_2HD_2DD_FDD_IF)
217 dma->set_context_ch2(fdc);
218 dma->set_context_ch3(fdc);
220 // sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
221 sio_kbd->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 1);
222 pit->set_context_ch0(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 1);
223 #if defined(SUPPORT_OLD_BUZZER)
224 // pit ch.1: memory refresh
227 pit->set_context_ch1(beep, SIG_PCM1BIT_SIGNAL, 1);
230 pit->set_constant_clock(0, pit_clocks);
231 pit->set_constant_clock(1, pit_clocks);
232 pit->set_constant_clock(2, pit_clocks);
233 pio_mouse->set_context_port_c(mouse, SIG_MOUSE_PORT_C, 0xf0, 0);
234 // sysport port.c bit6: printer strobe
235 #if defined(SUPPORT_OLD_BUZZER)
236 pio_sys->set_context_port_c(beep, SIG_BEEP_MUTE, 8, 0);
238 pio_sys->set_context_port_c(beep, SIG_PCM1BIT_MUTE, 8, 0);
240 // sysport port.c bit2: enable txrdy interrupt
241 // sysport port.c bit1: enable txempty interrupt
242 // sysport port.c bit0: enable rxrdy interrupt
243 pio_prn->set_context_port_a(printer, SIG_PRINTER_OUT, 0xff, 0);
244 pio_prn->set_context_port_c(printer, SIG_PRINTER_STB, 0x80, 0);
245 #if defined(HAS_I86) || defined(HAS_V30)
246 pio_prn->set_context_port_c(g_not, SIG_NOT_INPUT, 8, 0);
247 g_not->set_context_out(pic, SIG_I8259_CHIP1 | SIG_I8259_IR0, 1);
249 dmareg1->set_context_output(dma, SIG_I8237_BANK1, 0x0f, 0);
250 dmareg2->set_context_output(dma, SIG_I8237_BANK2, 0x0f, 0);
251 dmareg3->set_context_output(dma, SIG_I8237_BANK3, 0x0f, 0);
252 dmareg0->set_context_output(dma, SIG_I8237_BANK0, 0x0f, 0);
253 rtcreg->set_context_output(rtc, SIG_UPD1990A_CMD, 0x07, 0);
254 rtcreg->set_context_output(rtc, SIG_UPD1990A_DIN, 0x20, 0);
255 rtcreg->set_context_output(rtc, SIG_UPD1990A_STB, 0x08, 0);
256 rtcreg->set_context_output(rtc, SIG_UPD1990A_CLK, 0x10, 0);
257 pic->set_context_cpu(cpu);
258 rtc->set_context_dout(pio_sys, SIG_I8255_PORT_B, 1);
259 opn->set_context_irq(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
260 opn->set_context_port_b(joystick, SIG_JOYSTICK_SELECT, 0xc0, 0);
262 display->set_context_pic(pic);
263 display->set_context_gdc_chr(gdc_chr, gdc_chr->get_ra());
264 display->set_context_gdc_gfx(gdc_gfx, gdc_gfx->get_ra(), gdc_gfx->get_cs());
265 fmsound->set_context_opn(opn);
266 joystick->set_context_opn(opn);
267 keyboard->set_context_sio(sio_kbd);
268 mouse->set_context_pic(pic);
269 mouse->set_context_pio(pio_mouse);
271 #if defined(SUPPORT_2HD_FDD_IF)
272 fdc_2hd->set_context_irq(floppy, SIG_FLOPPY_2HD_IRQ, 1);
273 fdc_2hd->set_context_drq(floppy, SIG_FLOPPY_2HD_DRQ, 1);
274 fdc_2hd->raise_irq_when_media_changed = true;
275 floppy->set_context_fdc_2hd(fdc_2hd);
277 #if defined(SUPPORT_2DD_FDD_IF)
278 fdc_2dd->set_context_irq(floppy, SIG_FLOPPY_2DD_IRQ, 1);
279 fdc_2dd->set_context_drq(floppy, SIG_FLOPPY_2DD_DRQ, 1);
280 fdc_2dd->raise_irq_when_media_changed = true;
281 floppy->set_context_fdc_2dd(fdc_2dd);
283 #if defined(SUPPORT_2HD_2DD_FDD_IF)
284 fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
285 fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
286 fdc->raise_irq_when_media_changed = true;
287 floppy->set_context_fdc(fdc);
289 floppy->set_context_dma(dma);
290 floppy->set_context_pic(pic);
292 #if defined(SUPPORT_CMT_IF)
293 sio_cmt->set_context_out(cmt, SIG_CMT_OUT);
294 // sio_cmt->set_context_txrdy(cmt, SIG_CMT_TXRDY, 1);
295 // sio_cmt->set_context_rxrdy(cmt, SIG_CMT_RXRDY, 1);
296 // sio_cmt->set_context_txe(cmt, SIG_CMT_TXEMP, 1);
297 cmt->set_context_sio(sio_cmt);
301 cpu->set_context_mem(memory);
302 cpu->set_context_io(io);
303 cpu->set_context_intr(pic);
304 #ifdef SINGLE_MODE_DMA
305 cpu->set_context_dma(dma);
308 cpu->set_context_debugger(new DEBUGGER(this, emu));
311 #if defined(SUPPORT_320KB_FDD_IF)
313 pc80s31k->set_context_cpu(cpu_sub);
314 pc80s31k->set_context_fdc(fdc_sub);
315 pc80s31k->set_context_pio(pio_sub);
316 pio_fdd->set_context_port_a(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
317 pio_fdd->set_context_port_b(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
318 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
319 pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
320 pio_fdd->clear_ports_by_cmdreg = true;
321 pio_sub->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
322 pio_sub->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
323 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
324 pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
325 pio_sub->clear_ports_by_cmdreg = true;
326 fdc_sub->set_context_irq(cpu_sub, SIG_CPU_IRQ, 1);
327 cpu_sub->set_context_mem(pc80s31k);
328 cpu_sub->set_context_io(pc80s31k);
329 cpu_sub->set_context_intr(pc80s31k);
331 cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
336 memset(ram, 0, sizeof(ram));
337 memset(ipl, 0xff, sizeof(ipl));
338 memset(sound_bios, 0xff, sizeof(sound_bios));
339 #if defined(_PC9801) || defined(_PC9801E)
340 memset(fd_bios_2hd, 0xff, sizeof(fd_bios_2hd));
341 memset(fd_bios_2dd, 0xff, sizeof(fd_bios_2dd));
344 memory->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));
345 int sound_bios_ok = memory->read_bios(_T("SOUND.ROM"), sound_bios, sizeof(sound_bios));
346 #if defined(_PC9801) || defined(_PC9801E)
347 memory->read_bios(_T("2HDIF.ROM"), fd_bios_2hd, sizeof(fd_bios_2hd));
348 memory->read_bios(_T("2DDIF.ROM"), fd_bios_2dd, sizeof(fd_bios_2dd));
351 memory->set_memory_rw(0x00000, 0x9ffff, ram);
352 // A0000h - A1FFFh: TEXT VRAM
353 // A2000h - A3FFFh: ATTRIBUTE
354 memory->set_memory_mapped_io_rw(0xa0000, 0xa3fff, display);
355 // A8000h - BFFFFh: VRAM
356 memory->set_memory_mapped_io_rw(0xa8000, 0xbffff, display);
357 memory->set_memory_r(0xcc000, 0xcffff, sound_bios);
358 #if defined(_PC9801) || defined(_PC9801E)
359 memory->set_memory_r(0xd6000, 0xd6fff, fd_bios_2dd);
360 memory->set_memory_r(0xd7000, 0xd7fff, fd_bios_2hd);
362 #if defined(SUPPORT_16_COLORS)
363 // E0000h - E7FFFh: VRAM
364 memory->set_memory_mapped_io_rw(0xe0000, 0xe7fff, display);
366 memory->set_memory_r(0xe8000, 0xfffff, ipl);
368 display->sound_bios_ok = (sound_bios_ok != 0); // memory switch
371 io->set_iomap_alias_rw(0x00, pic, 0);
372 io->set_iomap_alias_rw(0x02, pic, 1);
373 io->set_iomap_alias_rw(0x08, pic, 2);
374 io->set_iomap_alias_rw(0x0a, pic, 3);
376 io->set_iomap_alias_rw(0x01, dma, 0x00);
377 io->set_iomap_alias_rw(0x03, dma, 0x01);
378 io->set_iomap_alias_rw(0x05, dma, 0x02);
379 io->set_iomap_alias_rw(0x07, dma, 0x03);
380 io->set_iomap_alias_rw(0x09, dma, 0x04);
381 io->set_iomap_alias_rw(0x0b, dma, 0x05);
382 io->set_iomap_alias_rw(0x0d, dma, 0x06);
383 io->set_iomap_alias_rw(0x0f, dma, 0x07);
384 io->set_iomap_alias_rw(0x11, dma, 0x08);
385 io->set_iomap_alias_w(0x13, dma, 0x09);
386 io->set_iomap_alias_w(0x15, dma, 0x0a);
387 io->set_iomap_alias_w(0x17, dma, 0x0b);
388 io->set_iomap_alias_w(0x19, dma, 0x0c);
389 io->set_iomap_alias_rw(0x1b, dma, 0x0d);
390 io->set_iomap_alias_w(0x1d, dma, 0x0e);
391 io->set_iomap_alias_w(0x1f, dma, 0x0f);
392 io->set_iomap_single_w(0x21, dmareg1);
393 io->set_iomap_single_w(0x23, dmareg2);
394 io->set_iomap_single_w(0x25, dmareg3);
395 io->set_iomap_single_w(0x27, dmareg0);
397 io->set_iomap_single_w(0x20, rtcreg);
399 io->set_iomap_alias_rw(0x30, sio_rs, 0);
400 io->set_iomap_alias_rw(0x32, sio_rs, 1);
402 io->set_iomap_alias_rw(0x31, pio_sys, 0);
403 io->set_iomap_alias_rw(0x33, pio_sys, 1);
404 io->set_iomap_alias_rw(0x35, pio_sys, 2);
405 io->set_iomap_alias_w(0x37, pio_sys, 3);
407 io->set_iomap_alias_rw(0x40, pio_prn, 0);
408 io->set_iomap_alias_rw(0x42, pio_prn, 1);
409 io->set_iomap_alias_rw(0x44, pio_prn, 2);
410 io->set_iomap_alias_w(0x46, pio_prn, 3);
412 io->set_iomap_alias_rw(0x41, sio_kbd, 0);
413 io->set_iomap_alias_rw(0x43, sio_kbd, 1);
415 // 50h, 52h: NMI Flip Flop
417 #if defined(SUPPORT_320KB_FDD_IF)
418 io->set_iomap_alias_rw(0x51, pio_fdd, 0);
419 io->set_iomap_alias_rw(0x53, pio_fdd, 1);
420 io->set_iomap_alias_rw(0x55, pio_fdd, 2);
421 io->set_iomap_alias_w(0x57, pio_fdd, 3);
424 io->set_iomap_alias_rw(0x60, gdc_chr, 0);
425 io->set_iomap_alias_rw(0x62, gdc_chr, 1);
427 io->set_iomap_single_w(0x64, display);
428 io->set_iomap_single_w(0x68, display);
429 #if defined(SUPPORT_16_COLORS)
430 io->set_iomap_single_w(0x6a, display);
432 io->set_iomap_single_w(0x6c, display);
433 io->set_iomap_single_w(0x6e, display);
435 io->set_iomap_single_w(0x70, display);
436 io->set_iomap_single_w(0x72, display);
437 io->set_iomap_single_w(0x74, display);
438 io->set_iomap_single_w(0x76, display);
439 io->set_iomap_single_w(0x78, display);
440 io->set_iomap_single_w(0x7a, display);
441 #if defined(SUPPORT_16_COLORS)
442 io->set_iomap_single_w(0x7c, display);
443 io->set_iomap_single_w(0x7e, display);
446 io->set_iomap_alias_rw(0x71, pit, 0);
447 io->set_iomap_alias_rw(0x73, pit, 1);
448 io->set_iomap_alias_rw(0x75, pit, 2);
449 io->set_iomap_alias_w(0x77, pit, 3);
453 io->set_iomap_single_rw(0x90, floppy);
454 io->set_iomap_single_rw(0x92, floppy);
455 io->set_iomap_single_rw(0x94, floppy);
457 #if defined(SUPPORT_CMT_IF)
458 io->set_iomap_alias_rw(0x91, sio_cmt, 0);
459 io->set_iomap_alias_rw(0x93, sio_cmt, 1);
460 io->set_iomap_single_w(0x95, cmt);
461 io->set_iomap_single_w(0x97, cmt);
464 io->set_iomap_alias_rw(0xa0, gdc_gfx, 0);
465 io->set_iomap_alias_rw(0xa2, gdc_gfx, 1);
467 #if defined(SUPPORT_2ND_VRAM)
468 io->set_iomap_single_w(0xa4, display);
469 io->set_iomap_single_w(0xa6, display);
471 io->set_iomap_single_rw(0xa8, display);
472 io->set_iomap_single_rw(0xaa, display);
473 io->set_iomap_single_rw(0xac, display);
474 io->set_iomap_single_rw(0xae, display);
476 io->set_iomap_single_w(0xa1, display);
477 io->set_iomap_single_w(0xa3, display);
478 io->set_iomap_single_w(0xa5, display);
479 io->set_iomap_single_rw(0xa9, display);
481 #if defined(SUPPORT_2HD_2DD_FDD_IF)
482 io->set_iomap_single_rw(0xbe, floppy);
484 io->set_iomap_single_rw(0xc8, floppy);
485 io->set_iomap_single_rw(0xca, floppy);
486 io->set_iomap_single_rw(0xcc, floppy);
488 io->set_iomap_single_rw(0x188, fmsound);
489 io->set_iomap_single_rw(0x18a, fmsound);
491 io->set_iomap_single_rw(0x18c, fmsound);
492 io->set_iomap_single_rw(0x18e, fmsound);
493 io->set_iomap_single_rw(0xa460, fmsound);
496 #if !defined(SUPPORT_OLD_BUZZER)
497 io->set_iomap_alias_rw(0x3fd9, pit, 0);
498 io->set_iomap_alias_rw(0x3fdb, pit, 1);
499 io->set_iomap_alias_rw(0x3fdd, pit, 2);
500 io->set_iomap_alias_w(0x3fdf, pit, 3);
503 io->set_iomap_alias_rw(0x7fd9, pio_mouse, 0);
504 io->set_iomap_alias_rw(0x7fdb, pio_mouse, 1);
505 io->set_iomap_alias_rw(0x7fdd, pio_mouse, 2);
506 io->set_iomap_alias_w(0x7fdf, pio_mouse, 3);
507 #if !(defined(_PC9801) || defined(_PC9801E))
508 io->set_iomap_single_w(0xbfdb, mouse);
512 pc88event = new EVENT(this, emu);
513 pc88event->set_frames_per_sec(60);
514 pc88event->set_lines_per_frame(260);
516 pc88 = new PC88(this, emu);
517 pc88->set_context_event_manager(pc88event);
518 pc88sio = new I8251(this, emu);
519 pc88sio->set_context_event_manager(pc88event);
520 pc88pio = new I8255(this, emu);
521 pc88pio->set_context_event_manager(pc88event);
522 pc88pcm = new PCM1BIT(this, emu);
523 pc88pcm->set_context_event_manager(pc88event);
524 pc88rtc = new UPD1990A(this, emu);
525 pc88rtc->set_context_event_manager(pc88event);
526 pc88opn = new YM2203(this, emu);
527 pc88opn->set_context_event_manager(pc88event);
528 pc88cpu = new Z80(this, emu);
529 pc88cpu->set_context_event_manager(pc88event);
531 pc88sub = new PC80S31K(this, emu);
532 pc88sub->set_context_event_manager(pc88event);
533 pc88pio_sub = new I8255(this, emu);
534 pc88pio_sub->set_context_event_manager(pc88event);
535 pc88fdc_sub = new UPD765A(this, emu);
536 pc88fdc_sub->set_context_event_manager(pc88event);
537 pc88cpu_sub = new Z80(this, emu);
538 pc88cpu_sub->set_context_event_manager(pc88event);
540 pc88event->set_context_cpu(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
541 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
542 pc88event->set_context_sound(pc88opn);
543 pc88event->set_context_sound(pc88pcm);
545 pc88->set_context_cpu(pc88cpu);
546 pc88->set_context_opn(pc88opn);
547 pc88->set_context_pcm(pc88pcm);
548 pc88->set_context_pio(pc88pio);
549 pc88->set_context_rtc(pc88rtc);
550 pc88->set_context_sio(pc88sio);
551 pc88cpu->set_context_mem(pc88);
552 pc88cpu->set_context_io(pc88);
553 pc88cpu->set_context_intr(pc88);
555 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
557 pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
558 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
559 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
561 pc88sub->set_context_cpu(pc88cpu_sub);
562 pc88sub->set_context_fdc(pc88fdc_sub);
563 pc88sub->set_context_pio(pc88pio_sub);
564 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
565 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
566 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
567 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
568 pc88pio->clear_ports_by_cmdreg = true;
569 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
570 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
571 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
572 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
573 pc88pio_sub->clear_ports_by_cmdreg = true;
574 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
575 pc88cpu_sub->set_context_mem(pc88sub);
576 pc88cpu_sub->set_context_io(pc88sub);
577 pc88cpu_sub->set_context_intr(pc88sub);
579 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
583 // initialize all devices
584 for(DEVICE* device = first_device; device; device = device->next_device) {
585 device->initialize();
587 #if defined(_PC9801) || defined(_PC9801E)
588 fdc_2hd->get_disk_handler(0)->drive_num = 0;
589 fdc_2hd->get_disk_handler(1)->drive_num = 1;
590 fdc_2dd->get_disk_handler(0)->drive_num = 2;
591 fdc_2dd->get_disk_handler(1)->drive_num = 3;
592 fdc_sub->get_disk_handler(0)->drive_num = 4;
593 fdc_sub->get_disk_handler(1)->drive_num = 5;
594 #elif defined(_PC9801VF) || defined(_PC9801U)
595 fdc_2dd->get_disk_handler(0)->drive_num = 0;
596 fdc_2dd->get_disk_handler(1)->drive_num = 1;
597 #elif defined(_PC98DO)
598 fdc->get_disk_handler(0)->drive_num = 0;
599 fdc->get_disk_handler(1)->drive_num = 1;
600 pc88fdc_sub->get_disk_handler(0)->drive_num = 2;
601 pc88fdc_sub->get_disk_handler(1)->drive_num = 3;
603 fdc->get_disk_handler(0)->drive_num = 0;
604 fdc->get_disk_handler(1)->drive_num = 1;
610 // delete all devices
611 for(DEVICE* device = first_device; device;) {
612 DEVICE *next_device = device->next_device;
615 device = next_device;
619 DEVICE* VM::get_device(int id)
621 for(DEVICE* device = first_device; device; device = device->next_device) {
622 if(device->this_device_id == id) {
629 // ----------------------------------------------------------------------------
630 // drive virtual machine
631 // ----------------------------------------------------------------------------
636 for(DEVICE* device = first_device; device; device = device->next_device) {
640 for(DEVICE* device = first_device; device; device = device->next_device) {
645 // initial device settings
646 pio_mouse->write_signal(SIG_I8255_PORT_A, 0xf0, 0xff); // clear mouse status
647 pio_mouse->write_signal(SIG_I8255_PORT_B, 0x40, 0xff); // cpu high & sw3-6
648 uint8 port_c = 0x08; // normal mode & sw1-5 & sw1-6
649 #if defined(HAS_V30) || defined(HAS_V33)
650 port_c |= 0x04; // V30
652 pio_mouse->write_signal(SIG_I8255_PORT_C, 0x40, 0xff);
654 pio_sys->write_signal(SIG_I8255_PORT_A, 0xe3, 0xff);
655 pio_sys->write_signal(SIG_I8255_PORT_B, 0xf8, 0xff);//0xe8??
658 uint8 prn_b = 0x00; // system type = first PC-9801
659 #elif defined(_PC9801U)
660 uint8 prn_b = 0xc0; // system type = PC-9801U,PC-98LT,PC-98HA
662 uint8 prn_b = 0x80; // system type = others
665 prn_b |= 0x20; // system clock is 8MHz
667 prn_b |= 0x10; // don't use LCD display
668 #if !defined(SUPPORT_16_COLORS)
669 prn_b |= 0x08; // standard graphics
671 prn_b |= 0x04; // printer is not busy
672 #if defined(HAS_V30) || defined(HAS_V33)
675 #if defined(_PC9801VF) || defined(_PC9801U)
676 prn_b |= 0x01; // PC-9801VF or PC-9801U
678 pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
680 #if defined(SUPPORT_320KB_FDD_IF)
681 pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
682 pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
683 pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
685 #if defined(SUPPORT_2DD_FDD_IF)
686 fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1); // 2DD FDC RDY is pulluped
689 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff); // PC-9801-26(K) IRQ=12
691 #if defined(SUPPORT_OLD_BUZZER)
692 beep->write_signal(SIG_BEEP_ON, 1, 1);
693 beep->write_signal(SIG_BEEP_MUTE, 1, 1);
695 beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
696 beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
700 pc88opn->SetReg(0x29, 3); // for Misty Blue
701 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
702 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
716 double VM::frame_rate()
719 if(config.boot_mode != 0) {
720 return pc88event->frame_rate();
723 return event->frame_rate();
726 // ----------------------------------------------------------------------------
728 // ----------------------------------------------------------------------------
731 DEVICE *VM::get_cpu(int index)
734 if(index == 0 && boot_mode == 0) {
736 } else if(index == 1 && boot_mode != 0) {
738 } else if(index == 2 && boot_mode != 0) {
744 #if defined(SUPPORT_320KB_FDD_IF)
745 } else if(index == 1) {
754 // ----------------------------------------------------------------------------
756 // ----------------------------------------------------------------------------
758 void VM::draw_screen()
765 display->draw_screen();
768 int VM::access_lamp()
770 #if defined(_PC9801) || defined(_PC9801E)
771 return (fdc_2hd->read_signal(0) & 3) | (fdc_2dd->read_signal(0) & 3) | (fdc_sub->read_signal(0) & 3);
772 #elif defined(_PC9801VF) || defined(_PC9801U)
773 return fdc_2dd->read_signal(0);
774 #elif defined(_PC98DO)
776 return pc88fdc_sub->read_signal(0);
778 return fdc->read_signal(0);
781 return fdc->read_signal(0);
785 // ----------------------------------------------------------------------------
787 // ----------------------------------------------------------------------------
789 void VM::initialize_sound(int rate, int samples)
791 // init sound manager
792 event->initialize_sound(rate, samples);
795 #if defined(SUPPORT_OLD_BUZZER)
796 beep->init(rate, 2400, 8000);
798 beep->init(rate, 8000);
801 opn->init(rate, 7987248, samples, 0, 0);
803 opn->init(rate, 3993624, samples, 0, 0);
807 // init sound manager
808 pc88event->initialize_sound(rate, samples);
812 pc88opn->init(rate, 7987248, samples, 0, 0);
814 pc88opn->init(rate, 3993624, samples, 0, 0);
816 pc88pcm->init(rate, 8000);
820 uint16* VM::create_sound(int* extra_frames)
824 return pc88event->create_sound(extra_frames);
827 return event->create_sound(extra_frames);
830 int VM::sound_buffer_ptr()
834 return pc88event->sound_buffer_ptr();
837 return event->sound_buffer_ptr();
840 // ----------------------------------------------------------------------------
842 // ----------------------------------------------------------------------------
844 void VM::key_down(int code, bool repeat)
848 pc88->key_down(code, repeat);
851 keyboard->key_down(code, repeat);
854 void VM::key_up(int code)
858 // pc88->key_up(code);
861 keyboard->key_up(code);
864 // ----------------------------------------------------------------------------
866 // ----------------------------------------------------------------------------
868 void VM::open_disk(int drv, _TCHAR* file_path, int bank)
870 #if defined(_PC9801) || defined(_PC9801E)
871 if(drv == 0 || drv == 1) {
872 fdc_2hd->open_disk(drv, file_path, bank);
873 } else if(drv == 2 || drv == 3) {
874 fdc_2dd->open_disk(drv - 2, file_path, bank);
875 } else if(drv == 4 || drv == 5) {
876 fdc_sub->open_disk(drv - 4, file_path, bank);
878 #elif defined(_PC9801VF) || defined(_PC9801U)
879 if(drv == 0 || drv == 1) {
880 fdc_2dd->open_disk(drv, file_path, bank);
882 #elif defined(_PC98DO)
883 if(drv == 0 || drv == 1) {
884 fdc->open_disk(drv, file_path, bank);
885 } else if(drv == 2 || drv == 3) {
886 pc88fdc_sub->open_disk(drv - 2, file_path, bank);
889 if(drv == 0 || drv == 1) {
890 fdc->open_disk(drv, file_path, bank);
895 void VM::close_disk(int drv)
897 #if defined(_PC9801) || defined(_PC9801E)
898 if(drv == 0 || drv == 1) {
899 fdc_2hd->close_disk(drv);
900 } else if(drv == 2 || drv == 3) {
901 fdc_2dd->close_disk(drv - 2);
902 } else if(drv == 4 || drv == 5) {
903 fdc_sub->close_disk(drv - 4);
905 #elif defined(_PC9801VF) || defined(_PC9801U)
906 if(drv == 0 || drv == 1) {
907 fdc_2dd->close_disk(drv);
909 #elif defined(_PC98DO)
910 if(drv == 0 || drv == 1) {
911 fdc->close_disk(drv);
912 } else if(drv == 2 || drv == 3) {
913 pc88fdc_sub->close_disk(drv - 2);
916 if(drv == 0 || drv == 1) {
917 fdc->close_disk(drv);
922 bool VM::disk_inserted(int drv)
924 #if defined(_PC9801) || defined(_PC9801E)
925 if(drv == 0 || drv == 1) {
926 return fdc_2hd->disk_inserted(drv);
927 } else if(drv == 2 || drv == 3) {
928 return fdc_2dd->disk_inserted(drv - 2);
929 } else if(drv == 4 || drv == 5) {
930 return fdc_sub->disk_inserted(drv - 4);
932 #elif defined(_PC9801VF) || defined(_PC9801U)
933 if(drv == 0 || drv == 1) {
934 return fdc_2dd->disk_inserted(drv);
936 #elif defined(_PC98DO)
937 if(drv == 0 || drv == 1) {
938 return fdc->disk_inserted(drv);
939 } else if(drv == 2 || drv == 3) {
940 return pc88fdc_sub->disk_inserted(drv - 2);
943 if(drv == 0 || drv == 1) {
944 return fdc->disk_inserted(drv);
950 #if defined(USE_DISK_WRITE_PROTECT)
951 void VM::write_protect_fd(int drv, bool flag)
954 #if defined(_PC9801) || defined(_PC9801E)
956 fdc_2hd->write_protect_fd(drv, flag);
958 fdc_2dd->write_protect_fd(drv - 2, flag);
960 fdc_sub->write_protect_fd(drv - 4, flag);
962 #elif defined(_PC9801VF) || defined(_PC9801U)
964 fdc_2dd->write_protect_fd(drv, flag);
966 #elif defined(_PC98DO)
968 fdc->write_protect_fd(drv, flag);
970 pc88fdc_sub->write_protect_fd(drv - 2, flag);
974 fdc->write_protect_fd(drv, flag);
980 bool VM::is_write_protect_fd(int drv)
982 if(drv < 0) return false;
983 #if defined(_PC9801) || defined(_PC9801E)
985 return fdc_2hd->is_write_protect_fd(drv);
987 return fdc_2dd->is_write_protect_fd(drv - 2);
989 return fdc_sub->is_write_protect_fd(drv - 4);
991 #elif defined(_PC9801VF) || defined(_PC9801U)
993 return fdc_2dd->is_write_protect_fd(drv);
995 #elif defined(_PC98DO)
997 return fdc->is_write_protect_fd(drv);
999 return pc88fdc_sub->is_write_protect_fd(drv - 2);
1003 return fdc->is_write_protect_fd(drv);
1010 #if defined(SUPPORT_CMT_IF) || defined(_PC98DO)
1011 void VM::play_tape(_TCHAR* file_path)
1013 #if defined(_PC98DO)
1014 pc88->play_tape(file_path);
1016 cmt->play_tape(file_path);
1020 void VM::rec_tape(_TCHAR* file_path)
1022 #if defined(_PC98DO)
1023 pc88->rec_tape(file_path);
1025 cmt->rec_tape(file_path);
1029 void VM::close_tape()
1031 #if defined(_PC98DO)
1038 bool VM::tape_inserted()
1040 #if defined(_PC98DO)
1041 return pc88->tape_inserted();
1043 return cmt->tape_inserted();
1047 #if defined(USE_TAPE_PTR)
1048 int VM::get_tape_ptr()
1050 #if defined(_PC98DO)
1051 return pc88->get_tape_ptr();
1053 return cmt->get_tape_ptr();
1060 void VM::set_mix_cmt(bool flag)
1062 #ifdef DATAREC_SOUND
1063 # if defined(_PC98DO)
1065 pc88->write_signal(SIG_PC88_DATAREC_MIX, 1, 1);
1067 pc88->write_signal(SIG_PC88_DATAREC_MIX, 0, 1);
1071 cmt->write_signal(SIG_CMT_MIX, 1, 1);
1073 cmt->write_signal(SIG_CMT_MIX, 0, 1);
1079 void VM::set_volume_cmt(uint32 volume)
1081 #ifdef DATAREC_SOUND
1082 # if defined(_PC98DO)
1083 pc88->write_signal(SIG_PC88_DATAREC_VOLUME, volume, 0xffffffff);
1085 cmt->write_signal(SIG_CMT_VOLUME, volume, 0xffffffff);
1094 #if defined(_PC98DO)
1095 if(boot_mode != 0) {
1096 // return pc88event->now_skip();
1097 return pc88->now_skip();
1100 return event->now_skip();
1103 void VM::update_config()
1105 #if defined(_PC9801E) || defined(_PC9801VM) || defined(_PC98DO)
1106 if(cpu_type != config.cpu_type) {
1108 int cpu_clocks = CPU_CLOCKS;
1109 #if defined(_PC9801E)
1110 if(config.cpu_type != 0) {
1112 cpu_clocks = 4992030;
1113 pit_clock_8mhz = false;
1116 cpu_clocks = CPU_CLOCKS;
1117 pit_clock_8mhz = true;
1119 #elif defined(_PC9801VM) || defined(_PC98DO)
1120 if(config.cpu_type != 0) {
1122 cpu_clocks = 7987248;
1123 pit_clock_8mhz = true;
1125 cpu_clocks = CPU_CLOCKS;
1126 pit_clock_8mhz = false;
1129 uint8 prn_b = pio_prn->read_signal(SIG_I8255_PORT_B);
1130 if(pit_clock_8mhz) {
1131 prn_b |= 0x20; // system clock is 8MHz
1132 pit_clocks = 1996812;
1135 pit_clocks = 2457600;
1137 pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
1138 pit->set_constant_clock(0, pit_clocks);
1139 pit->set_constant_clock(1, pit_clocks);
1140 pit->set_constant_clock(2, pit_clocks);
1141 event->set_cpu_clock(cpu, cpu_clocks);
1142 #if defined(_PC98DO)
1143 pc88event->set_cpu_clock(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
1145 cpu_type = config.cpu_type;
1149 #if defined(_PC98DO)
1150 if(boot_mode != config.boot_mode) {
1151 // boot mode is changed !!!
1152 boot_mode = config.boot_mode;
1156 for(DEVICE* device = first_device; device; device = device->next_device) {
1157 device->update_config();
1161 #define STATE_VERSION 2
1163 void VM::save_state(FILEIO* state_fio)
1165 state_fio->FputUint32(STATE_VERSION);
1167 for(DEVICE* device = first_device; device; device = device->next_device) {
1168 device->save_state(state_fio);
1170 state_fio->Fwrite(ram, sizeof(ram), 1);
1171 state_fio->FputBool(pit_clock_8mhz);
1172 #if defined(_PC98DO)
1173 state_fio->FputInt32(boot_mode);
1177 bool VM::load_state(FILEIO* state_fio)
1179 if(state_fio->FgetUint32() != STATE_VERSION) {
1182 for(DEVICE* device = first_device; device; device = device->next_device) {
1183 if(!device->load_state(state_fio)) {
1187 state_fio->Fread(ram, sizeof(ram), 1);
1188 pit_clock_8mhz = state_fio->FgetBool();
1189 #if defined(_PC98DO)
1190 boot_mode = state_fio->FgetInt32();