OSDN Git Service

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