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
13 #include "../../emu.h"
14 #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 : 7981350); // XM8 version 1.00
541 // pc88event->set_context_cpu(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
542 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
543 pc88event->set_context_sound(pc88opn);
544 pc88event->set_context_sound(pc88pcm);
546 pc88->set_context_cpu(pc88cpu);
547 pc88->set_context_opn(pc88opn);
548 pc88->set_context_pcm(pc88pcm);
549 pc88->set_context_pio(pc88pio);
550 pc88->set_context_rtc(pc88rtc);
551 pc88->set_context_sio(pc88sio);
552 pc88cpu->set_context_mem(pc88);
553 pc88cpu->set_context_io(pc88);
554 pc88cpu->set_context_intr(pc88);
556 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
558 pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
559 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
560 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
562 pc88sub->set_context_cpu(pc88cpu_sub);
563 pc88sub->set_context_fdc(pc88fdc_sub);
564 pc88sub->set_context_pio(pc88pio_sub);
565 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
566 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
567 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
568 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
569 pc88pio->clear_ports_by_cmdreg = true;
570 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
571 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
572 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
573 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
574 pc88pio_sub->clear_ports_by_cmdreg = true;
575 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
576 pc88cpu_sub->set_context_mem(pc88sub);
577 pc88cpu_sub->set_context_io(pc88sub);
578 pc88cpu_sub->set_context_intr(pc88sub);
580 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
584 // initialize all devices
585 for(DEVICE* device = first_device; device; device = device->next_device) {
586 device->initialize();
592 // delete all devices
593 for(DEVICE* device = first_device; device;) {
594 DEVICE *next_device = device->next_device;
597 device = next_device;
601 DEVICE* VM::get_device(int id)
603 for(DEVICE* device = first_device; device; device = device->next_device) {
604 if(device->this_device_id == id) {
611 // ----------------------------------------------------------------------------
612 // drive virtual machine
613 // ----------------------------------------------------------------------------
618 for(DEVICE* device = first_device; device; device = device->next_device) {
622 for(DEVICE* device = first_device; device; device = device->next_device) {
627 // initial device settings
628 pio_mouse->write_signal(SIG_I8255_PORT_A, 0xf0, 0xff); // clear mouse status
629 pio_mouse->write_signal(SIG_I8255_PORT_B, 0x40, 0xff); // cpu high & sw3-6
630 uint8 port_c = 0x08; // normal mode & sw1-5 & sw1-6
631 #if defined(HAS_V30) || defined(HAS_V33)
632 port_c |= 0x04; // V30
634 pio_mouse->write_signal(SIG_I8255_PORT_C, 0x40, 0xff);
636 pio_sys->write_signal(SIG_I8255_PORT_A, 0xe3, 0xff);
637 pio_sys->write_signal(SIG_I8255_PORT_B, 0xf8, 0xff);//0xe8??
640 uint8 prn_b = 0x00; // system type = first PC-9801
641 #elif defined(_PC9801U)
642 uint8 prn_b = 0xc0; // system type = PC-9801U,PC-98LT,PC-98HA
644 uint8 prn_b = 0x80; // system type = others
647 prn_b |= 0x20; // system clock is 8MHz
649 prn_b |= 0x10; // don't use LCD display
650 #if !defined(SUPPORT_16_COLORS)
651 prn_b |= 0x08; // standard graphics
653 prn_b |= 0x04; // printer is not busy
654 #if defined(HAS_V30) || defined(HAS_V33)
657 #if defined(_PC9801VF) || defined(_PC9801U)
658 prn_b |= 0x01; // PC-9801VF or PC-9801U
660 pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
662 #if defined(SUPPORT_320KB_FDD_IF)
663 pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
664 pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
665 pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
667 #if defined(SUPPORT_2DD_FDD_IF)
668 fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1); // 2DD FDC RDY is pulluped
671 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff); // PC-9801-26(K) IRQ=12
673 #if defined(SUPPORT_OLD_BUZZER)
674 beep->write_signal(SIG_BEEP_ON, 1, 1);
675 beep->write_signal(SIG_BEEP_MUTE, 1, 1);
677 beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
678 beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
682 pc88opn->SetReg(0x29, 3); // for Misty Blue
683 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
684 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
698 double VM::frame_rate()
701 if(config.boot_mode != 0) {
702 return pc88event->frame_rate();
705 return event->frame_rate();
708 // ----------------------------------------------------------------------------
710 // ----------------------------------------------------------------------------
713 DEVICE *VM::get_cpu(int index)
716 if(index == 0 && boot_mode == 0) {
718 } else if(index == 1 && boot_mode != 0) {
720 } else if(index == 2 && boot_mode != 0) {
726 #if defined(SUPPORT_320KB_FDD_IF)
727 } else if(index == 1) {
736 // ----------------------------------------------------------------------------
738 // ----------------------------------------------------------------------------
740 void VM::draw_screen()
747 display->draw_screen();
750 int VM::access_lamp()
752 #if defined(_PC9801) || defined(_PC9801E)
753 return (fdc_2hd->read_signal(0) & 3) | (fdc_2dd->read_signal(0) & 3) | (fdc_sub->read_signal(0) & 3);
754 #elif defined(_PC9801VF) || defined(_PC9801U)
755 return fdc_2dd->read_signal(0);
756 #elif defined(_PC98DO)
758 return pc88fdc_sub->read_signal(0);
760 return fdc->read_signal(0);
763 return fdc->read_signal(0);
767 // ----------------------------------------------------------------------------
769 // ----------------------------------------------------------------------------
771 void VM::initialize_sound(int rate, int samples)
773 // init sound manager
774 event->initialize_sound(rate, samples);
777 #if defined(SUPPORT_OLD_BUZZER)
778 beep->init(rate, 2400, 8000);
780 beep->init(rate, 8000);
783 opn->init(rate, 7987248, samples, 0, 0);
785 opn->init(rate, 3993624, samples, 0, 0);
789 // init sound manager
790 pc88event->initialize_sound(rate, samples);
794 pc88opn->init(rate, 7987248, samples, 0, 0);
796 pc88opn->init(rate, 3993624, samples, 0, 0);
798 pc88pcm->init(rate, 8000);
802 uint16* VM::create_sound(int* extra_frames)
806 return pc88event->create_sound(extra_frames);
809 return event->create_sound(extra_frames);
812 int VM::sound_buffer_ptr()
816 return pc88event->sound_buffer_ptr();
819 return event->sound_buffer_ptr();
822 // ----------------------------------------------------------------------------
824 // ----------------------------------------------------------------------------
826 void VM::key_down(int code, bool repeat)
830 pc88->key_down(code, repeat);
833 keyboard->key_down(code, repeat);
836 void VM::key_up(int code)
840 // pc88->key_up(code);
843 keyboard->key_up(code);
846 // ----------------------------------------------------------------------------
848 // ----------------------------------------------------------------------------
850 void VM::open_disk(int drv, _TCHAR* file_path, int bank)
852 #if defined(_PC9801) || defined(_PC9801E)
853 if(drv == 0 || drv == 1) {
854 fdc_2hd->open_disk(drv, file_path, bank);
855 } else if(drv == 2 || drv == 3) {
856 fdc_2dd->open_disk(drv - 2, file_path, bank);
857 } else if(drv == 4 || drv == 5) {
858 fdc_sub->open_disk(drv - 4, file_path, bank);
860 #elif defined(_PC9801VF) || defined(_PC9801U)
861 if(drv == 0 || drv == 1) {
862 fdc_2dd->open_disk(drv, file_path, bank);
864 #elif defined(_PC98DO)
865 if(drv == 0 || drv == 1) {
866 fdc->open_disk(drv, file_path, bank);
867 } else if(drv == 2 || drv == 3) {
868 pc88fdc_sub->open_disk(drv - 2, file_path, bank);
871 if(drv == 0 || drv == 1) {
872 fdc->open_disk(drv, file_path, bank);
877 void VM::close_disk(int drv)
879 #if defined(_PC9801) || defined(_PC9801E)
880 if(drv == 0 || drv == 1) {
881 fdc_2hd->close_disk(drv);
882 } else if(drv == 2 || drv == 3) {
883 fdc_2dd->close_disk(drv - 2);
884 } else if(drv == 4 || drv == 5) {
885 fdc_sub->close_disk(drv - 4);
887 #elif defined(_PC9801VF) || defined(_PC9801U)
888 if(drv == 0 || drv == 1) {
889 fdc_2dd->close_disk(drv);
891 #elif defined(_PC98DO)
892 if(drv == 0 || drv == 1) {
893 fdc->close_disk(drv);
894 } else if(drv == 2 || drv == 3) {
895 pc88fdc_sub->close_disk(drv - 2);
898 if(drv == 0 || drv == 1) {
899 fdc->close_disk(drv);
904 bool VM::disk_inserted(int drv)
906 #if defined(_PC9801) || defined(_PC9801E)
907 if(drv == 0 || drv == 1) {
908 return fdc_2hd->disk_inserted(drv);
909 } else if(drv == 2 || drv == 3) {
910 return fdc_2dd->disk_inserted(drv - 2);
911 } else if(drv == 4 || drv == 5) {
912 return fdc_sub->disk_inserted(drv - 4);
914 #elif defined(_PC9801VF) || defined(_PC9801U)
915 if(drv == 0 || drv == 1) {
916 return fdc_2dd->disk_inserted(drv);
918 #elif defined(_PC98DO)
919 if(drv == 0 || drv == 1) {
920 return fdc->disk_inserted(drv);
921 } else if(drv == 2 || drv == 3) {
922 return pc88fdc_sub->disk_inserted(drv - 2);
925 if(drv == 0 || drv == 1) {
926 return fdc->disk_inserted(drv);
932 #if defined(USE_DISK_WRITE_PROTECT)
933 void VM::write_protect_fd(int drv, bool flag)
936 #if defined(_PC9801) || defined(_PC9801E)
938 fdc_2hd->write_protect_fd(drv, flag);
940 fdc_2dd->write_protect_fd(drv - 2, flag);
942 fdc_sub->write_protect_fd(drv - 4, flag);
944 #elif defined(_PC9801VF) || defined(_PC9801U)
946 fdc_2dd->write_protect_fd(drv, flag);
948 #elif defined(_PC98DO)
950 fdc->write_protect_fd(drv, flag);
952 pc88fdc_sub->write_protect_fd(drv - 2, flag);
956 fdc->write_protect_fd(drv, flag);
962 bool VM::is_write_protect_fd(int drv)
964 if(drv < 0) return false;
965 #if defined(_PC9801) || defined(_PC9801E)
967 return fdc_2hd->is_write_protect_fd(drv);
969 return fdc_2dd->is_write_protect_fd(drv - 2);
971 return fdc_sub->is_write_protect_fd(drv - 4);
973 #elif defined(_PC9801VF) || defined(_PC9801U)
975 return fdc_2dd->is_write_protect_fd(drv);
977 #elif defined(_PC98DO)
979 return fdc->is_write_protect_fd(drv);
981 return pc88fdc_sub->is_write_protect_fd(drv - 2);
985 return fdc->is_write_protect_fd(drv);
992 #if defined(SUPPORT_CMT_IF) || defined(_PC98DO)
993 void VM::play_tape(_TCHAR* file_path)
996 pc88->play_tape(file_path);
998 cmt->play_tape(file_path);
1002 void VM::rec_tape(_TCHAR* file_path)
1004 #if defined(_PC98DO)
1005 pc88->rec_tape(file_path);
1007 cmt->rec_tape(file_path);
1011 void VM::close_tape()
1013 #if defined(_PC98DO)
1020 bool VM::tape_inserted()
1022 #if defined(_PC98DO)
1023 return pc88->tape_inserted();
1025 return cmt->tape_inserted();
1029 #if defined(USE_TAPE_PTR)
1030 int VM::get_tape_ptr()
1032 #if defined(_PC98DO)
1033 return pc88->get_tape_ptr();
1035 return cmt->get_tape_ptr();
1044 #if defined(_PC98DO)
1045 if(boot_mode != 0) {
1046 // return pc88event->now_skip();
1047 return pc88->now_skip();
1050 return event->now_skip();
1053 void VM::update_config()
1055 #if defined(_PC9801E) || defined(_PC9801VM) || defined(_PC98DO)
1056 if(cpu_type != config.cpu_type) {
1058 int cpu_clocks = CPU_CLOCKS;
1059 #if defined(_PC9801E)
1060 if(config.cpu_type != 0) {
1062 cpu_clocks = 4992030;
1063 pit_clock_8mhz = false;
1066 cpu_clocks = CPU_CLOCKS;
1067 pit_clock_8mhz = true;
1069 #elif defined(_PC9801VM) || defined(_PC98DO)
1070 if(config.cpu_type != 0) {
1072 cpu_clocks = 7987248;
1073 pit_clock_8mhz = true;
1075 cpu_clocks = CPU_CLOCKS;
1076 pit_clock_8mhz = false;
1079 uint8 prn_b = pio_prn->read_signal(SIG_I8255_PORT_B);
1080 if(pit_clock_8mhz) {
1081 prn_b |= 0x20; // system clock is 8MHz
1082 pit_clocks = 1996812;
1085 pit_clocks = 2457600;
1087 pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
1088 pit->set_constant_clock(0, pit_clocks);
1089 pit->set_constant_clock(1, pit_clocks);
1090 pit->set_constant_clock(2, pit_clocks);
1091 event->set_cpu_clock(cpu, cpu_clocks);
1092 #if defined(_PC98DO)
1093 pc88event->set_cpu_clock(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
1095 cpu_type = config.cpu_type;
1099 #if defined(_PC98DO)
1100 if(boot_mode != config.boot_mode) {
1101 // boot mode is changed !!!
1102 boot_mode = config.boot_mode;
1106 for(DEVICE* device = first_device; device; device = device->next_device) {
1107 device->update_config();
1111 #define STATE_VERSION 2
1113 void VM::save_state(FILEIO* state_fio)
1115 state_fio->FputUint32(STATE_VERSION);
1117 for(DEVICE* device = first_device; device; device = device->next_device) {
1118 device->save_state(state_fio);
1120 state_fio->Fwrite(ram, sizeof(ram), 1);
1121 state_fio->FputBool(pit_clock_8mhz);
1122 #if defined(_PC98DO)
1123 state_fio->FputInt32(boot_mode);
1127 bool VM::load_state(FILEIO* state_fio)
1129 if(state_fio->FgetUint32() != STATE_VERSION) {
1132 for(DEVICE* device = first_device; device; device = device->next_device) {
1133 if(!device->load_state(state_fio)) {
1137 state_fio->Fread(ram, sizeof(ram), 1);
1138 pit_clock_8mhz = state_fio->FgetBool();
1139 #if defined(_PC98DO)
1140 boot_mode = state_fio->FgetInt32();