3 NEC PC-8001 Emulator 'ePC-8001'
4 NEC PC-8001mkII Emulator 'ePC-8001mkII'
5 NEC PC-8001mkIISR Emulator 'ePC-8001mkIISR'
6 NEC PC-8801 Emulator 'ePC-8801'
7 NEC PC-8801mkII Emulator 'ePC-8801mkII'
8 NEC PC-8801MA Emulator 'ePC-8801MA'
10 Author : Takeda.Toshiya
17 #include "../../emu.h"
18 #include "../device.h"
23 #include "../pcm1bit.h"
24 //#include "../pcpr201.h"
25 #include "../prnfile.h"
26 #include "../upd1990a.h"
27 #if defined(SUPPORT_PC88_OPN1) || defined(SUPPORT_PC88_OPN2)
28 #include "../ym2203.h"
34 #include "../pc80s31k.h"
35 #include "../upd765a.h"
38 #include "../debugger.h"
41 #ifdef SUPPORT_PC88_CDROM
42 #include "../scsi_cdrom.h"
43 #include "../scsi_host.h"
46 #ifdef SUPPORT_PC88_HMB20
47 #include "../ym2151.h"
50 #ifdef SUPPORT_PC88_GSX8800
51 #include "../ay_3_891x.h"
54 #if defined(SUPPORT_PC88_GSX8800) || defined(SUPPORT_PC88_PCG8100) || defined(SUPPORT_PC88_16BIT)
58 #ifdef SUPPORT_PC88_JAST
59 #include "../pcm8bit.h"
62 #if defined(SUPPORT_PC88_16BIT)
66 #include "../memory.h"
69 #ifdef SUPPORT_M88_DISKDRV
76 #ifdef SUPPORT_M88_DISKDRV
77 using PC88DEV::DiskIO;
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 VM::VM(EMU_TEMPLATE* parent_emu) : VM_TEMPLATE(parent_emu)
86 #if defined(PC8001_VARIANT)
88 if(config.boot_mode != MODE_PC80_N) {
89 config.boot_mode = MODE_PC80_N;
91 // 8inch floppy drives are not supported
92 config.dipswitch &= ~DIPSWITCH_FDD_8INCH;
93 #elif defined(_PC8001MK2)
94 if(config.boot_mode == MODE_PC80_V2) {
95 config.boot_mode = MODE_PC80_V1;
99 #if !defined(PC8801SR_VARIANT)
100 if(config.boot_mode == MODE_PC88_V1H || config.boot_mode == MODE_PC88_V2 || config.boot_mode == MODE_PC88_V2CD) {
101 config.boot_mode = MODE_PC88_V1S;
104 #if defined(_PC8801MK2) || defined(PC8801SR_VARIANT)
105 // 5inch floppy drives are always existing
106 config.dipswitch |= DIPSWITCH_FDD_5INCH;
109 boot_mode = config.boot_mode;
112 first_device = last_device = NULL;
113 dummy = new DEVICE(this, emu); // must be 1st device
115 pc88event = new EVENT(this, emu);
117 pc88 = new PC88(this, emu);
118 pc88sio = new I8251(this, emu);
119 pc88pio = new I8255(this, emu);
120 pc88pcm = new PCM1BIT(this, emu);
122 // pc88pcm->set_context_debugger(new DEBUGGER(this, emu));
124 pc88rtc = new UPD1990A(this, emu);
125 // pc88rtc->set_device_name(_T("uPD1990A RTC (PC-8801)"));
126 // pc88rtc->set_context_event_manager(pc88event);
127 if(config.printer_type == 0) {
128 pc88prn = new PRNFILE(this, emu);
129 // pc88prn->set_context_event_manager(pc88event);
130 // } else if(config.printer_type == 1) {
131 // pc88prn = new PCPR201(this, emu);
132 // pc88prn->set_context_event_manager(pc88event);
133 #ifdef SUPPORT_PC88_JAST
134 } else if(config.printer_type == 2) {
135 pc88prn = new PCM8BIT(this, emu);
136 // pc88prn->set_context_event_manager(pc88event);
141 pc88cpu = new Z80(this, emu);
142 // pc88cpu->set_context_event_manager(pc88event);
144 if(config.dipswitch & DIPSWITCH_FDD_5INCH) {
145 pc88sub = new PC80S31K(this, emu);
146 pc88sub->set_device_name(_T("PC-80S31K (Sub)"));
147 // pc88sub->set_context_event_manager(pc88event);
148 pc88pio_sub = new I8255(this, emu);
149 pc88pio_sub->set_device_name(_T("8255 PIO (Sub)"));
150 // pc88pio_sub->set_context_event_manager(pc88event);
151 pc88fdc_sub = new UPD765A(this, emu);
152 pc88fdc_sub->set_device_name(_T("uPD765A FDC (Sub)"));
153 // pc88fdc_sub->set_context_event_manager(pc88event);
154 pc88noise_seek = new NOISE(this, emu);
155 // pc88noise_seek->set_context_event_manager(pc88event);
156 pc88noise_head_down = new NOISE(this, emu);
157 // pc88noise_head_down->set_context_event_manager(pc88event);
158 pc88noise_head_up = new NOISE(this, emu);
159 // pc88noise_head_up->set_context_event_manager(pc88event);
160 pc88cpu_sub = new Z80(this, emu);
161 pc88cpu_sub->set_device_name(_T("Z80 CPU (Sub)"));
162 // pc88cpu_sub->set_context_event_manager(pc88event);
167 pc88noise_seek = pc88noise_head_down = pc88noise_head_up = NULL;
170 #ifdef SUPPORT_PC88_FDD_8INCH
171 if(config.dipswitch & DIPSWITCH_FDD_8INCH) {
172 pc88fdc_8inch = new UPD765A(this, emu);
173 pc88fdc_8inch->set_device_name(_T("uPD765A FDC (8inch)"));
174 // pc88fdc_8inch->set_context_event_manager(pc88event);
175 pc88noise_8inch_seek = new NOISE(this, emu);
176 // pc88noise_8inch_seek->set_context_event_manager(pc88event);
177 pc88noise_8inch_head_down = new NOISE(this, emu);
178 // pc88noise_8inch_head_down->set_context_event_manager(pc88event);
179 pc88noise_8inch_head_up = new NOISE(this, emu);
180 // pc88noise_8inch_head_up->set_context_event_manager(pc88event);
182 pc88fdc_8inch = NULL;
183 pc88noise_8inch_seek = pc88noise_8inch_head_down = pc88noise_8inch_head_up = NULL;
186 #ifdef SUPPORT_PC88_CDROM
187 pc88scsi_host = new SCSI_HOST(this, emu);
188 // pc88scsi_host->set_context_event_manager(pc88event);
189 pc88scsi_cdrom = new SCSI_CDROM(this, emu);
190 // pc88scsi_cdrom->set_context_event_manager(pc88event);
192 #if defined(_PC8801MA)
194 // 0: 44h:OPNA A4h:None PC-8801FH/MH or later
195 // 1: 44h:OPN A4h:None PC-8801mkIISR/TR/FR/MR
196 // 2: 44h:OPN A4h:OPNA PC-8801mkIISR/TR/FR/MR + PC-8801-23
197 // 3: 44h:OPN A4h:OPN PC-8801mkIISR/TR/FR/MR + PC-8801-11
198 // 4: 44h:OPNA A4h:OPNA PC-8801FH/MH or later + PC-8801-24
199 // 5: 44h:OPNA A4h:OPN PC-8801FH/MH or later + PC-8801-11
200 pc88opn1 = new YM2203(this, emu);
201 if(config.sound_type == 0 || config.sound_type == 4 || config.sound_type == 5) {
202 pc88opn1->is_ym2608 = true;
203 pc88opn1->set_device_name(_T("YM2608 OPNA #1"));
205 pc88opn1->is_ym2608 = false;
206 pc88opn1->set_device_name(_T("YM2203 OPN #1"));
208 if(config.sound_type >= 2) {
209 pc88opn2 = new YM2203(this, emu);
210 if(config.sound_type == 2 || config.sound_type == 4) {
211 pc88opn2->is_ym2608 = true;
212 pc88opn2->set_device_name(_T("YM2608 OPNA #2"));
213 } else if(config.sound_type == 3 || config.sound_type == 5) {
214 pc88opn2->is_ym2608 = false;
215 pc88opn2->set_device_name(_T("YM2203 OPN #2"));
220 #elif defined(_PC8001SR)
222 // 0: 44h:OPN A4h:None PC-8001mkIISR
223 // 1: 44h:OPN A4h:OPN PC-8001mkIISR + PC-8801-11
224 pc88opn1 = new YM2203(this, emu);
225 pc88opn1->is_ym2608 = false;
226 pc88opn1->set_device_name(_T("YM2203 OPN #1"));
227 if(config.sound_type == 1) {
228 pc88opn2 = new YM2203(this, emu);
229 // pc88opn2->set_context_event_manager(pc88event);
230 pc88opn2->is_ym2608 = false;
231 pc88opn2->set_device_name(_T("YM2203 OPN #2"));
235 #elif defined(_PC8001MK2) || defined(_PC8801) || defined(_PC8801MK2)
236 // 0: 44h:None A4h:None PC-8001mkII
237 // 1: 44h:None A4h:OPN PC-8001mkII + PC-8801-11
238 if(config.sound_type == 1) {
239 pc88opn2 = new YM2203(this, emu);
240 pc88opn2->is_ym2608 = false;
241 pc88opn2->set_device_name(_T("YM2203 OPN #2"));
246 #if defined(SUPPORT_PC88_OPN1)
247 pc88opn1 = new YM2203(this, emu);
248 #if defined(SUPPORT_PC88_OPNA)
249 pc88opn1->is_ym2608 = true;
250 pc88opn1->set_device_name(_T("YM2608 OPNA #1"));
252 pc88opn1->is_ym2608 = false;
253 pc88opn1->set_device_name(_T("YM2203 OPN #1"));
256 #if defined(SUPPORT_PC88_OPN2)
257 pc88opn2 = new YM2203(this, emu);
258 #if defined(SUPPORT_PC88_OPNA)
259 pc88opn2->is_ym2608 = true;
260 pc88opn2->set_device_name(_T("YM2608 OPNA #2"));
262 pc88opn2->is_ym2608 = false;
263 pc88opn2->set_device_name(_T("YM2203 OPN #2"));
268 #ifdef SUPPORT_PC88_OPN1
269 if(pc88opn1 != NULL) {
270 pc88opn1->set_context_debugger(new DEBUGGER(this, emu));
273 #ifdef SUPPORT_PC88_OPN2
274 if(pc88opn2 != NULL) {
275 pc88opn2->set_context_debugger(new DEBUGGER(this, emu));
279 #ifdef SUPPORT_PC88_HMB20
280 if(config.dipswitch & DIPSWITCH_HMB20) {
281 pc88opm = new YM2151(this, emu);
283 pc88opm->set_context_debugger(new DEBUGGER(this, emu));
285 pc88opm->set_device_name(_T("YM2151 OPM (HMB-20)"));
290 #ifdef SUPPORT_PC88_GSX8800
291 if(config.dipswitch & DIPSWITCH_GSX8800) {
292 // pc88gsx_pit = new I8253(this, emu);
293 // pc88gsx_pit->set_device_name(_T("8253 PIT (GSX-8800)"));
294 // pc88gsx_pit->set_context_event_manager(pc88event);
295 pc88gsx_psg1 = new AY_3_891X(this, emu);
296 pc88gsx_psg1->set_device_name(_T("AY-3-8910 PSG #1 (GSX-8800)"));
297 pc88gsx_psg2 = new AY_3_891X(this, emu);
298 pc88gsx_psg2->set_device_name(_T("AY-3-8910 PSG #2 (GSX-8800)"));
299 pc88gsx_psg3 = new AY_3_891X(this, emu);
300 pc88gsx_psg3->set_device_name(_T("AY-3-8910 PSG #3 (GSX-8800)"));
301 pc88gsx_psg4 = new AY_3_891X(this, emu);
302 pc88gsx_psg4->set_device_name(_T("AY-3-8910 PSG #4 (GSX-8800)"));
304 pc88gsx_psg1->set_context_debugger(new DEBUGGER(this, emu));
305 pc88gsx_psg2->set_context_debugger(new DEBUGGER(this, emu));
306 pc88gsx_psg3->set_context_debugger(new DEBUGGER(this, emu));
307 pc88gsx_psg4->set_context_debugger(new DEBUGGER(this, emu));
310 // pc88gsx_pit = NULL;
311 pc88gsx_psg1 = pc88gsx_psg2 = pc88gsx_psg3 = pc88gsx_psg4 = NULL;
314 #ifdef SUPPORT_PC88_PCG8100
315 if(config.dipswitch & DIPSWITCH_PCG8100) {
316 pc88pcg_pit = new I8253(this, emu);
317 pc88pcg_pit->set_device_name(_T("8253 PIT (PCG-8100)"));
318 pc88pcg_pcm1 = new PCM1BIT(this, emu);
319 pc88pcg_pcm1->set_device_name(_T("1-Bit PCM Sound (PCG-8100 #1)"));
320 pc88pcg_pcm2 = new PCM1BIT(this, emu);
321 pc88pcg_pcm2->set_device_name(_T("1-Bit PCM Sound (PCG-8100 #2)"));
322 pc88pcg_pcm3 = new PCM1BIT(this, emu);
323 pc88pcg_pcm3->set_device_name(_T("1-Bit PCM Sound (PCG-8100 #3)"));
326 pc88pcg_pcm1 = pc88pcg_pcm2 = pc88pcg_pcm3 = NULL;
329 #ifdef SUPPORT_PC88_16BIT
330 if(config.dipswitch & DIPSWITCH_16BIT) {
331 pc88pit_16bit = new I8253(this, emu);
332 pc88pio_16bit = new I8255(this, emu);
333 pc88pic_16bit = new I8259(this, emu);
334 pc88cpu_16bit = new I86(this, emu);
335 pc88cpu_16bit->device_model = INTEL_8086;
336 pc88io_16bit = new IO(this, emu);
337 pc88mem_16bit = new MEMORY(this, emu);
339 pc88cpu_16bit = NULL;
342 #ifdef SUPPORT_M88_DISKDRV
343 if(config.dipswitch & DIPSWITCH_M88_DISKDRV) {
344 pc88diskio = new DiskIO(this, emu);
345 // pc88diskio->set_context_event_manager(pc88event);
351 // set cpu device contexts
352 #ifdef SUPPORT_PC88_HIGH_CLOCK
353 pc88event->set_context_cpu(pc88cpu, (config.cpu_type == 1) ? 3993624 : 7987248);
355 pc88event->set_context_cpu(pc88cpu, 3993624);
357 if(pc88cpu_sub != NULL) {
358 pc88event->set_context_cpu(pc88cpu_sub, 3993624);
360 #ifdef SUPPORT_PC88_16BIT
361 if(pc88cpu_16bit != NULL) {
362 pc88event->set_context_cpu(pc88cpu_16bit, 7987248);
366 // set sound device contexts
367 pc88event->set_context_sound(pc88pcm);
368 #ifdef SUPPORT_PC88_CDROM
369 pc88event->set_context_sound(pc88scsi_cdrom);
371 #ifdef SUPPORT_PC88_OPN1
372 if(pc88opn1 != NULL) {
373 pc88event->set_context_sound(pc88opn1);
376 #ifdef SUPPORT_PC88_OPN2
377 if(pc88opn2 != NULL) {
378 pc88event->set_context_sound(pc88opn2);
381 #ifdef SUPPORT_PC88_HMB20
382 if(config.dipswitch & DIPSWITCH_HMB20) {
383 pc88event->set_context_sound(pc88opm);
386 #ifdef SUPPORT_PC88_GSX8800
387 if(config.dipswitch & DIPSWITCH_GSX8800) {
388 pc88event->set_context_sound(pc88gsx_psg1);
389 pc88event->set_context_sound(pc88gsx_psg2);
390 pc88event->set_context_sound(pc88gsx_psg3);
391 pc88event->set_context_sound(pc88gsx_psg4);
394 #ifdef SUPPORT_PC88_PCG8100
395 if(config.dipswitch & DIPSWITCH_PCG8100) {
396 pc88event->set_context_sound(pc88pcg_pcm1);
397 pc88event->set_context_sound(pc88pcg_pcm2);
398 pc88event->set_context_sound(pc88pcg_pcm3);
401 #ifdef SUPPORT_PC88_JAST
402 if(config.printer_type == 2) {
403 pc88event->set_context_sound(pc88prn);
406 if(config.dipswitch & DIPSWITCH_FDD_5INCH) {
407 pc88event->set_context_sound(pc88noise_seek);
408 pc88event->set_context_sound(pc88noise_head_down);
409 pc88event->set_context_sound(pc88noise_head_up);
411 #ifdef SUPPORT_PC88_FDD_8INCH
412 if(config.dipswitch & DIPSWITCH_FDD_8INCH) {
413 pc88event->set_context_sound(pc88noise_8inch_seek);
414 pc88event->set_context_sound(pc88noise_8inch_head_down);
415 pc88event->set_context_sound(pc88noise_8inch_head_up);
419 // set other device contexts
420 pc88->set_context_cpu(pc88cpu);
421 pc88->set_context_pcm(pc88pcm);
422 pc88->set_context_pio(pc88pio);
423 pc88->set_context_prn(pc88prn);
424 pc88->set_context_rtc(pc88rtc);
425 pc88->set_context_sio(pc88sio);
426 #ifdef SUPPORT_PC88_FDD_8INCH
427 if(config.dipswitch & DIPSWITCH_FDD_8INCH) {
428 pc88->set_context_fdc_8inch(pc88fdc_8inch);
431 #ifdef SUPPORT_PC88_CDROM
432 pc88->set_context_scsi_host(pc88scsi_host);
433 pc88->set_context_scsi_cdrom(pc88scsi_cdrom);
435 #ifdef SUPPORT_PC88_OPN1
436 if(pc88opn1 != NULL) {
437 pc88->set_context_opn1(pc88opn1);
440 #ifdef SUPPORT_PC88_OPN2
441 if(pc88opn2 != NULL) {
442 pc88->set_context_opn2(pc88opn2);
445 #ifdef SUPPORT_PC88_HMB20
446 if(config.dipswitch & DIPSWITCH_HMB20) {
447 pc88->set_context_opm(pc88opm);
450 #ifdef SUPPORT_PC88_GSX8800
451 if(config.dipswitch & DIPSWITCH_GSX8800) {
452 // pc88->set_context_gsx_pit(pc88gsx_pit);
453 pc88->set_context_gsx_psg1(pc88gsx_psg1);
454 pc88->set_context_gsx_psg2(pc88gsx_psg2);
455 pc88->set_context_gsx_psg3(pc88gsx_psg3);
456 pc88->set_context_gsx_psg4(pc88gsx_psg4);
459 #ifdef SUPPORT_PC88_PCG8100
460 if(config.dipswitch & DIPSWITCH_PCG8100) {
461 pc88->set_context_pcg_pit(pc88pcg_pit);
462 pc88->set_context_pcg_pcm1(pc88pcg_pcm1);
463 pc88->set_context_pcg_pcm2(pc88pcg_pcm2);
464 pc88->set_context_pcg_pcm3(pc88pcg_pcm3);
467 #ifdef SUPPORT_PC88_16BIT
468 if(config.dipswitch & DIPSWITCH_16BIT) {
469 pc88->set_context_pio_16bit(pc88pio_16bit);
472 #ifdef SUPPORT_M88_DISKDRV
473 if(config.dipswitch & DIPSWITCH_M88_DISKDRV) {
474 pc88->set_context_diskio(pc88diskio);
477 pc88cpu->set_context_mem(pc88);
478 pc88cpu->set_context_io(pc88);
479 pc88cpu->set_context_intr(pc88);
481 pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
483 pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
484 pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
486 if(config.dipswitch & DIPSWITCH_FDD_5INCH) {
487 pc88sub->set_context_cpu(pc88cpu_sub);
488 pc88sub->set_context_fdc(pc88fdc_sub);
489 pc88sub->set_context_pio(pc88pio_sub);
490 pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
491 pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
492 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
493 pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
494 pc88pio->clear_ports_by_cmdreg = true;
495 pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
496 pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
497 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
498 pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
499 pc88pio_sub->clear_ports_by_cmdreg = true;
500 pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
501 pc88fdc_sub->set_context_noise_seek(pc88noise_seek);
502 pc88fdc_sub->set_context_noise_head_down(pc88noise_head_down);
503 pc88fdc_sub->set_context_noise_head_up(pc88noise_head_up);
504 pc88cpu_sub->set_context_mem(pc88sub);
505 pc88cpu_sub->set_context_io(pc88sub);
506 pc88cpu_sub->set_context_intr(pc88sub);
508 pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
512 #ifdef SUPPORT_PC88_FDD_8INCH
513 if(config.dipswitch & DIPSWITCH_FDD_8INCH) {
514 pc88fdc_8inch->set_context_irq(pc88, SIG_PC88_8INCH_IRQ, 1);
515 pc88fdc_8inch->set_context_drq(pc88, SIG_PC88_8INCH_DRQ, 1);
516 pc88fdc_8inch->set_context_noise_seek(pc88noise_8inch_seek);
517 pc88fdc_8inch->set_context_noise_head_down(pc88noise_8inch_head_down);
518 pc88fdc_8inch->set_context_noise_head_up(pc88noise_8inch_head_up);
521 #ifdef SUPPORT_PC88_CDROM
522 pc88scsi_cdrom->scsi_id = 0;
523 pc88scsi_cdrom->set_context_interface(pc88scsi_host);
524 pc88scsi_host->set_context_target(pc88scsi_cdrom);
525 pc88scsi_host->set_context_drq(pc88, SIG_PC88_SCSI_DRQ, 1);
527 #ifdef SUPPORT_PC88_OPN1
528 if(pc88opn1 != NULL) {
529 pc88opn1->set_context_irq(pc88, SIG_PC88_OPN1_IRQ, 1);
532 #ifdef SUPPORT_PC88_OPN2
533 if(pc88opn2 != NULL) {
534 pc88opn2->set_context_irq(pc88, SIG_PC88_OPN2_IRQ, 1);
537 #ifdef SUPPORT_PC88_GSX8800
538 // if(config.dipswitch & DIPSWITCH_GSX8800) {
539 // pc88gsx_pit->set_context_ch0(pc88, SIG_PC88_GSX_IRQ, 1);
540 // pc88gsx_pit->set_context_ch1(pc88gsx_pit, SIG_I8253_CLOCK_2, 1);
541 // pc88gsx_pit->set_constant_clock(0, 1996800);
542 // pc88gsx_pit->set_constant_clock(1, 1996800);
545 #ifdef SUPPORT_PC88_PCG8100
546 if(config.dipswitch & DIPSWITCH_PCG8100) {
547 pc88pcg_pit->set_context_ch0(pc88pcg_pcm1, SIG_PCM1BIT_SIGNAL, 1);
548 pc88pcg_pit->set_context_ch1(pc88pcg_pcm2, SIG_PCM1BIT_SIGNAL, 1);
549 pc88pcg_pit->set_context_ch2(pc88pcg_pcm3, SIG_PCM1BIT_SIGNAL, 1);
550 pc88pcg_pit->set_constant_clock(0, 3993624);
551 pc88pcg_pit->set_constant_clock(1, 3993624);
552 pc88pcg_pit->set_constant_clock(2, 3993624);
555 #ifdef SUPPORT_PC88_16BIT
556 if(config.dipswitch & DIPSWITCH_16BIT) {
557 memset(pc88rom_16bit, 0xff, sizeof(pc88rom_16bit));
558 memset(pc88ram_16bit, 0x00, sizeof(pc88ram_16bit));
560 FILEIO* fio = new FILEIO();
561 if(fio->Fopen(create_local_path(_T("PC-8801-16_I86.ROM")), FILEIO_READ_BINARY)) {
562 fio->Fread(pc88rom_16bit, sizeof(pc88rom_16bit), 1);
567 pc88mem_16bit->set_memory_rw(0, sizeof(pc88ram_16bit) - 1, pc88ram_16bit);
568 pc88mem_16bit->set_memory_r(0xff000, 0xfffff, pc88rom_16bit);
570 pc88io_16bit->set_iomap_alias_rw(0x00, pc88pit_16bit, 0);
571 pc88io_16bit->set_iomap_alias_rw(0x02, pc88pit_16bit, 1);
572 pc88io_16bit->set_iomap_alias_rw(0x04, pc88pit_16bit, 2);
573 pc88io_16bit->set_iomap_alias_w (0x06, pc88pit_16bit, 3);
574 pc88io_16bit->set_iomap_alias_rw(0x10, pc88pio_16bit, 0);
575 pc88io_16bit->set_iomap_alias_rw(0x12, pc88pio_16bit, 1);
576 pc88io_16bit->set_iomap_alias_rw(0x14, pc88pio_16bit, 2);
577 pc88io_16bit->set_iomap_alias_w (0x16, pc88pio_16bit, 3);
578 pc88io_16bit->set_iomap_alias_rw(0x20, pc88pic_16bit, 0);
579 pc88io_16bit->set_iomap_alias_rw(0x22, pc88pic_16bit, 1);
581 pc88pit_16bit->set_context_ch0(pc88pic_16bit, SIG_I8259_IR0, 1);
582 pc88pit_16bit->set_context_ch1(pc88pit_16bit, SIG_I8253_CLOCK_2, 1);
583 pc88pit_16bit->set_context_ch2(pc88pic_16bit, SIG_I8259_IR7, 1);
584 pc88pit_16bit->set_constant_clock(0, 2995218);
585 pc88pit_16bit->set_constant_clock(1, 2995218);
586 pc88pio_16bit->set_context_port_a(pc88, SIG_PC88_16BIT_PORTA, 0xff, 0);
587 pc88pio_16bit->set_context_port_c(pc88, SIG_PC88_16BIT_PORTC, 0x82, 0); // PC7+PC1
588 pc88pio_16bit->set_context_port_c(pc88pic_16bit, SIG_I8259_IR1, 0x01, 0); // PC0
589 pc88pio_16bit->set_context_port_c(pc88pic_16bit, SIG_I8259_IR2, 0x08, 0); // PC3
590 pc88pic_16bit->set_context_cpu(pc88cpu_16bit);
591 pc88cpu_16bit->set_context_mem(pc88mem_16bit);
592 pc88cpu_16bit->set_context_io(pc88io_16bit);
593 pc88cpu_16bit->set_context_intr(pc88pic_16bit);
595 pc88cpu_16bit->set_context_debugger(new DEBUGGER(this, emu));
601 // initialize all devices
602 #if defined(__GIT_REPO_VERSION)
603 set_git_repo_version(__GIT_REPO_VERSION);
605 initialize_devices();
607 // for(DEVICE* device = first_device; device; device = device->next_device) {
608 // printf("DEV NAME=%s ID=%d\n", device->this_device_name, device->this_device_id);
609 // device->initialize();
611 #ifdef SUPPORT_PC88_FDD_8INCH
612 if(config.dipswitch & DIPSWITCH_FDD_8INCH) {
613 pc88fdc_8inch->set_drive_type(0, DRIVE_TYPE_2HD);
614 pc88fdc_8inch->set_drive_type(1, DRIVE_TYPE_2HD);
615 // pc88fdc_8inch->write_signal(SIG_UPD765A_MOTOR, 1, 1);
622 // delete all devices
624 // for(DEVICE* device = first_device; device;) {
625 // DEVICE *next_device = device->next_device;
626 // device->release();
628 // device = next_device;
633 // ----------------------------------------------------------------------------
634 // drive virtual machine
635 // ----------------------------------------------------------------------------
640 for(DEVICE* device = first_device; device; device = device->next_device) {
643 for(DEVICE* device = first_device; device; device = device->next_device) {
647 // initial device settings
648 #ifdef SUPPORT_PC88_OPN1
649 if(pc88opn1 != NULL) {
650 pc88opn1->set_reg(0x29, 3); // for Misty Blue
653 if(pc88pio_sub != NULL) {
654 pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
656 pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
664 double VM::get_frame_rate()
666 return pc88event->get_frame_rate();
669 // ----------------------------------------------------------------------------
671 // ----------------------------------------------------------------------------
674 DEVICE *VM::get_cpu(int index)
678 } else if(index == 1) {
680 #ifdef SUPPORT_PC88_16BIT
681 } else if(index == 2) {
682 return pc88cpu_16bit;
689 // ----------------------------------------------------------------------------
691 // ----------------------------------------------------------------------------
693 void VM::draw_screen()
698 // ----------------------------------------------------------------------------
700 // ----------------------------------------------------------------------------
702 void VM::initialize_sound(int rate, int samples)
704 // init sound manager
705 pc88event->initialize_sound(rate, samples);
708 pc88pcm->initialize_sound(rate, 8000);
709 #ifdef SUPPORT_PC88_OPN1
710 if(pc88opn1 != NULL) {
711 if(pc88opn1->is_ym2608) {
712 pc88opn1->initialize_sound(rate, 7987248, samples, 0, 0);
714 pc88opn1->initialize_sound(rate, 3993624, samples, 0, 0);
718 #ifdef SUPPORT_PC88_OPN2
719 if(pc88opn2 != NULL) {
720 if(pc88opn2->is_ym2608) {
721 pc88opn2->initialize_sound(rate, 7987248, samples, 0, 0);
723 pc88opn2->initialize_sound(rate, 3993624, samples, 0, 0);
727 #ifdef SUPPORT_PC88_HMB20
728 if(config.dipswitch & DIPSWITCH_HMB20) {
729 pc88opm->initialize_sound(rate, 4000000, samples, 0);
732 #ifdef SUPPORT_PC88_GSX8800
733 if(config.dipswitch & DIPSWITCH_GSX8800) {
734 pc88gsx_psg1->initialize_sound(rate, 3993624, samples, 0, 0);
735 pc88gsx_psg2->initialize_sound(rate, 3993624, samples, 0, 0);
736 pc88gsx_psg3->initialize_sound(rate, 3993624, samples, 0, 0);
737 pc88gsx_psg4->initialize_sound(rate, 3993624, samples, 0, 0);
740 #ifdef SUPPORT_PC88_PCG8100
741 if(config.dipswitch & DIPSWITCH_PCG8100) {
742 pc88pcg_pcm1->initialize_sound(rate, 8000);
743 pc88pcg_pcm2->initialize_sound(rate, 8000);
744 pc88pcg_pcm3->initialize_sound(rate, 8000);
747 #ifdef SUPPORT_PC88_JAST
748 if(config.printer_type == 2) {
749 PCM8BIT *pcm8 = (PCM8BIT *)pc88prn;
750 pcm8->initialize_sound(rate, 32000);
755 uint16_t* VM::create_sound(int* extra_frames)
757 return pc88event->create_sound(extra_frames);
760 int VM::get_sound_buffer_ptr()
762 return pc88event->get_sound_buffer_ptr();
765 #ifdef USE_SOUND_VOLUME
766 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
768 #ifdef SUPPORT_PC88_OPN1
770 if(pc88opn1 != NULL) {
771 pc88opn1->set_volume(0, decibel_l, decibel_r);
776 if(pc88opn1 != NULL) {
777 pc88opn1->set_volume(1, decibel_l, decibel_r);
781 #ifdef SUPPORT_PC88_OPNA
783 if(pc88opn1 != NULL && pc88opn1->is_ym2608) {
784 pc88opn1->set_volume(2, decibel_l, decibel_r);
789 if(pc88opn1 != NULL && pc88opn1->is_ym2608) {
790 pc88opn1->set_volume(3, decibel_l, decibel_r);
796 #ifdef SUPPORT_PC88_OPN2
798 if(pc88opn2 != NULL) {
799 pc88opn2->set_volume(0, decibel_l, decibel_r);
804 if(pc88opn2 != NULL) {
805 pc88opn2->set_volume(1, decibel_l, decibel_r);
809 #ifdef SUPPORT_PC88_OPNA
811 if(pc88opn2 != NULL && pc88opn2->is_ym2608) {
812 pc88opn2->set_volume(2, decibel_l, decibel_r);
817 if(pc88opn2 != NULL && pc88opn2->is_ym2608) {
818 pc88opn2->set_volume(3, decibel_l, decibel_r);
824 #ifdef SUPPORT_PC88_CDROM
826 pc88scsi_cdrom->set_volume(0, decibel_l, decibel_r);
830 #ifdef SUPPORT_PC88_HMB20
832 if(pc88opm != NULL) {
833 pc88opm->set_volume(0, decibel_l, decibel_r);
838 #ifdef SUPPORT_PC88_GSX8800
840 if(pc88gsx_psg1 != NULL) {
841 pc88gsx_psg1->set_volume(0, decibel_l, decibel_r);
843 if(pc88gsx_psg2 != NULL) {
844 pc88gsx_psg2->set_volume(0, decibel_l, decibel_r);
846 if(pc88gsx_psg3 != NULL) {
847 pc88gsx_psg3->set_volume(0, decibel_l, decibel_r);
849 if(pc88gsx_psg4 != NULL) {
850 pc88gsx_psg4->set_volume(0, decibel_l, decibel_r);
855 #ifdef SUPPORT_PC88_PCG8100
857 if(pc88pcg_pcm1 != NULL) {
858 pc88pcg_pcm1->set_volume(0, decibel_l, decibel_r);
860 if(pc88pcg_pcm2 != NULL) {
861 pc88pcg_pcm2->set_volume(0, decibel_l, decibel_r);
863 if(pc88pcg_pcm3 != NULL) {
864 pc88pcg_pcm3->set_volume(0, decibel_l, decibel_r);
869 #ifdef SUPPORT_PC88_JAST
871 if(config.printer_type == 2) {
872 PCM8BIT *pcm8 = (PCM8BIT *)pc88prn;
873 pcm8->set_volume(0, decibel_l, decibel_r);
879 pc88pcm->set_volume(0, decibel_l, decibel_r);
883 if(pc88noise_seek != NULL) {
884 pc88noise_seek->set_volume(0, decibel_l, decibel_r);
886 if(pc88noise_head_down != NULL) {
887 pc88noise_head_down->set_volume(0, decibel_l, decibel_r);
889 if(pc88noise_head_up != NULL) {
890 pc88noise_head_up->set_volume(0, decibel_l, decibel_r);
892 #ifdef SUPPORT_PC88_FDD_8INCH
893 if(pc88noise_8inch_seek != NULL) {
894 pc88noise_8inch_seek->set_volume(0, decibel_l, decibel_r);
896 if(pc88noise_8inch_head_down != NULL) {
897 pc88noise_8inch_head_down->set_volume(0, decibel_l, decibel_r);
899 if(pc88noise_8inch_head_up != NULL) {
900 pc88noise_8inch_head_up->set_volume(0, decibel_l, decibel_r);
908 // ----------------------------------------------------------------------------
910 // ----------------------------------------------------------------------------
912 void VM::key_down(int code, bool repeat)
914 pc88->key_down(code, repeat);
917 void VM::key_up(int code)
921 bool VM::get_caps_locked()
923 return pc88->get_caps_locked();
926 bool VM::get_kana_locked()
928 return pc88->get_kana_locked();
931 // ----------------------------------------------------------------------------
933 // ----------------------------------------------------------------------------
935 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
937 UPD765A *controller = get_floppy_disk_controller(drv);
939 if(controller != NULL) {
940 controller->open_disk(drv & 1, file_path, bank);
944 void VM::close_floppy_disk(int drv)
946 UPD765A *controller = get_floppy_disk_controller(drv);
948 if(controller != NULL) {
949 controller->close_disk(drv & 1);
953 bool VM::is_floppy_disk_connected(int drv)
955 DISK *handler = get_floppy_disk_handler(drv);
957 return (handler != NULL);
960 bool VM::is_floppy_disk_inserted(int drv)
962 DISK *handler = get_floppy_disk_handler(drv);
964 if(handler != NULL) {
965 return handler->inserted;
970 void VM::is_floppy_disk_protected(int drv, bool value)
972 DISK *handler = get_floppy_disk_handler(drv);
974 if(handler != NULL) {
975 handler->write_protected = value;
979 bool VM::is_floppy_disk_protected(int drv)
981 DISK *handler = get_floppy_disk_handler(drv);
983 if(handler != NULL) {
984 return handler->write_protected;
989 uint32_t VM::is_floppy_disk_accessed()
993 for(int drv = 0; drv < USE_FLOPPY_DISK; drv += 2) {
994 UPD765A *controller = get_floppy_disk_controller(drv);
996 if(controller != NULL) {
997 status |= (controller->read_signal(0) & 3) << drv;
1003 uint32_t VM::floppy_disk_indicator_color()
1005 if(pc88fdc_sub != nullptr) {
1006 return ((pc88fdc_sub->get_drive_type(0) == DRIVE_TYPE_2HD) ? 1 : 0) |
1007 ((pc88fdc_sub->get_drive_type(1) == DRIVE_TYPE_2HD) ? 2 : 0);
1012 UPD765A *VM::get_floppy_disk_controller(int drv)
1014 if(drv == 0 || drv == 1) {
1017 #ifdef SUPPORT_PC88_FDD_8INCH
1018 if(drv == 2 || drv == 3) {
1019 return pc88fdc_8inch;
1025 DISK *VM::get_floppy_disk_handler(int drv)
1027 UPD765A *controller = get_floppy_disk_controller(drv);
1029 if(controller != NULL) {
1030 return controller->get_disk_handler(drv & 1);
1035 void VM::play_tape(int drv, const _TCHAR* file_path)
1037 pc88->play_tape(file_path);
1040 void VM::rec_tape(int drv, const _TCHAR* file_path)
1042 pc88->rec_tape(file_path);
1045 void VM::close_tape(int drv)
1050 bool VM::is_tape_inserted(int drv)
1052 return pc88->is_tape_inserted();
1055 #ifdef SUPPORT_PC88_CDROM
1056 void VM::open_compact_disc(int drv, const _TCHAR* file_path)
1058 pc88scsi_cdrom->open(file_path);
1061 void VM::close_compact_disc(int drv)
1063 pc88scsi_cdrom->close();
1066 bool VM::is_compact_disc_inserted(int drv)
1068 return pc88scsi_cdrom->mounted();
1071 uint32_t VM::is_compact_disc_accessed()
1073 return pc88scsi_cdrom->accessed();
1077 bool VM::is_frame_skippable()
1079 // return event->is_frame_skippable();
1080 return pc88->is_frame_skippable();
1083 void VM::update_config()
1085 if(boot_mode != config.boot_mode) {
1086 // boot mode is changed !!!
1087 boot_mode = config.boot_mode;
1090 for(DEVICE* device = first_device; device; device = device->next_device) {
1091 device->update_config();
1096 double VM::get_current_usec()
1098 if(pc88event == NULL) return 0.0;
1099 return pc88event->get_current_usec();
1102 uint64_t VM::get_current_clock_uint64()
1104 if(pc88event == NULL) return (uint64_t)0;
1105 return pc88event->get_current_clock_uint64();
1108 #define STATE_VERSION 13
1110 bool VM::process_state(FILEIO* state_fio, bool loading)
1112 if(!(VM_TEMPLATE::process_state_core(state_fio, loading, STATE_VERSION))) {
1115 // Machine specified.
1116 #ifdef SUPPORT_PC88_16BIT
1117 state_fio->StateArray(pc88ram_16bit, sizeof(pc88ram_16bit), 1);
1119 state_fio->StateValue(boot_mode);