OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc9801 / pc9801.cpp
1 /*
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'
13
14         Author : Takeda.Toshiya
15         Date   : 2010.09.15-
16
17         [ virtual machine ]
18 */
19
20 #include "pc9801.h"
21 #include "../../emu.h"
22 #include "../device.h"
23 #include "../event.h"
24
25 #if defined(SUPPORT_OLD_BUZZER)
26 #include "../beep.h"
27 #endif
28 #include "../disk.h"
29 #if defined(USE_HARD_DISK)
30 #include "../harddisk.h"
31 #endif
32 #include "../i8237.h"
33 #include "../i8251.h"
34 #include "../i8253.h"
35 #include "../i8255.h"
36 #include "../i8259.h"
37 #if defined(HAS_I386) || defined(HAS_I486)
38 #include "../i386.h"
39 #elif defined(HAS_I86) || defined(HAS_V30)
40 #include "../i286.h"
41 #else
42 #include "../i286.h"
43 #endif
44 #include "../io.h"
45 #include "../ls244.h"
46 #include "../memory.h"
47 #include "../noise.h"
48 #include "../not.h"
49 #if !defined(SUPPORT_OLD_BUZZER)
50 #include "../pcm1bit.h"
51 #endif
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"
57 #endif
58 #include "../tms3631.h"
59 #include "../upd1990a.h"
60 #include "../upd7220.h"
61 #include "../upd765a.h"
62 #include "../ym2203.h"
63
64 #ifdef USE_DEBUGGER
65 #include "../debugger.h"
66 #endif
67
68 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
69 #include "cpureg.h"
70 #endif
71 #include "display.h"
72 #include "dmareg.h"
73 #include "floppy.h"
74 #include "fmsound.h"
75 #include "joystick.h"
76 #include "keyboard.h"
77 #include "membus.h"
78 #include "mouse.h"
79 #if defined(SUPPORT_SASI_IF)
80 #include "sasi.h"
81 #endif
82 #if defined(SUPPORT_SCSI_IF)
83 #include "scsi.h"
84 #endif
85 #if defined(SUPPORT_IDE_IF)
86 #include "ide.h"
87 #endif
88
89 #if defined(SUPPORT_CMT_IF)
90 using PC9801::CMT;
91 #endif
92 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
93 using PC9801::CPUREG;
94 #endif
95 using PC9801::DISPLAY;
96 using PC9801::DMAREG;
97 using PC9801::FLOPPY;
98 using PC9801::FMSOUND;
99 using PC9801::JOYSTICK;
100 using PC9801::KEYBOARD;
101 using PC9801::MEMBUS;
102 using PC9801::MOUSE;
103 #if defined(SUPPORT_SASI_IF)
104 using PC9801::SASI;
105 #endif
106 #if defined(SUPPORT_SCSI_IF)
107 using PC9801::SCSI;
108 #endif
109 #if defined(SUPPORT_IDE_IF)
110 using PC9801::IDE;
111 #endif
112
113 #if defined(SUPPORT_320KB_FDD_IF)
114 #include "../pc80s31k.h"
115 #include "../z80.h"
116 #endif
117 #if defined(SUPPORT_CMT_IF)
118 #include "cmt.h"
119 #endif
120
121 #if defined(_PC98DO) || defined(_PC98DOPLUS)
122 #include "../pc80s31k.h"
123 #include "../z80.h"
124 #include "../pc8801/pc88.h"
125 #endif
126
127 #if defined(_PC98DO) || defined(_PC98DOPLUS)
128 using PC88DEV::PC88;
129 #endif
130 // ----------------------------------------------------------------------------
131 // initialize
132 // ----------------------------------------------------------------------------
133
134 VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
135 {
136         // check configs
137 #if defined(_PC98DO) || defined(_PC98DOPLUS)
138         boot_mode = config.boot_mode;
139 #endif
140         int cpu_clocks = CPU_CLOCKS;
141 #if defined(PIT_CLOCK_8MHZ)
142         pit_clock_8mhz = true;
143 #else
144         pit_clock_8mhz = false;
145 #endif
146 #if defined(_PC9801E)
147         if(config.cpu_type != 0) {
148                 // 8MHz -> 5MHz
149                 cpu_clocks = 4992030;
150                 pit_clock_8mhz = false;
151         }
152 #elif defined(_PC9801VM) || defined(_PC98DO) || defined(_PC98DOPLUS) || defined(_PC9801VX) || defined(_PC98XL)
153         if(config.cpu_type != 0) {
154                 // 10MHz/16MHz -> 8MHz
155                 cpu_clocks = 7987248;
156                 pit_clock_8mhz = true;
157         }
158 #elif defined(_PC9801RA) || defined(_PC98RL)
159         if(config.cpu_type != 0) {
160                 // 20MHz -> 16MHz
161                 cpu_clocks = 15974496;
162                 pit_clock_8mhz = true;
163         }
164 #endif
165         int pit_clocks = pit_clock_8mhz ? 1996812 : 2457600;
166         
167         sound_type = config.sound_type;
168         
169         // create devices
170         first_device = last_device = NULL;
171         dummy = new DEVICE(this, emu);  // must be 1st device
172         event = new EVENT(this, emu);   // must be 2nd device
173         
174 #if defined(SUPPORT_OLD_BUZZER)
175         beep = new BEEP(this, emu);
176 #else
177         beep = new PCM1BIT(this, emu);
178 #endif
179         dma = new I8237(this, emu);
180 #if defined(SUPPORT_CMT_IF)
181         sio_cmt = new I8251(this, emu);         // for cmt
182         sio_cmt->set_device_name(_T("8251 SIO (CMT)"));
183 #endif
184         sio_rs = new I8251(this, emu);          // for rs232c
185         sio_rs->set_device_name(_T("8251 SIO (RS-232C)"));
186         sio_kbd = new I8251(this, emu);         // for keyboard
187         sio_kbd->set_device_name(_T("8251 SIO (Keyboard)"));
188         pit = new I8253(this, emu);
189 #if defined(SUPPORT_320KB_FDD_IF)
190         pio_fdd = new I8255(this, emu);         // for 320kb fdd i/f
191         pio_fdd->set_device_name(_T("8255 PIO (320KB I/F)"));
192 #endif
193         pio_mouse = new I8255(this, emu);       // for mouse
194         pio_mouse->set_device_name(_T("8255 PIO (Mouse)"));
195         pio_sys = new I8255(this, emu);         // for system port
196         pio_sys->set_device_name(_T("8255 PIO (System)"));
197         pio_prn = new I8255(this, emu);         // for printer
198         pio_prn->set_device_name(_T("8255 PIO (Printer)"));
199         pic = new I8259(this, emu);
200 #if defined(HAS_I386) || defined(HAS_I486)
201         cpu = new I386(this, emu); // 80386, 80486
202 #elif defined(HAS_I86) || defined(HAS_V30)
203         cpu = new I286(this, emu);// 8086, V30, 80286
204 #else
205         cpu = new I286(this, emu);
206 #endif  
207 #if defined(HAS_I86)
208         cpu->set_device_name(_T("CPU(i8086)"));
209 #elif defined(HAS_I386)
210         cpu->set_device_name(_T("CPU(i386)"));
211 #elif defined(HAS_I486)
212         cpu->set_device_name(_T("CPU(i486)"));
213 #elif defined(HAS_PENTIUM)
214         cpu->set_device_name(_T("CPU(Pentium)"));
215 #elif defined(HAS_V33A)
216         cpu->set_device_name(_T("CPU(V33A)"));
217 #elif defined(HAS_V30)
218         cpu->set_device_name(_T("CPU(V30)"));
219 #else
220         cpu->set_device_name(_T("CPU(i286)"));
221 #endif
222         io = new IO(this, emu);
223         rtcreg = new LS244(this, emu);
224         rtcreg->set_device_name(_T("74LS244 (RTC)"));
225         //memory = new MEMORY(this, emu);
226         memory = new MEMBUS(this, emu);
227         not_busy = new NOT(this, emu);
228         not_busy->set_device_name(_T("NOT Gate (Printer Busy)"));
229 #if defined(HAS_I86) || defined(HAS_V30)
230         not_prn = new NOT(this, emu);
231         not_prn->set_device_name(_T("NOT Gate (Printer IRQ)"));
232 #endif
233         rtc = new UPD1990A(this, emu);
234 #if defined(SUPPORT_2HD_FDD_IF)
235         fdc_2hd = new UPD765A(this, emu);
236         fdc_2hd->set_device_name(_T("uPD765A FDC (2HD I/F)"));
237 #endif
238 #if defined(SUPPORT_2DD_FDD_IF)
239         fdc_2dd = new UPD765A(this, emu);
240         fdc_2dd->set_device_name(_T("uPD765A FDC (2DD I/F)"));
241 #endif
242 #if defined(SUPPORT_2HD_2DD_FDD_IF)
243         fdc = new UPD765A(this, emu);
244         fdc->set_device_name(_T("uPD765A FDC (2HD/2DD I/F)"));
245 #endif
246         noise_seek = new NOISE(this, emu);
247         noise_head_down = new NOISE(this, emu);
248         noise_head_up = new NOISE(this, emu);
249 #if defined(SUPPORT_SASI_IF)
250         sasi_host = new SCSI_HOST(this, emu);
251         sasi_hdd = new SASI_HDD(this, emu);
252         sasi_hdd->set_device_name(_T("SASI Hard Disk Drive"));
253         sasi_hdd->scsi_id = 0;
254         sasi_hdd->bytes_per_sec = 625 * 1024; // 625KB/s
255         for(int i = 0; i < USE_HARD_DISK; i++) {
256                 sasi_hdd->set_disk_handler(i, new HARDDISK(emu));
257         }
258         sasi_hdd->set_context_interface(sasi_host);
259         sasi_host->set_context_target(sasi_hdd);
260 #endif
261 #if defined(SUPPORT_SCSI_IF)
262         scsi_host = new SCSI_HOST(this, emu);
263         for(int i = 0; i < USE_HARD_DISK; i++) {
264                 scsi_hdd[i] = new SCSI_HDD(this, emu);
265                 scsi_hdd[i]->set_device_name(_T("SCSI Hard Disk Drive #%d"), i + 1);
266                 scsi_hdd[i]->scsi_id = i;
267                 scsi_hdd[i]->set_disk_handler(0, new HARDDISK(emu));
268                 scsi_hdd[i]->set_context_interface(scsi_host);
269                 scsi_host->set_context_target(scsi_hdd[i]);
270         }
271 #endif
272         gdc_chr = new UPD7220(this, emu);
273         gdc_chr->set_device_name(_T("uPD7220 GDC (Character)"));
274         gdc_gfx = new UPD7220(this, emu);
275         gdc_gfx->set_device_name(_T("uPD7220 GDC (Graphics)"));
276         
277         if(sound_type == 0 || sound_type == 1) {
278                 opn = new YM2203(this, emu);
279 #ifdef SUPPORT_PC98_OPNA
280                 opn->is_ym2608 = true;
281 #endif
282                 fmsound = new FMSOUND(this, emu);
283                 joystick = new JOYSTICK(this, emu);
284         } else if(sound_type == 2 || sound_type == 3) {
285                 tms3631 = new TMS3631(this, emu);
286                 tms3631->set_device_name(_T("TMS3631 SSG (PC-9801-14)"));
287                 pit_14 = new I8253(this, emu);
288                 pit_14->set_device_name(_T("8253 PIT (PC-9801-14)"));
289                 pio_14 = new I8255(this, emu);
290                 pio_14->set_device_name(_T("8255 PIO (PC-9801-14)"));
291                 maskreg_14 = new LS244(this, emu);
292                 maskreg_14->set_device_name(_T("74LS244 (PC-9801-14)"));
293         }
294         if(config.printer_type == 0) {
295                 printer = new PRNFILE(this, emu);
296 //      } else if(config.printer_type == 1) {
297 //              printer = new PCPR201(this, emu);
298         } else {
299                 printer = dummy;
300         }
301         
302 #if defined(SUPPORT_CMT_IF)
303         cmt = new CMT(this, emu);
304 #endif
305 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
306         cpureg = new CPUREG(this, emu);
307 #endif
308         display = new DISPLAY(this, emu);
309         dmareg = new DMAREG(this, emu);
310         floppy = new FLOPPY(this, emu);
311         keyboard = new KEYBOARD(this, emu);
312         mouse = new MOUSE(this, emu);
313 #if defined(SUPPORT_SASI_IF)
314         sasi = new SASI(this, emu);
315 #endif
316 #if defined(SUPPORT_SCSI_IF)
317         scsi = new SCSI(this, emu);
318 #endif
319 #if defined(SUPPORT_IDE_IF)
320         ide = new IDE(this, emu);
321 #endif
322         
323 #if defined(SUPPORT_320KB_FDD_IF)
324         // 320kb fdd drives
325         pio_sub = new I8255(this, emu);
326         pio_sub->set_device_name(_T("8255 PIO (320KB FDD)"));
327         pc80s31k = new PC80S31K(this, emu);
328         pc80s31k->set_device_name(_T("PC-80S31K (320KB FDD)"));
329         fdc_sub = new UPD765A(this, emu);
330         fdc_sub->set_device_name(_T("uPD765A FDC (320KB FDD)"));
331         cpu_sub = new Z80(this, emu);
332         cpu_sub->set_device_name(_T("Z80 CPU (320KB FDD)"));
333 #endif
334         
335         /* IRQ  0  PIT
336                 1  KEYBOARD
337                 2  CRTV
338                 3  (INT0)
339                 4  RS-232C
340                 5  (INT1)
341                 6  (INT2)
342                 7  SLAVE PIC
343                 8  PRINTER
344                 9  (INT3) PC-9801-27 (SASI), PC-9801-55 (SCSI), or IDE
345                 10 (INT41) FDC (640KB I/F)
346                 11 (INT42) FDC (1MB I/F)
347                 12 (INT5) PC-9801-26(K) or PC-9801-14
348                 13 (INT6) MOUSE
349                 14 
350                 15 (RESERVED)
351         */
352         
353         // set contexts
354         event->set_context_cpu(cpu, cpu_clocks);
355 #if defined(SUPPORT_320KB_FDD_IF)
356         event->set_context_cpu(cpu_sub, 4000000);
357 #endif
358         event->set_context_sound(beep);
359         if(sound_type == 0 || sound_type == 1) {
360                 event->set_context_sound(opn);
361         } else if(sound_type == 2 || sound_type == 3) {
362                 event->set_context_sound(tms3631);
363         }
364         event->set_context_sound(noise_seek);
365         event->set_context_sound(noise_head_down);
366         event->set_context_sound(noise_head_up);
367         
368         dma->set_context_memory(memory);
369         // dma ch.0: sasi
370         // dma ch.1: memory refresh
371 #if defined(SUPPORT_2HD_FDD_IF)
372         dma->set_context_ch2(fdc_2hd);
373         dma->set_context_tc2(fdc_2hd, SIG_UPD765A_TC, 1);
374 #endif
375 #if defined(SUPPORT_2DD_FDD_IF)
376         dma->set_context_ch3(fdc_2dd);
377         dma->set_context_tc3(fdc_2dd, SIG_UPD765A_TC, 1);
378 #endif
379 #if defined(SUPPORT_2HD_2DD_FDD_IF)
380 #if !defined(SUPPORT_HIRESO)
381         dma->set_context_ch2(fdc);
382         dma->set_context_ch3(fdc);
383         dma->set_context_tc2(fdc, SIG_UPD765A_TC, 1);
384         dma->set_context_tc3(fdc, SIG_UPD765A_TC, 1);
385 #else
386         dma->set_context_ch1(fdc);
387         dma->set_context_tc1(fdc, SIG_UPD765A_TC, 1);
388 #endif
389 #endif
390 //      sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
391         sio_kbd->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 1);
392         pit->set_context_ch0(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 1);
393 #if defined(SUPPORT_OLD_BUZZER)
394         // pit ch.1: memory refresh
395 #else
396         // pit ch.1: buzzer
397         pit->set_context_ch1(beep, SIG_PCM1BIT_SIGNAL, 1);
398 #endif
399         // pit ch.2: rs-232c
400         pit->set_constant_clock(0, pit_clocks);
401         pit->set_constant_clock(1, pit_clocks);
402         pit->set_constant_clock(2, pit_clocks);
403         pio_mouse->set_context_port_c(mouse, SIG_MOUSE_PORT_C, 0xf0, 0);
404 #if defined(SUPPORT_HIRESO)
405         // sysport port.c bit7,5: sysport port.b bit4,3
406         pio_sys->set_context_port_c(pio_sys, SIG_I8255_PORT_B, 0x80, -3); // SHUT0
407         pio_sys->set_context_port_c(pio_sys, SIG_I8255_PORT_B, 0x20, -2); // SHUT1
408 #endif
409         // sysport port.c bit6: printer strobe
410 #if defined(SUPPORT_OLD_BUZZER)
411         pio_sys->set_context_port_c(beep, SIG_BEEP_MUTE, 0x08, 0);
412 #else
413         pio_sys->set_context_port_c(beep, SIG_PCM1BIT_MUTE, 0x08, 0);
414 #endif
415         // sysport port.c bit2: enable txrdy interrupt
416         // sysport port.c bit1: enable txempty interrupt
417         // sysport port.c bit0: enable rxrdy interrupt
418         pio_prn->set_context_port_a(printer, SIG_PRINTER_DATA, 0xff, 0);
419         pio_prn->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x80, 0);
420         if(config.printer_type == 0) {
421                 PRNFILE *prnfile = (PRNFILE *)printer;
422                 prnfile->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
423 //      } else if(config.printer_type == 1) {
424 //              PRNFILE *pcpr201 = (PCPR201 *)printer;
425 //              pcpr201->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
426         }
427         not_busy->set_context_out(pio_prn, SIG_I8255_PORT_B, 4);
428 #if defined(HAS_I86) || defined(HAS_V30)
429         pio_prn->set_context_port_c(not_prn, SIG_NOT_INPUT, 8, 0);
430         not_prn->set_context_out(pic, SIG_I8259_CHIP1 | SIG_I8259_IR0, 1);
431 #endif
432         rtcreg->set_context_output(rtc, SIG_UPD1990A_CMD, 0x07, 0);
433         rtcreg->set_context_output(rtc, SIG_UPD1990A_DIN, 0x20, 0);
434         rtcreg->set_context_output(rtc, SIG_UPD1990A_STB, 0x08, 0);
435         rtcreg->set_context_output(rtc, SIG_UPD1990A_CLK, 0x10, 0);
436         pic->set_context_cpu(cpu);
437         rtc->set_context_dout(pio_sys, SIG_I8255_PORT_B, 1);
438         
439         if(sound_type == 0 || sound_type == 1) {
440                 opn->set_context_irq(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
441                 opn->set_context_port_b(joystick, SIG_JOYSTICK_SELECT, 0xc0, 0);
442                 fmsound->set_context_opn(opn);
443                 joystick->set_context_opn(opn);
444         } else if(sound_type == 2 || sound_type == 3) {
445                 pio_14->set_context_port_a(tms3631, SIG_TMS3631_ENVELOP1, 0xff, 0);
446                 pio_14->set_context_port_b(tms3631, SIG_TMS3631_ENVELOP2, 0xff, 0);
447                 pio_14->set_context_port_c(tms3631, SIG_TMS3631_DATAREG, 0xff, 0);
448                 maskreg_14->set_context_output(tms3631, SIG_TMS3631_MASKREG, 0xff, 0);
449                 pit_14->set_constant_clock(2, 1996800 / 8);
450                 pit_14->set_context_ch2(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
451         }
452         
453 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
454         cpureg->set_context_cpu(cpu);
455 #endif
456         display->set_context_pic(pic);
457         display->set_context_gdc_chr(gdc_chr, gdc_chr->get_ra());
458         display->set_context_gdc_gfx(gdc_gfx, gdc_gfx->get_ra(), gdc_gfx->get_cs());
459         dmareg->set_context_dma(dma);
460         keyboard->set_context_sio(sio_kbd);
461         memory->set_context_display(display);
462         mouse->set_context_pic(pic);
463         mouse->set_context_pio(pio_mouse);
464         
465 #if defined(SUPPORT_2HD_FDD_IF)
466         fdc_2hd->set_context_irq(floppy, SIG_FLOPPY_2HD_IRQ, 1);
467         fdc_2hd->set_context_drq(floppy, SIG_FLOPPY_2HD_DRQ, 1);
468         fdc_2hd->set_context_noise_seek(noise_seek);
469         fdc_2hd->set_context_noise_head_down(noise_head_down);
470         fdc_2hd->set_context_noise_head_up(noise_head_up);
471         fdc_2hd->raise_irq_when_media_changed = true;
472         floppy->set_context_fdc_2hd(fdc_2hd);
473 #endif
474 #if defined(SUPPORT_2DD_FDD_IF)
475         fdc_2dd->set_context_irq(floppy, SIG_FLOPPY_2DD_IRQ, 1);
476         fdc_2dd->set_context_drq(floppy, SIG_FLOPPY_2DD_DRQ, 1);
477         fdc_2dd->set_context_noise_seek(noise_seek);
478         fdc_2dd->set_context_noise_head_down(noise_head_down);
479         fdc_2dd->set_context_noise_head_up(noise_head_up);
480         fdc_2dd->raise_irq_when_media_changed = true;
481         floppy->set_context_fdc_2dd(fdc_2dd);
482 #endif
483 #if defined(SUPPORT_2HD_2DD_FDD_IF)
484         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
485         fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
486         fdc->set_context_noise_seek(noise_seek);
487         fdc->set_context_noise_head_down(noise_head_down);
488         fdc->set_context_noise_head_up(noise_head_up);
489         fdc->raise_irq_when_media_changed = true;
490         floppy->set_context_fdc(fdc);
491 #endif
492         floppy->set_context_dma(dma);
493         floppy->set_context_pic(pic);
494         
495 #if defined(SUPPORT_SASI_IF)
496 #if !defined(SUPPORT_HIRESO)
497         sasi_host->set_context_irq(pio_sys, SIG_I8255_PORT_B, 0x10);
498 #endif
499         sasi_host->set_context_irq(sasi, SIG_SASI_IRQ, 1);
500         sasi_host->set_context_drq(sasi, SIG_SASI_DRQ, 1);
501 #ifdef _PC98XA
502         dma->set_context_ch3(sasi_host);
503         dma->set_context_tc3(sasi, SIG_SASI_TC, 1);
504 #else
505         dma->set_context_ch0(sasi_host);
506         dma->set_context_tc0(sasi, SIG_SASI_TC, 1);
507 #endif
508         sasi->set_context_host(sasi_host);
509         sasi->set_context_hdd(sasi_hdd);
510         sasi->set_context_dma(dma);
511         sasi->set_context_pic(pic);
512 #endif
513 #if defined(SUPPORT_SCSI_IF)
514         dma->set_context_ch0(scsi);
515         scsi->set_context_dma(dma);
516         scsi->set_context_pic(pic);
517 #endif
518 #if defined(SUPPORT_IDE_IF)
519         dma->set_context_ch0(ide);
520         ide->set_context_dma(dma);
521         ide->set_context_pic(pic);
522 #endif
523         
524 #if defined(SUPPORT_CMT_IF)
525         sio_cmt->set_context_out(cmt, SIG_CMT_OUT);
526 //      sio_cmt->set_context_txrdy(cmt, SIG_CMT_TXRDY, 1);
527 //      sio_cmt->set_context_rxrdy(cmt, SIG_CMT_RXRDY, 1);
528 //      sio_cmt->set_context_txe(cmt, SIG_CMT_TXEMP, 1);
529         cmt->set_context_sio(sio_cmt);
530 #endif
531         
532         // cpu bus
533         cpu->set_context_mem(memory);
534         cpu->set_context_io(io);
535         cpu->set_context_intr(pic);
536 #ifdef SINGLE_MODE_DMA
537         cpu->set_context_dma(dma);
538 #endif
539 #ifdef USE_DEBUGGER
540         cpu->set_context_debugger(new DEBUGGER(this, emu));
541 #endif
542         
543 #if defined(SUPPORT_320KB_FDD_IF)
544         // 320kb fdd drives
545         pc80s31k->set_context_cpu(cpu_sub);
546         pc80s31k->set_context_fdc(fdc_sub);
547         pc80s31k->set_context_pio(pio_sub);
548         pio_fdd->set_context_port_a(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
549         pio_fdd->set_context_port_b(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
550         pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
551         pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
552         pio_fdd->clear_ports_by_cmdreg = true;
553         pio_sub->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
554         pio_sub->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
555         pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
556         pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
557         pio_sub->clear_ports_by_cmdreg = true;
558         fdc_sub->set_context_irq(cpu_sub, SIG_CPU_IRQ, 1);
559         fdc_sub->set_context_noise_seek(noise_seek);
560         fdc_sub->set_context_noise_head_down(noise_head_down);
561         fdc_sub->set_context_noise_head_up(noise_head_up);
562         cpu_sub->set_context_mem(pc80s31k);
563         cpu_sub->set_context_io(pc80s31k);
564         cpu_sub->set_context_intr(pc80s31k);
565 #ifdef USE_DEBUGGER
566         cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
567 #endif
568 #endif
569         
570         // i/o bus
571         io->set_iomap_alias_rw(0x0000, pic, 0);
572         io->set_iomap_alias_rw(0x0002, pic, 1);
573         io->set_iomap_alias_rw(0x0008, pic, 2);
574         io->set_iomap_alias_rw(0x000a, pic, 3);
575         
576         io->set_iomap_alias_rw(0x0001, dma, 0x00);
577         io->set_iomap_alias_rw(0x0003, dma, 0x01);
578         io->set_iomap_alias_rw(0x0005, dma, 0x02);
579         io->set_iomap_alias_rw(0x0007, dma, 0x03);
580         io->set_iomap_alias_rw(0x0009, dma, 0x04);
581         io->set_iomap_alias_rw(0x000b, dma, 0x05);
582         io->set_iomap_alias_rw(0x000d, dma, 0x06);
583         io->set_iomap_alias_rw(0x000f, dma, 0x07);
584         io->set_iomap_alias_rw(0x0011, dma, 0x08);
585         io->set_iomap_alias_w (0x0013, dma, 0x09);
586         io->set_iomap_alias_w (0x0015, dma, 0x0a);
587         io->set_iomap_alias_w (0x0017, dma, 0x0b);
588         io->set_iomap_alias_w (0x0019, dma, 0x0c);
589         io->set_iomap_alias_rw(0x001b, dma, 0x0d);
590         io->set_iomap_alias_w (0x001d, dma, 0x0e);
591         io->set_iomap_alias_w (0x001f, dma, 0x0f);
592         io->set_iomap_single_w(0x0021, dmareg);
593         io->set_iomap_single_w(0x0023, dmareg);
594         io->set_iomap_single_w(0x0025, dmareg);
595         io->set_iomap_single_w(0x0027, dmareg);
596 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
597         io->set_iomap_single_w(0x0029, dmareg);
598 #endif
599 #if defined(SUPPORT_32BIT_ADDRESS)
600         io->set_iomap_single_w(0x0e05, dmareg);
601         io->set_iomap_single_w(0x0e07, dmareg);
602         io->set_iomap_single_w(0x0e09, dmareg);
603         io->set_iomap_single_w(0x0e0b, dmareg);
604 #endif
605         
606         io->set_iomap_single_w(0x0020, rtcreg);
607         
608         io->set_iomap_alias_rw(0x0030, sio_rs, 0);
609         io->set_iomap_alias_rw(0x0032, sio_rs, 1);
610         
611         io->set_iomap_alias_rw(0x0031, pio_sys, 0);
612         io->set_iomap_alias_rw(0x0033, pio_sys, 1);
613         io->set_iomap_alias_rw(0x0035, pio_sys, 2);
614         io->set_iomap_alias_w (0x0037, pio_sys, 3);
615         
616         io->set_iomap_alias_rw(0x0040, pio_prn, 0);
617         io->set_iomap_alias_rw(0x0042, pio_prn, 1);
618         io->set_iomap_alias_rw(0x0044, pio_prn, 2);
619         io->set_iomap_alias_w (0x0046, pio_prn, 3);
620         
621         io->set_iomap_alias_rw(0x0041, sio_kbd, 0);
622         io->set_iomap_alias_rw(0x0043, sio_kbd, 1);
623         
624 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
625         io->set_iomap_single_w(0x0050, cpureg);
626         io->set_iomap_single_w(0x0052, cpureg);
627 #endif
628         
629 #if defined(SUPPORT_320KB_FDD_IF)
630         io->set_iomap_alias_rw(0x0051, pio_fdd, 0);
631         io->set_iomap_alias_rw(0x0053, pio_fdd, 1);
632         io->set_iomap_alias_rw(0x0055, pio_fdd, 2);
633         io->set_iomap_alias_w (0x0057, pio_fdd, 3);
634 #endif
635         
636         io->set_iomap_alias_rw(0x0060, gdc_chr, 0);
637         io->set_iomap_alias_rw(0x0062, gdc_chr, 1);
638         
639         io->set_iomap_single_w(0x64, display);
640         io->set_iomap_single_w(0x68, display);
641 #if defined(SUPPORT_16_COLORS)
642         io->set_iomap_single_w(0x6a, display);
643 #endif
644         io->set_iomap_single_w(0x6c, display);
645         io->set_iomap_single_w(0x6e, display);
646         
647         io->set_iomap_single_w(0x70, display);
648         io->set_iomap_single_w(0x72, display);
649         io->set_iomap_single_w(0x74, display);
650         io->set_iomap_single_w(0x76, display);
651         io->set_iomap_single_w(0x78, display);
652         io->set_iomap_single_w(0x7a, display);
653 #if defined(SUPPORT_GRCG)
654 #if !defined(SUPPORT_HIRESO)
655         io->set_iomap_single_w(0x007c, display);
656         io->set_iomap_single_w(0x007e, display);
657 #else
658         io->set_iomap_single_w(0x00a4, display);
659         io->set_iomap_single_w(0x00a6, display);
660 #endif
661 #endif
662         
663 #if defined(SUPPORT_SASI_IF)
664         io->set_iomap_single_rw(0x0080, sasi);
665         io->set_iomap_single_rw(0x0082, sasi);
666 #endif
667 #if defined(SUPPORT_SCSI_IF)
668         io->set_iomap_single_rw(0x0cc0, scsi);
669         io->set_iomap_single_rw(0x0cc2, scsi);
670         io->set_iomap_single_rw(0x0cc4, scsi);
671 #endif
672 #if defined(SUPPORT_IDE_IF)
673         io->set_iomap_single_rw(0x0640, ide);
674         io->set_iomap_single_rw(0x0642, ide);
675         io->set_iomap_single_rw(0x0644, ide);
676         io->set_iomap_single_rw(0x0646, ide);
677         io->set_iomap_single_rw(0x0648, ide);
678         io->set_iomap_single_rw(0x064a, ide);
679         io->set_iomap_single_rw(0x064c, ide);
680         io->set_iomap_single_rw(0x064e, ide);
681         io->set_iomap_single_rw(0x074c, ide);
682         io->set_iomap_single_rw(0x074e, ide);
683 #endif
684         
685         io->set_iomap_alias_rw(0x00a0, gdc_gfx, 0);
686         io->set_iomap_alias_rw(0x00a2, gdc_gfx, 1);
687         
688 #if defined(SUPPORT_2ND_VRAM) && !defined(SUPPORT_HIRESO)
689         io->set_iomap_single_rw(0x00a4, display);
690         io->set_iomap_single_rw(0x00a6, display);
691 #endif
692         io->set_iomap_single_rw(0xa8, display);
693         io->set_iomap_single_rw(0xaa, display);
694         io->set_iomap_single_rw(0xac, display);
695         io->set_iomap_single_rw(0xae, display);
696         
697 //      io->set_iomap_single_w(0xa1, display);
698 //      io->set_iomap_single_w(0xa3, display);
699 //      io->set_iomap_single_w(0xa5, display);
700         io->set_iomap_single_rw(0xa1, display);
701         io->set_iomap_single_rw(0xa3, display);
702         io->set_iomap_single_rw(0xa5, display);
703         io->set_iomap_single_rw(0xa9, display);
704 #if defined(SUPPORT_EGC)
705         io->set_iomap_range_rw(0x04a0, 0x04af, display);
706 #endif
707         
708         io->set_iomap_alias_rw(0x0071, pit, 0);
709         io->set_iomap_alias_rw(0x0073, pit, 1);
710         io->set_iomap_alias_rw(0x0075, pit, 2);
711         io->set_iomap_alias_w (0x0077, pit, 3);
712         
713         io->set_iomap_single_rw(0x0090, floppy);
714         io->set_iomap_single_rw(0x0092, floppy);
715         io->set_iomap_single_rw(0x0094, floppy);
716         io->set_iomap_single_rw(0x0096, floppy);
717 #if defined(SUPPORT_2HD_2DD_FDD_IF)
718 #if !defined(SUPPORT_HIRESO)
719         io->set_iomap_single_rw(0x00be, floppy);
720 #else
721 //#if !defined(_PC98XA) && !defined(_PC98XL)
722         io->set_iomap_single_w (0x00be, floppy);
723 //#endif
724 #endif
725 #endif
726 #if !defined(SUPPORT_HIRESO)
727         io->set_iomap_single_rw(0x00c8, floppy);
728         io->set_iomap_single_rw(0x00ca, floppy);
729         io->set_iomap_single_rw(0x00cc, floppy);
730         io->set_iomap_single_rw(0x00ce, floppy);
731 #endif
732         
733 #if defined(SUPPORT_CMT_IF)
734         io->set_iomap_alias_rw(0x0091, sio_cmt, 0);
735         io->set_iomap_alias_rw(0x0093, sio_cmt, 1);
736         io->set_iomap_single_w(0x0095, cmt);
737         io->set_iomap_single_w(0x0097, cmt);
738 #endif
739         
740 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
741         io->set_iomap_single_rw(0x00f0, cpureg);
742         io->set_iomap_single_rw(0x00f2, cpureg);
743 #endif
744 #if defined(SUPPORT_32BIT_ADDRESS)
745         io->set_iomap_single_rw(0x00f6, cpureg);
746 #endif
747         
748         if(sound_type == 0 || sound_type == 1) {
749                 io->set_iomap_single_rw(0x0188, fmsound);
750                 io->set_iomap_single_rw(0x018a, fmsound);
751 #ifdef SUPPORT_PC98_OPNA
752                 io->set_iomap_single_rw(0x018c, fmsound);
753                 io->set_iomap_single_rw(0x018e, fmsound);
754                 io->set_iomap_single_rw(0xa460, fmsound);
755 #endif
756         } else if(sound_type == 2 || sound_type == 3) {
757                 io->set_iomap_alias_rw(0x0088, pio_14, 0);
758                 io->set_iomap_alias_rw(0x008a, pio_14, 1);
759                 io->set_iomap_alias_rw(0x008c, pio_14, 2);
760                 io->set_iomap_alias_w(0x008e, pio_14, 3);
761                 io->set_iovalue_single_r(0x008e, 0x08);
762                 io->set_iomap_single_w(0x0188, maskreg_14);
763                 io->set_iomap_single_w(0x018a, maskreg_14);
764                 io->set_iomap_alias_rw(0x018c, pit_14, 2);
765                 io->set_iomap_alias_w(0x018e, pit_14, 3);
766 //              io->set_iovalue_single_r(0x018e, 0x00); // INT0
767 //              io->set_iovalue_single_r(0x018e, 0x40); // INT41
768                 io->set_iovalue_single_r(0x018e, 0x80); // INT5
769 //              io->set_iovalue_single_r(0x018e, 0xc0); // INT6
770         }
771         
772 //#if !defined(SUPPORT_HIRESO)
773 //      io->set_iovalue_single_r(0x0431, 0x04); // bit2: 1 = Normal mode, 0 = Hireso mode
774 //#else
775 //      io->set_iovalue_single_r(0x0431, 0x00);
776 //#endif
777 #if defined(SUPPORT_ITF_ROM)
778         io->set_iomap_single_w(0x043d, memory);
779 #endif
780 #if !defined(SUPPORT_HIRESO)
781         io->set_iomap_single_w(0x043f, memory);
782 #endif
783 #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS)
784 #if !defined(_PC98XA)
785         io->set_iomap_single_rw(0x0439, memory);
786 #endif
787 #if !defined(SUPPORT_HIRESO)
788         io->set_iomap_single_rw(0x0461, memory);
789         io->set_iomap_single_rw(0x0463, memory);
790 #else
791         io->set_iomap_single_rw(0x0091, memory);
792         io->set_iomap_single_rw(0x0093, memory);
793 #endif
794         io->set_iomap_single_r(0x0567, memory);
795 #endif
796 #if defined(SUPPORT_32BIT_ADDRESS)
797         io->set_iomap_single_w(0x053d, memory);
798 #endif
799         
800 #if !(defined(_PC9801) || defined(_PC9801E) || defined(SUPPORT_HIRESO))
801         io->set_iomap_alias_rw(0x3fd9, pit, 0);
802         io->set_iomap_alias_rw(0x3fdb, pit, 1);
803         io->set_iomap_alias_rw(0x3fdd, pit, 2);
804         io->set_iomap_alias_w (0x3fdf, pit, 3);
805 #endif
806         
807 #if !defined(SUPPORT_HIRESO)
808         io->set_iomap_alias_rw(0x7fd9, pio_mouse, 0);
809         io->set_iomap_alias_rw(0x7fdb, pio_mouse, 1);
810         io->set_iomap_alias_rw(0x7fdd, pio_mouse, 2);
811         io->set_iomap_alias_w (0x7fdf, pio_mouse, 3);
812         io->set_iomap_single_rw(0xbfdb, mouse);
813 #else
814         io->set_iomap_alias_rw(0x0061, pio_mouse, 0);
815         io->set_iomap_alias_rw(0x0063, pio_mouse, 1);
816         io->set_iomap_alias_rw(0x0065, pio_mouse, 2);
817         io->set_iomap_alias_rw(0x0067, pio_mouse, 3);
818 #endif
819         
820 #if defined(_PC98DO) || defined(_PC98DOPLUS)
821         pc88event = new EVENT(this, emu);
822         pc88event->set_device_name(_T("Event Manager (PC-8801)"));
823         pc88event->set_frames_per_sec(60);
824         pc88event->set_lines_per_frame(260);
825         
826         pc88 = new PC88(this, emu);
827         pc88->set_context_event_manager(pc88event);
828         pc88sio = new I8251(this, emu);
829         pc88sio->set_device_name(_T("8251 SIO (PC-8801)"));
830         pc88sio->set_context_event_manager(pc88event);
831         pc88pio = new I8255(this, emu);
832         pc88pio->set_device_name(_T("8255 PIO (PC-8801)"));
833         pc88pio->set_context_event_manager(pc88event);
834         pc88pcm = new PCM1BIT(this, emu);
835         pc88pcm->set_device_name(_T("1-Bit PCM Sound (PC-8801)"));
836         pc88pcm->set_context_event_manager(pc88event);
837         pc88rtc = new UPD1990A(this, emu);
838         pc88rtc->set_device_name(_T("uPD1990A RTC (PC-8801)"));
839         pc88rtc->set_context_event_manager(pc88event);
840         pc88opn = new YM2203(this, emu);
841 #ifdef SUPPORT_PC88_OPNA
842         pc88opn->set_device_name(_T("YM2608 OPNA (PC-8801)"));
843         pc88opn->is_ym2608 = true;
844 #else
845         pc88opn->set_device_name(_T("YM2203 OPN (PC-8801)"));
846 #endif
847         pc88opn->set_context_event_manager(pc88event);
848         pc88cpu = new Z80(this, emu);
849         pc88cpu->set_device_name(_T("Z80 CPU (PC-8801)"));
850         pc88cpu->set_context_event_manager(pc88event);
851         
852         if(config.printer_type == 0) {
853                 pc88prn = new PRNFILE(this, emu);
854                 pc88prn->set_context_event_manager(pc88event);
855 //      } else if(config.printer_type == 1) {
856 //              pc88prn = new PCPR201(this, emu);
857 //              pc88prn->set_context_event_manager(pc88event);
858         } else {
859                 pc88prn = dummy;
860         }
861         
862         pc88sub = new PC80S31K(this, emu);
863         pc88sub->set_device_name(_T("PC-80S31K (PC-8801 Sub)"));
864         pc88sub->set_context_event_manager(pc88event);
865         pc88pio_sub = new I8255(this, emu);
866         pc88pio_sub->set_device_name(_T("8255 PIO (PC-8801 Sub)"));
867         pc88pio_sub->set_context_event_manager(pc88event);
868         pc88fdc_sub = new UPD765A(this, emu);
869         pc88fdc_sub->set_device_name(_T("uPD765A FDC (PC-8801 Sub)"));
870         pc88fdc_sub->set_context_event_manager(pc88event);
871         pc88noise_seek = new NOISE(this, emu);
872         pc88noise_seek->set_context_event_manager(pc88event);
873         pc88noise_head_down = new NOISE(this, emu);
874         pc88noise_head_down->set_context_event_manager(pc88event);
875         pc88noise_head_up = new NOISE(this, emu);
876         pc88noise_head_up->set_context_event_manager(pc88event);
877         pc88cpu_sub = new Z80(this, emu);
878         pc88cpu_sub->set_device_name(_T("Z80 CPU (PC-8801 Sub)"));
879         pc88cpu_sub->set_context_event_manager(pc88event);
880         
881         pc88event->set_context_cpu(pc88cpu, (config.cpu_type == 1) ? 3993624 : 7987248);
882         pc88event->set_context_cpu(pc88cpu_sub, 3993624);
883         pc88event->set_context_sound(pc88opn);
884         pc88event->set_context_sound(pc88pcm);
885         pc88event->set_context_sound(pc88noise_seek);
886         pc88event->set_context_sound(pc88noise_head_down);
887         pc88event->set_context_sound(pc88noise_head_up);
888         
889         pc88->set_context_cpu(pc88cpu);
890         pc88->set_context_opn(pc88opn);
891         pc88->set_context_pcm(pc88pcm);
892         pc88->set_context_pio(pc88pio);
893         pc88->set_context_prn(pc88prn);
894         pc88->set_context_rtc(pc88rtc);
895         pc88->set_context_sio(pc88sio);
896         pc88cpu->set_context_mem(pc88);
897         pc88cpu->set_context_io(pc88);
898         pc88cpu->set_context_intr(pc88);
899 #ifdef USE_DEBUGGER
900         pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
901 #endif
902         pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
903         pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
904         pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
905         
906         pc88sub->set_context_cpu(pc88cpu_sub);
907         pc88sub->set_context_fdc(pc88fdc_sub);
908         pc88sub->set_context_pio(pc88pio_sub);
909         pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
910         pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
911         pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
912         pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
913         pc88pio->clear_ports_by_cmdreg = true;
914         pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
915         pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
916         pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
917         pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
918         pc88pio_sub->clear_ports_by_cmdreg = true;
919         pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
920         pc88fdc_sub->set_context_noise_seek(pc88noise_seek);
921         pc88fdc_sub->set_context_noise_head_down(pc88noise_head_down);
922         pc88fdc_sub->set_context_noise_head_up(pc88noise_head_up);
923         pc88cpu_sub->set_context_mem(pc88sub);
924         pc88cpu_sub->set_context_io(pc88sub);
925         pc88cpu_sub->set_context_intr(pc88sub);
926 #ifdef USE_DEBUGGER
927         pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
928 #endif
929 #endif
930
931         // initialize all devices
932 #if defined(__GIT_REPO_VERSION)
933         strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
934 #endif
935         for(DEVICE* device = first_device; device; device = device->next_device) {
936                 device->initialize();
937         }
938         
939 #if defined(_PC9801) || defined(_PC9801E)
940         fdc_2hd->get_disk_handler(0)->drive_num = 0;
941         fdc_2hd->get_disk_handler(1)->drive_num = 1;
942         fdc_2dd->get_disk_handler(0)->drive_num = 2;
943         fdc_2dd->get_disk_handler(1)->drive_num = 3;
944         fdc_sub->get_disk_handler(0)->drive_num = 4;
945         fdc_sub->get_disk_handler(1)->drive_num = 5;
946 #elif defined(_PC9801VF) || defined(_PC9801U)
947         fdc_2dd->get_disk_handler(0)->drive_num = 0;
948         fdc_2dd->get_disk_handler(1)->drive_num = 1;
949 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
950         fdc->get_disk_handler(0)->drive_num = 0;
951         fdc->get_disk_handler(1)->drive_num = 1;
952         pc88fdc_sub->get_disk_handler(0)->drive_num = 2;
953         pc88fdc_sub->get_disk_handler(1)->drive_num = 3;
954 #else
955         fdc->get_disk_handler(0)->drive_num = 0;
956         fdc->get_disk_handler(1)->drive_num = 1;
957 #endif
958 #if defined(USE_HARD_DISK)
959         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
960                 if(!(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv]))) {
961 #if defined(SUPPORT_SASI_IF)
962                         create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("SASI%d.DAT"), drv);
963 #endif
964 #if defined(SUPPORT_SCSI_IF)
965                         create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("SCSI%d.DAT"), drv);
966 #endif
967 #if defined(SUPPORT_IDE_IF)
968                         create_local_path(config.last_hard_disk_path[drv], _MAX_PATH, _T("IDE%d.DAT"), drv);
969 #endif
970                 }
971         }
972 #endif
973 }
974
975 VM::~VM()
976 {
977         // delete all devices
978         for(DEVICE* device = first_device; device;) {
979                 DEVICE *next_device = device->next_device;
980                 device->release();
981                 delete device;
982                 device = next_device;
983         }
984 }
985
986 DEVICE* VM::get_device(int id)
987 {
988         for(DEVICE* device = first_device; device; device = device->next_device) {
989                 if(device->this_device_id == id) {
990                         return device;
991                 }
992         }
993         return NULL;
994 }
995
996 // ----------------------------------------------------------------------------
997 // drive virtual machine
998 // ----------------------------------------------------------------------------
999
1000 void VM::reset()
1001 {
1002         // reset all devices
1003         for(DEVICE* device = first_device; device; device = device->next_device) {
1004                 device->reset();
1005         }
1006 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1007         for(DEVICE* device = first_device; device; device = device->next_device) {
1008                 device->reset();
1009         }
1010 #endif
1011         
1012         // initial device settings
1013         uint8_t port_a, port_b, port_c;
1014         
1015         port_a  = 0xf0; // Clear mouse buttons and counters
1016         port_b  = 0x00;
1017 #if defined(_PC98XA)
1018         port_b |= (uint8_t)((RAM_SIZE - 0x100000) / 0x40000);
1019 #else
1020 #if defined(SUPPORT_HIRESO)
1021         port_b |= 0x80; // DIP SW 1-4, 1 = External FDD #3/#4, 0 = #1/#2
1022 #endif
1023         port_b |= 0x40; // DIP SW 3-6, 1 = Enable internal RAM 80000h-9FFFFh
1024 #if defined(_PC98RL)
1025         port_b |= 0x10; // DIP SW 3-3, 1 = DMA ch.0 for SASI-HDD
1026 #endif
1027 #if defined(USE_CPU_TYPE)
1028         if(config.cpu_type != 0) {
1029 #if !defined(SUPPORT_HIRESO)
1030                 port_b |= 0x02; // SPDSW, 1 = 10MHz, 0 = 12MHz
1031 #else
1032                 port_b |= 0x01; // SPDSW, 1 = 8/16MHz, 0 = 10/20MHz
1033 #endif
1034         }
1035 #endif
1036 #endif
1037         port_c  = 0x00;
1038 #if defined(SUPPORT_HIRESO)
1039 //      port_c |= 0x08; // MODSW, 1 = Normal Mode, 0 = Hirezo Mode
1040 #endif
1041 #if defined(HAS_V30) || defined(HAS_V33)
1042         port_c |= 0x04; // DIP SW 3-8, 1 = V30, 0 = 80x86
1043 #endif
1044         pio_mouse->write_signal(SIG_I8255_PORT_A, port_a, 0xff);
1045         pio_mouse->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1046         pio_mouse->write_signal(SIG_I8255_PORT_C, port_c, 0xff);
1047         
1048         port_a  = 0x00;
1049         port_a |= 0x80; // DIP SW 2-8, 1 = GDC 2.5MHz, 0 = GDC 5MHz
1050         port_a |= 0x40; // DIP SW 2-7, 1 = Do not control FD motor
1051         port_a |= 0x20; // DIP SW 2-6, 1 = Enable internal HD
1052 //      port_a |= 0x10; // DIP SW 2-5, 1 = Initialize emory switch
1053 //      port_a |= 0x08; // DIP SW 2-4, 1 = 20 lines, 0 = 25 lines
1054 //      port_a |= 0x04; // DIP SW 2-3, 1 = 40 columns, 0 = 80 columns
1055         port_a |= 0x02; // DIP SW 2-2, 1 = BASIC mode, 0 = Terminal mode
1056         port_a |= 0x01; // DIP SW 2-1, 1 = Normal mode, 0 = LT mode
1057         port_b  = 0x00;
1058         port_b |= 0x80; // RS-232C CI#, 1 = OFF
1059         port_b |= 0x40; // RS-232C CS#, 1 = OFF
1060         port_b |= 0x20; // RS-232C CD#, 1 = OFF
1061 #if !defined(SUPPORT_HIRESO)
1062 //      port_b |= 0x10; // INT3, 1 = Active, 0 = Inactive
1063         port_b |= 0x08; // DIP SW 1-1, 1 = Hiresolution CRT, 0 = Standard CRT
1064 #else
1065         port_b |= 0x10; // SHUT0
1066         port_b |= 0x08; // SHUT1
1067 #endif
1068 //      port_b |= 0x04; // IMCK, 1 = Parity error occurs in internal RAM
1069 //      port_b |= 0x02; // EMCK, 1 = Parity error occurs in external RAM
1070 //      port_b |= 0x01; // CDAT
1071         port_c  = 0x00;
1072         port_c |= 0x80; // SHUT0
1073         port_c |= 0x40; // PSTBM, 1 = Mask printer's PSTB#
1074         port_c |= 0x20; // SHUT1
1075         port_c |= 0x10; // MCHKEN, 1 = Enable parity check for RAM
1076         port_c |= 0x08; // BUZ, 1 = Stop buzzer
1077         port_c |= 0x04; // TXRE, 1 = Enable IRQ from RS-232C 8251A TXRDY
1078         port_c |= 0x02; // TXEE, 1 = Enable IRQ from RS-232C 8251A TXEMPTY
1079         port_c |= 0x01; // RXRE, 1 = Enable IRQ from RS-232C 8251A RXRDY
1080         pio_sys->write_signal(SIG_I8255_PORT_A, port_a, 0xff);
1081         pio_sys->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1082         pio_sys->write_signal(SIG_I8255_PORT_C, port_c, 0xff);
1083         
1084         port_b  = 0x00;
1085 #if defined(_PC9801)
1086 //      port_b |= 0x80; // TYP1, 0 = PC-9801 (first)
1087 //      port_b |= 0x40; // TYP0, 0
1088 #elif defined(_PC9801U)
1089         port_b |= 0x80; // TYP1, 1 = PC-9801U
1090         port_b |= 0x40; // TYP0, 1
1091 #else
1092         port_b |= 0x80; // TYP1, 1 = Other PC-9801 series
1093 //      port_b |= 0x40; // TYP0, 0
1094 #endif
1095         if(pit_clock_8mhz) {
1096                 port_b |= 0x20; // MOD, 1 = System clock 8MHz, 0 = 5/10MHz
1097         }
1098         port_b |= 0x10; // DIP SW 1-3, 1 = Don't use LCD
1099 #if !defined(SUPPORT_16_COLORS)
1100         port_b |= 0x08; // DIP SW 1-8, 1 = Standard graphic mode, 0 = Enhanced graphic mode
1101 #endif
1102         port_b |= 0x04; // Printer BUSY#, 1 = Inactive, 0 = Active (BUSY)
1103 #if defined(HAS_V30) || defined(HAS_V33)
1104         port_b |= 0x02; // CPUT, 1 = V30/V33, 0 = 80x86
1105 #endif
1106 #if defined(_PC9801VF) || defined(_PC9801U)
1107         port_b |= 0x01; // VF, 1 = PC-9801VF/U
1108 #endif
1109         pio_prn->write_signal(SIG_I8255_PORT_B, port_b, 0xff);
1110         
1111 #if defined(SUPPORT_320KB_FDD_IF)
1112         pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
1113         pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
1114         pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
1115 #endif
1116 #if defined(SUPPORT_2DD_FDD_IF)
1117         fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1);        // 2DD FDC RDY is pulluped
1118 #endif
1119         
1120         if(sound_type == 0 || sound_type == 1) {
1121 //              opn->write_signal(SIG_YM2203_PORT_A, 0x3f, 0xff);       // PC-9801-26(K) INT0
1122 //              opn->write_signal(SIG_YM2203_PORT_A, 0xbf, 0xff);       // PC-9801-26(K) INT41
1123                 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff);       // PC-9801-26(K) INT5
1124 //              opn->write_signal(SIG_YM2203_PORT_A, 0x7f, 0xff);       // PC-9801-26(K) INT6
1125         }
1126         
1127 #if defined(SUPPORT_OLD_BUZZER)
1128         beep->write_signal(SIG_BEEP_ON, 1, 1);
1129         beep->write_signal(SIG_BEEP_MUTE, 1, 1);
1130 #else
1131         beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
1132         beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
1133 #endif
1134         
1135 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1136         pc88opn->set_reg(0x29, 3); // for Misty Blue
1137         pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
1138         pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
1139 #endif
1140 }
1141
1142 void VM::run()
1143 {
1144 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1145         if(boot_mode != 0) {
1146                 pc88event->drive();
1147         } else
1148 #endif
1149         event->drive();
1150 }
1151
1152 double VM::get_frame_rate()
1153 {
1154 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1155         if(config.boot_mode != 0) {
1156                 return pc88event->get_frame_rate();
1157         } else
1158 #endif
1159         return event->get_frame_rate();
1160 }
1161
1162 // ----------------------------------------------------------------------------
1163 // debugger
1164 // ----------------------------------------------------------------------------
1165
1166 #ifdef USE_DEBUGGER
1167 DEVICE *VM::get_cpu(int index)
1168 {
1169 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1170         if(index == 0 && boot_mode == 0) {
1171                 return cpu;
1172         } else if(index == 1 && boot_mode != 0) {
1173                 return pc88cpu;
1174         } else if(index == 2 && boot_mode != 0) {
1175                 return pc88cpu_sub;
1176         }
1177 #else
1178         if(index == 0) {
1179                 return cpu;
1180 #if defined(SUPPORT_320KB_FDD_IF)
1181         } else if(index == 1) {
1182                 return cpu_sub;
1183 #endif
1184         }
1185 #endif
1186         return NULL;
1187 }
1188 #endif
1189
1190 // ----------------------------------------------------------------------------
1191 // draw screen
1192 // ----------------------------------------------------------------------------
1193
1194 void VM::draw_screen()
1195 {
1196 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1197         if(boot_mode != 0) {
1198                 pc88->draw_screen();
1199         } else
1200 #endif
1201         display->draw_screen();
1202 }
1203
1204 // ----------------------------------------------------------------------------
1205 // soud manager
1206 // ----------------------------------------------------------------------------
1207
1208 void VM::initialize_sound(int rate, int samples)
1209 {
1210         // init sound manager
1211         event->initialize_sound(rate, samples);
1212         
1213         // init sound gen
1214 #if defined(SUPPORT_OLD_BUZZER)
1215         beep->initialize_sound(rate, 2400, 8000);
1216 #else
1217         beep->initialize_sound(rate, 8000);
1218 #endif
1219         if(sound_type == 0 || sound_type == 1) {
1220 #ifdef HAS_YM2608
1221                 opn->initialize_sound(rate, 7987248, samples, 0, 0);
1222 #else
1223                 opn->initialize_sound(rate, 3993624, samples, 0, 0);
1224 #endif
1225         } else if(sound_type == 2 || sound_type == 3) {
1226                 tms3631->initialize_sound(rate, 8000);
1227         }
1228         
1229 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1230         // init sound manager
1231         pc88event->initialize_sound(rate, samples);
1232         
1233         // init sound gen
1234 #ifdef HAS_YM2608
1235         pc88opn->initialize_sound(rate, 7987248, samples, 0, 0);
1236 #else
1237         pc88opn->initialize_sound(rate, 3993624, samples, 0, 0);
1238 #endif
1239         pc88pcm->initialize_sound(rate, 8000);
1240 #endif
1241 }
1242
1243 uint16_t* VM::create_sound(int* extra_frames)
1244 {
1245 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1246         if(boot_mode != 0) {
1247                 return pc88event->create_sound(extra_frames);
1248         } else
1249 #endif
1250         return event->create_sound(extra_frames);
1251 }
1252
1253 int VM::get_sound_buffer_ptr()
1254 {
1255 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1256         if(boot_mode != 0) {
1257                 return pc88event->get_sound_buffer_ptr();
1258         } else
1259 #endif
1260         return event->get_sound_buffer_ptr();
1261 }
1262
1263 #ifdef USE_SOUND_VOLUME
1264 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
1265 {
1266         if(ch-- == 0) {
1267                 if(sound_type == 0 || sound_type == 1) {
1268                         opn->set_volume(0, decibel_l, decibel_r);
1269                 }
1270         } else if(ch-- == 0) {
1271                 if(sound_type == 0 || sound_type == 1) {
1272                         opn->set_volume(1, decibel_l, decibel_r);
1273                 }
1274 #if defined(SUPPORT_PC98_OPNA)
1275         } else if(ch-- == 0) {
1276                 if(sound_type == 0 || sound_type == 1) {
1277                         opn->set_volume(2, decibel_l, decibel_r);
1278                 }
1279         } else if(ch-- == 0) {
1280                 if(sound_type == 0 || sound_type == 1) {
1281                         opn->set_volume(3, decibel_l, decibel_r);
1282                 }
1283 #endif
1284         } else if(ch-- == 0) {
1285                 if(sound_type == 2 || sound_type == 3) {
1286                         tms3631->set_volume(0, decibel_l, decibel_r);
1287                 }
1288         } else if(ch-- == 0) {
1289                 beep->set_volume(0, decibel_l, decibel_r);
1290 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1291         } else if(ch-- == 0) {
1292                 pc88opn->set_volume(0, decibel_l, decibel_r);
1293         } else if(ch-- == 0) {
1294                 pc88opn->set_volume(1, decibel_l, decibel_r);
1295 #if defined(SUPPORT_PC88_OPNA)
1296         } else if(ch-- == 0) {
1297                 pc88opn->set_volume(2, decibel_l, decibel_r);
1298         } else if(ch-- == 0) {
1299                 pc88opn->set_volume(3, decibel_l, decibel_r);
1300 #endif
1301         } else if(ch-- == 0) {
1302                 pc88pcm->set_volume(0, decibel_l, decibel_r);
1303 #endif
1304         } else if(ch-- == 0) {
1305                 noise_seek->set_volume(0, decibel_l, decibel_r);
1306                 noise_head_down->set_volume(0, decibel_l, decibel_r);
1307                 noise_head_up->set_volume(0, decibel_l, decibel_r);
1308 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1309                 pc88noise_seek->set_volume(0, decibel_l, decibel_r);
1310                 pc88noise_head_down->set_volume(0, decibel_l, decibel_r);
1311                 pc88noise_head_up->set_volume(0, decibel_l, decibel_r);
1312 #endif
1313         }
1314 }
1315 #endif
1316
1317 // ----------------------------------------------------------------------------
1318 // notify key
1319 // ----------------------------------------------------------------------------
1320
1321 void VM::key_down(int code, bool repeat)
1322 {
1323 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1324         if(boot_mode != 0) {
1325                 pc88->key_down(code, repeat);
1326         } else
1327 #endif
1328         keyboard->key_down(code, repeat);
1329 }
1330
1331 void VM::key_up(int code)
1332 {
1333 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1334         if(boot_mode != 0) {
1335 //              pc88->key_up(code);
1336         } else
1337 #endif
1338         keyboard->key_up(code);
1339 }
1340
1341 bool VM::get_caps_locked()
1342 {
1343 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1344         if(boot_mode != 0) {
1345                 return pc88->get_caps_locked();
1346         } else
1347 #endif
1348         return keyboard->get_caps_locked();
1349 }
1350
1351 bool VM::get_kana_locked()
1352 {
1353 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1354         if(boot_mode != 0) {
1355                 return pc88->get_kana_locked();
1356         } else
1357 #endif
1358         return keyboard->get_kana_locked();
1359 }
1360
1361 // ----------------------------------------------------------------------------
1362 // user interface
1363 // ----------------------------------------------------------------------------
1364
1365 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1366 {
1367         UPD765A *controller = get_floppy_disk_controller(drv);
1368         
1369         if(controller != NULL) {
1370                 controller->open_disk(drv & 1, file_path, bank);
1371         }
1372 }
1373
1374 void VM::close_floppy_disk(int drv)
1375 {
1376         UPD765A *controller = get_floppy_disk_controller(drv);
1377         
1378         if(controller != NULL) {
1379                 controller->close_disk(drv & 1);
1380         }
1381 }
1382
1383 bool VM::is_floppy_disk_inserted(int drv)
1384 {
1385         DISK *handler = get_floppy_disk_handler(drv);
1386         
1387         if(handler != NULL) {
1388                 return handler->inserted;
1389         }
1390         return false;
1391 }
1392
1393 void VM::is_floppy_disk_protected(int drv, bool value)
1394 {
1395         DISK *handler = get_floppy_disk_handler(drv);
1396         
1397         if(handler != NULL) {
1398                 handler->write_protected = value;
1399         }
1400 }
1401
1402 bool VM::is_floppy_disk_protected(int drv)
1403 {
1404         DISK *handler = get_floppy_disk_handler(drv);
1405         
1406         if(handler != NULL) {
1407                 return handler->write_protected;
1408         }
1409         return false;
1410 }
1411
1412 uint32_t VM::is_floppy_disk_accessed()
1413 {
1414         uint32_t status = 0;
1415         
1416 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1417         if(boot_mode != 0) {
1418                 status = pc88fdc_sub->read_signal(0) & 3;
1419         } else {
1420                 status = fdc->read_signal(0) & 3;
1421         }
1422 #else
1423         for(int drv = 0; drv < USE_FLOPPY_DISK; drv += 2) {
1424                 UPD765A *controller = get_floppy_disk_controller(drv);
1425                 
1426                 if(controller != NULL) {
1427                         status |= (controller->read_signal(0) & 3) << drv;
1428                 }
1429         }
1430 #endif
1431         return status;
1432 }
1433
1434 UPD765A *VM::get_floppy_disk_controller(int drv)
1435 {
1436 #if defined(_PC9801) || defined(_PC9801E)
1437         if(drv == 0 || drv == 1) {
1438                 return fdc_2hd;
1439         } else if(drv == 2 || drv == 3) {
1440                 return fdc_2dd;
1441         } else if(drv == 4 || drv == 5) {
1442                 return fdc_sub;
1443         }
1444 #elif defined(_PC9801VF) || defined(_PC9801U)
1445         if(drv == 0 || drv == 1) {
1446                 return fdc_2dd;
1447         }
1448 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1449         if(drv == 0 || drv == 1) {
1450                 return fdc;
1451         } else if(drv == 2 || drv == 3) {
1452                 return pc88fdc_sub;
1453         }
1454 #else
1455         if(drv == 0 || drv == 1) {
1456                 return fdc;
1457         }
1458 #endif
1459         return NULL;
1460 }
1461
1462 DISK *VM::get_floppy_disk_handler(int drv)
1463 {
1464         UPD765A *controller = get_floppy_disk_controller(drv);
1465         
1466         if(controller != NULL) {
1467                 return controller->get_disk_handler(drv & 1);
1468         }
1469         return NULL;
1470 }
1471
1472 #if defined(USE_HARD_DISK)
1473 void VM::open_hard_disk(int drv, const _TCHAR* file_path)
1474 {
1475         if(drv < USE_HARD_DISK) {
1476 #if defined(SUPPORT_SASI_IF)
1477                 sasi_hdd->open(drv, file_path, 256);
1478 #endif
1479 #if defined(SUPPORT_SCSI_IF)
1480                 scsi_hdd[drv]->open(0, file_path, 512);
1481 #endif
1482 #if defined(SUPPORT_IDE_IF)
1483                 ide_hdd[drv]->open(0, file_path, 512);
1484 #endif
1485         }
1486 }
1487
1488 void VM::close_hard_disk(int drv)
1489 {
1490         if(drv < USE_HARD_DISK) {
1491 #if defined(SUPPORT_SASI_IF)
1492                 sasi_hdd->close(drv);
1493 #endif
1494 #if defined(SUPPORT_SCSI_IF)
1495                 scsi_hdd[drv]->close(0);
1496 #endif
1497 #if defined(SUPPORT_IDE_IF)
1498                 ide_hdd[drv]->close(0);
1499 #endif
1500         }
1501 }
1502
1503 bool VM::is_hard_disk_inserted(int drv)
1504 {
1505         if(drv < USE_HARD_DISK) {
1506 #if defined(SUPPORT_SASI_IF)
1507                 return sasi_hdd->mounted(drv);
1508 #endif
1509 #if defined(SUPPORT_SCSI_IF)
1510                 return scsi_hdd[drv]->mounted(0);
1511 #endif
1512 #if defined(SUPPORT_IDE_IF)
1513                 return ide_hdd[drv]->mounted(0);
1514 #endif
1515         }
1516         return false;
1517 }
1518
1519 uint32_t VM::is_hard_disk_accessed()
1520 {
1521         uint32_t status = 0;
1522         
1523         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
1524 #if defined(SUPPORT_SASI_IF)
1525                 if(sasi_hdd->accessed(drv)) {
1526                         status |= 1 << drv;
1527                 }
1528 #endif
1529 #if defined(SUPPORT_SCSI_IF)
1530                 if(scsi_hdd[drv]->accessed(0)) {
1531                         status |= 1 << drv;
1532                 }
1533 #endif
1534 #if defined(SUPPORT_IDE_IF)
1535                 if(ide_hdd[drv]->accessed(0)) {
1536                         status |= 1 << drv;
1537                 }
1538 #endif
1539         }
1540         return status;
1541 }
1542 #endif
1543
1544 #if defined(USE_TAPE)
1545 void VM::play_tape(int drv, const _TCHAR* file_path)
1546 {
1547 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1548         pc88->play_tape(file_path);
1549 #else
1550         cmt->play_tape(file_path);
1551 #endif
1552 }
1553
1554 void VM::rec_tape(int drv, const _TCHAR* file_path)
1555 {
1556 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1557         pc88->rec_tape(file_path);
1558 #else
1559         cmt->rec_tape(file_path);
1560 #endif
1561 }
1562
1563 void VM::close_tape(int drv)
1564 {
1565 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1566         pc88->close_tape();
1567 #else
1568         cmt->close_tape();
1569 #endif
1570 }
1571
1572 bool VM::is_tape_inserted(int drv)
1573 {
1574 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1575         return pc88->is_tape_inserted();
1576 #else
1577         return cmt->is_tape_inserted();
1578 #endif
1579 }
1580 #endif
1581
1582 bool VM::is_frame_skippable()
1583 {
1584 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1585         if(boot_mode != 0) {
1586 //              return pc88event->is_frame_skippable();
1587                 return pc88->is_frame_skippable();
1588         } else
1589 #endif
1590         return event->is_frame_skippable();
1591 }
1592
1593 void VM::update_config()
1594 {
1595 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1596         if(boot_mode != config.boot_mode) {
1597                 // boot mode is changed !!!
1598                 boot_mode = config.boot_mode;
1599                 reset();
1600         } else
1601 #endif
1602         for(DEVICE* device = first_device; device; device = device->next_device) {
1603                 device->update_config();
1604         }
1605 }
1606
1607 #define STATE_VERSION   13
1608
1609 bool VM::process_state(FILEIO* state_fio, bool loading)
1610 {
1611         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
1612                 return false;
1613         }
1614         for(DEVICE* device = first_device; device; device = device->next_device) {
1615                 // Note: typeid(foo).name is fixed by recent ABI.Not dec 6.
1616                 // const char *name = typeid(*device).name();
1617                 //       But, using get_device_name() instead of typeid(foo).name() 20181008 K.O
1618                 const char *name = device->get_device_name();
1619                 int len = strlen(name);
1620                 if(!state_fio->StateCheckInt32(len)) {
1621                         if(loading) {
1622                                 printf("Class name len Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
1623                         }
1624                         return false;
1625                 }
1626                 if(!state_fio->StateCheckBuffer(name, len, 1)) {
1627                         if(loading) {
1628                                 printf("Class name Error: DEVID=%d EXPECT=%s\n", device->this_device_id, name);
1629                         }
1630                         return false;
1631                 }
1632                 if(!device->process_state(state_fio, loading)) {
1633                         if(loading) {
1634                                 printf("Data loading Error: DEVID=%d\n", device->this_device_id);
1635                         }
1636                         return false;
1637                 }
1638         }
1639         state_fio->StateBool(pit_clock_8mhz);
1640 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1641         state_fio->StateInt32(boot_mode);
1642 #endif
1643         state_fio->StateInt32(sound_type);
1644         return true;
1645 }