OSDN Git Service

51f5953512f4e1574a95e98202fcd33e947e4f94
[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-98DO Emulator 'ePC-98DO'
5
6         Author : Takeda.Toshiya
7         Date   : 2010.09.15-
8
9         [ virtual machine ]
10 */
11
12 #include "pc9801.h"
13 #include "../../emu.h"
14 #include "../device.h"
15 #include "../event.h"
16
17 #if defined(SUPPORT_OLD_BUZZER)
18 #include "../beep.h"
19 #endif
20 #include "../disk.h"
21 #include "../i8237.h"
22 #include "../i8251.h"
23 #include "../i8253.h"
24 #include "../i8255.h"
25 #include "../i8259.h"
26 #if defined(HAS_I86) || defined(HAS_V30)
27 #include "../i286.h"
28 #else
29 #include "../i286.h"
30 #endif
31 #include "../io.h"
32 #include "../ls244.h"
33 #include "../memory.h"
34 #include "../noise.h"
35 #include "../not.h"
36 #if !defined(SUPPORT_OLD_BUZZER)
37 #include "../pcm1bit.h"
38 #endif
39 //#include "../pcpr201.h"
40 #include "../prnfile.h"
41 #include "../tms3631.h"
42 #include "../upd1990a.h"
43 #include "../upd7220.h"
44 #include "../upd765a.h"
45 #include "../ym2203.h"
46
47 #ifdef USE_DEBUGGER
48 #include "../debugger.h"
49 #endif
50
51 #include "display.h"
52 #include "floppy.h"
53 #include "fmsound.h"
54 #include "joystick.h"
55 #include "keyboard.h"
56 #include "mouse.h"
57
58 #if defined(SUPPORT_320KB_FDD_IF)
59 #include "../pc80s31k.h"
60 #include "../z80.h"
61 #endif
62 #if defined(SUPPORT_CMT_IF)
63 #include "cmt.h"
64 #endif
65
66 #if defined(_PC98DO) || defined(_PC98DOPLUS)
67 #include "../pc80s31k.h"
68 #include "../z80.h"
69 #include "../pc8801/pc88.h"
70 #endif
71
72 // ----------------------------------------------------------------------------
73 // initialize
74 // ----------------------------------------------------------------------------
75
76 VM::VM(EMU* parent_emu) : emu(parent_emu)
77 {
78         // check configs
79 #if defined(_PC98DO) || defined(_PC98DOPLUS)
80         boot_mode = config.boot_mode;
81 #endif
82         int cpu_clocks = CPU_CLOCKS;
83 #if defined(PIT_CLOCK_8MHZ)
84         pit_clock_8mhz = true;
85 #else
86         pit_clock_8mhz = false;
87 #endif
88 #if defined(_PC9801E)
89         if(config.cpu_type != 0) {
90                 // 8MHz -> 5MHz
91                 cpu_clocks = 4992030;
92                 pit_clock_8mhz = false;
93         }
94 #elif defined(_PC9801VM) || defined(_PC98DO)
95         if(config.cpu_type != 0) {
96                 // 10MHz -> 8MHz
97                 cpu_clocks = 7987248;
98                 pit_clock_8mhz = true;
99         }
100 #endif
101         int pit_clocks = pit_clock_8mhz ? 1996812 : 2457600;
102         
103         sound_type = config.sound_type;
104         
105         // create devices
106         first_device = last_device = NULL;
107         dummy = new DEVICE(this, emu);  // must be 1st device
108         event = new EVENT(this, emu);   // must be 2nd device
109         
110 #if defined(SUPPORT_OLD_BUZZER)
111         beep = new BEEP(this, emu);
112 #else
113         beep = new PCM1BIT(this, emu);
114 #endif
115         dma = new I8237(this, emu);
116 #if defined(SUPPORT_CMT_IF)
117         sio_cmt = new I8251(this, emu);         // for cmt
118         sio_cmt->set_device_name(_T("8251 SIO (CMT)"));
119 #endif
120         sio_rs = new I8251(this, emu);          // for rs232c
121         sio_rs->set_device_name(_T("8251 SIO (RS-232C)"));
122         sio_kbd = new I8251(this, emu);         // for keyboard
123         sio_kbd->set_device_name(_T("8251 SIO (Keyboard)"));
124         pit = new I8253(this, emu);
125 #if defined(SUPPORT_320KB_FDD_IF)
126         pio_fdd = new I8255(this, emu);         // for 320kb fdd i/f
127         pio_fdd->set_device_name(_T("8255 PIO (320KB I/F)"));
128 #endif
129         pio_mouse = new I8255(this, emu);       // for mouse
130         pio_mouse->set_device_name(_T("8255 PIO (Mouse)"));
131         pio_sys = new I8255(this, emu);         // for system port
132         pio_sys->set_device_name(_T("8255 PIO (System)"));
133         pio_prn = new I8255(this, emu);         // for printer
134         pio_prn->set_device_name(_T("8255 PIO (Printer)"));
135         pic = new I8259(this, emu);
136 #if defined(HAS_I86) || defined(HAS_V30)
137         cpu = new I286(this, emu);
138 #else
139         cpu = new I286(this, emu);
140 #endif  
141 #if defined(HAS_I86)
142         cpu->set_device_name(_T("CPU(i8086)"));
143 #elif defined(HAS_I386)
144         cpu->set_device_name(_T("CPU(i386)"));
145 #elif defined(HAS_I486)
146         cpu->set_device_name(_T("CPU(i486)"));
147 #elif defined(HAS_PENTIUM)
148         cpu->set_device_name(_T("CPU(Pentium)"));
149 #elif defined(HAS_V33A)
150         cpu->set_device_name(_T("CPU(V33A)"));
151 #elif defined(HAS_V30)
152         cpu->set_device_name(_T("CPU(V30)"));
153 #else
154         cpu->set_device_name(_T("CPU(i286)"));
155 #endif
156         io = new IO(this, emu);
157         dmareg1 = new LS244(this, emu);
158         dmareg1->set_device_name(_T("74LS244 (DMA #1)"));
159         dmareg2 = new LS244(this, emu);
160         dmareg2->set_device_name(_T("74LS244 (DMA #2)"));
161         dmareg3 = new LS244(this, emu);
162         dmareg3->set_device_name(_T("74LS244 (DMA #3)"));
163         dmareg0 = new LS244(this, emu);
164         dmareg0->set_device_name(_T("74LS244 (DMA #0)"));
165         rtcreg = new LS244(this, emu);
166         rtcreg->set_device_name(_T("74LS244 (RTC)"));
167         memory = new MEMORY(this, emu);
168         not_busy = new NOT(this, emu);
169         not_busy->set_device_name(_T("NOT Gate (Printer Busy)"));
170 #if defined(HAS_I86) || defined(HAS_V30)
171         not_prn = new NOT(this, emu);
172         not_prn->set_device_name(_T("NOT Gate (Printer IRQ)"));
173 #endif
174         rtc = new UPD1990A(this, emu);
175 #if defined(SUPPORT_2HD_FDD_IF)
176         fdc_2hd = new UPD765A(this, emu);
177         fdc_2hd->set_device_name(_T("uPD765A FDC (2HD I/F)"));
178 #endif
179 #if defined(SUPPORT_2DD_FDD_IF)
180         fdc_2dd = new UPD765A(this, emu);
181         fdc_2dd->set_device_name(_T("uPD765A FDC (2DD I/F)"));
182 #endif
183 #if defined(SUPPORT_2HD_2DD_FDD_IF)
184         fdc = new UPD765A(this, emu);
185         fdc->set_device_name(_T("uPD765A FDC (2HD/2DD I/F)"));
186 #endif
187         noise_seek = new NOISE(this, emu);
188         noise_head_down = new NOISE(this, emu);
189         noise_head_up = new NOISE(this, emu);
190         gdc_chr = new UPD7220(this, emu);
191         gdc_chr->set_device_name(_T("uPD7220 GDC (Character)"));
192         gdc_gfx = new UPD7220(this, emu);
193         gdc_gfx->set_device_name(_T("uPD7220 GDC (Graphics)"));
194         
195         if(sound_type == 0 || sound_type == 1) {
196                 opn = new YM2203(this, emu);
197 #ifdef SUPPORT_PC98_OPNA
198                 opn->is_ym2608 = true;
199 #endif
200                 fmsound = new FMSOUND(this, emu);
201                 joystick = new JOYSTICK(this, emu);
202         } else if(sound_type == 2 || sound_type == 3) {
203                 tms3631 = new TMS3631(this, emu);
204                 tms3631->set_device_name(_T("TMS3631 SSG (PC-9801-14)"));
205                 pit_14 = new I8253(this, emu);
206                 pit_14->set_device_name(_T("8253 PIT (PC-9801-14)"));
207                 pio_14 = new I8255(this, emu);
208                 pio_14->set_device_name(_T("8255 PIO (PC-9801-14)"));
209                 maskreg_14 = new LS244(this, emu);
210                 maskreg_14->set_device_name(_T("74LS244 (PC-9801-14)"));
211         }
212         if(config.printer_type == 0) {
213                 printer = new PRNFILE(this, emu);
214 //      } else if(config.printer_type == 1) {
215 //              printer = new PCPR201(this, emu);
216         } else {
217                 printer = dummy;
218         }
219         
220 #if defined(SUPPORT_CMT_IF)
221         cmt = new CMT(this, emu);
222 #endif
223         display = new DISPLAY(this, emu);
224         floppy = new FLOPPY(this, emu);
225         keyboard = new KEYBOARD(this, emu);
226         mouse = new MOUSE(this, emu);
227         
228 #if defined(SUPPORT_320KB_FDD_IF)
229         // 320kb fdd drives
230         pio_sub = new I8255(this, emu);
231         pio_sub->set_device_name(_T("8255 PIO (320KB FDD)"));
232         pc80s31k = new PC80S31K(this, emu);
233         pc80s31k->set_device_name(_T("PC-80S31K (320KB FDD)"));
234         fdc_sub = new UPD765A(this, emu);
235         fdc_sub->set_device_name(_T("uPD765A FDC (320KB FDD)"));
236         cpu_sub = new Z80(this, emu);
237         cpu_sub->set_device_name(_T("Z80 CPU (320KB FDD)"));
238 #endif
239         
240         /* IRQ  0  PIT
241                 1  KEYBOARD
242                 2  CRTV
243                 3  (INT0)
244                 4  RS-232C
245                 5  (INT1)
246                 6  (INT2)
247                 7  SLAVE PIC
248                 8  PRINTER
249                 9  (INT3)
250                 10 (INT41) FDC (640KB I/F)
251                 11 (INT42) FDC (1MB I/F)
252                 12 (INT5) PC-9801-26(K) or PC-9801-14
253                 13 (INT6) MOUSE
254                 14 
255                 15 (RESERVED)
256         */
257         
258         // set contexts
259         event->set_context_cpu(cpu, cpu_clocks);
260 #if defined(SUPPORT_320KB_FDD_IF)
261         event->set_context_cpu(cpu_sub, 4000000);
262 #endif
263         event->set_context_sound(beep);
264         if(sound_type == 0 || sound_type == 1) {
265                 event->set_context_sound(opn);
266         } else if(sound_type == 2 || sound_type == 3) {
267                 event->set_context_sound(tms3631);
268         }
269         event->set_context_sound(noise_seek);
270         event->set_context_sound(noise_head_down);
271         event->set_context_sound(noise_head_up);
272         
273         dma->set_context_memory(memory);
274         // dma ch.0: sasi
275         // dma ch.1: memory refresh
276 #if defined(SUPPORT_2HD_FDD_IF)
277         dma->set_context_ch2(fdc_2hd);
278 #endif
279 #if defined(SUPPORT_2DD_FDD_IF)
280         dma->set_context_ch3(fdc_2dd);
281 #endif
282 #if defined(SUPPORT_2HD_2DD_FDD_IF)
283         dma->set_context_ch2(fdc);
284         dma->set_context_ch3(fdc);
285 #endif
286 //      sio_rs->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR4, 1);
287         sio_kbd->set_context_rxrdy(pic, SIG_I8259_CHIP0 | SIG_I8259_IR1, 1);
288         pit->set_context_ch0(pic, SIG_I8259_CHIP0 | SIG_I8259_IR0, 1);
289 #if defined(SUPPORT_OLD_BUZZER)
290         // pit ch.1: memory refresh
291 #else
292         // pit ch.1: buzzer
293         pit->set_context_ch1(beep, SIG_PCM1BIT_SIGNAL, 1);
294 #endif
295         // pit ch.2: rs-232c
296         pit->set_constant_clock(0, pit_clocks);
297         pit->set_constant_clock(1, pit_clocks);
298         pit->set_constant_clock(2, pit_clocks);
299         pio_mouse->set_context_port_c(mouse, SIG_MOUSE_PORT_C, 0xf0, 0);
300         // sysport port.c bit6: printer strobe
301 #if defined(SUPPORT_OLD_BUZZER)
302         pio_sys->set_context_port_c(beep, SIG_BEEP_MUTE, 8, 0);
303 #else
304         pio_sys->set_context_port_c(beep, SIG_PCM1BIT_MUTE, 8, 0);
305 #endif
306         // sysport port.c bit2: enable txrdy interrupt
307         // sysport port.c bit1: enable txempty interrupt
308         // sysport port.c bit0: enable rxrdy interrupt
309         pio_prn->set_context_port_a(printer, SIG_PRINTER_DATA, 0xff, 0);
310         pio_prn->set_context_port_c(printer, SIG_PRINTER_STROBE, 0x80, 0);
311         if(config.printer_type == 0) {
312                 PRNFILE *prnfile = (PRNFILE *)printer;
313                 prnfile->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
314 //      } else if(config.printer_type == 1) {
315 //              PRNFILE *pcpr201 = (PCPR201 *)printer;
316 //              pcpr201->set_context_busy(not_busy, SIG_NOT_INPUT, 1);
317         }
318         not_busy->set_context_out(pio_prn, SIG_I8255_PORT_B, 4);
319 #if defined(HAS_I86) || defined(HAS_V30)
320         pio_prn->set_context_port_c(not_prn, SIG_NOT_INPUT, 8, 0);
321         not_prn->set_context_out(pic, SIG_I8259_CHIP1 | SIG_I8259_IR0, 1);
322 #endif
323         dmareg1->set_context_output(dma, SIG_I8237_BANK1, 0x0f, 0);
324         dmareg2->set_context_output(dma, SIG_I8237_BANK2, 0x0f, 0);
325         dmareg3->set_context_output(dma, SIG_I8237_BANK3, 0x0f, 0);
326         dmareg0->set_context_output(dma, SIG_I8237_BANK0, 0x0f, 0);
327         rtcreg->set_context_output(rtc, SIG_UPD1990A_CMD, 0x07, 0);
328         rtcreg->set_context_output(rtc, SIG_UPD1990A_DIN, 0x20, 0);
329         rtcreg->set_context_output(rtc, SIG_UPD1990A_STB, 0x08, 0);
330         rtcreg->set_context_output(rtc, SIG_UPD1990A_CLK, 0x10, 0);
331         pic->set_context_cpu(cpu);
332         rtc->set_context_dout(pio_sys, SIG_I8255_PORT_B, 1);
333         
334         if(sound_type == 0 || sound_type == 1) {
335                 opn->set_context_irq(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
336                 opn->set_context_port_b(joystick, SIG_JOYSTICK_SELECT, 0xc0, 0);
337                 fmsound->set_context_opn(opn);
338                 joystick->set_context_opn(opn);
339         } else if(sound_type == 2 || sound_type == 3) {
340                 pio_14->set_context_port_a(tms3631, SIG_TMS3631_ENVELOP1, 0xff, 0);
341                 pio_14->set_context_port_b(tms3631, SIG_TMS3631_ENVELOP2, 0xff, 0);
342                 pio_14->set_context_port_c(tms3631, SIG_TMS3631_DATAREG, 0xff, 0);
343                 maskreg_14->set_context_output(tms3631, SIG_TMS3631_MASKREG, 0xff, 0);
344                 pit_14->set_constant_clock(2, 1996800 / 8);
345                 pit_14->set_context_ch2(pic, SIG_I8259_CHIP1 | SIG_I8259_IR4, 1);
346         }
347         
348         display->set_context_pic(pic);
349         display->set_context_gdc_chr(gdc_chr, gdc_chr->get_ra());
350         display->set_context_gdc_gfx(gdc_gfx, gdc_gfx->get_ra(), gdc_gfx->get_cs());
351         keyboard->set_context_sio(sio_kbd);
352         mouse->set_context_pic(pic);
353         mouse->set_context_pio(pio_mouse);
354         
355 #if defined(SUPPORT_2HD_FDD_IF)
356         fdc_2hd->set_context_irq(floppy, SIG_FLOPPY_2HD_IRQ, 1);
357         fdc_2hd->set_context_drq(floppy, SIG_FLOPPY_2HD_DRQ, 1);
358         fdc_2hd->set_context_noise_seek(noise_seek);
359         fdc_2hd->set_context_noise_head_down(noise_head_down);
360         fdc_2hd->set_context_noise_head_up(noise_head_up);
361         fdc_2hd->raise_irq_when_media_changed = true;
362         floppy->set_context_fdc_2hd(fdc_2hd);
363 #endif
364 #if defined(SUPPORT_2DD_FDD_IF)
365         fdc_2dd->set_context_irq(floppy, SIG_FLOPPY_2DD_IRQ, 1);
366         fdc_2dd->set_context_drq(floppy, SIG_FLOPPY_2DD_DRQ, 1);
367         fdc_2dd->set_context_noise_seek(noise_seek);
368         fdc_2dd->set_context_noise_head_down(noise_head_down);
369         fdc_2dd->set_context_noise_head_up(noise_head_up);
370         fdc_2dd->raise_irq_when_media_changed = true;
371         floppy->set_context_fdc_2dd(fdc_2dd);
372 #endif
373 #if defined(SUPPORT_2HD_2DD_FDD_IF)
374         fdc->set_context_irq(floppy, SIG_FLOPPY_IRQ, 1);
375         fdc->set_context_drq(floppy, SIG_FLOPPY_DRQ, 1);
376         fdc->set_context_noise_seek(noise_seek);
377         fdc->set_context_noise_head_down(noise_head_down);
378         fdc->set_context_noise_head_up(noise_head_up);
379         fdc->raise_irq_when_media_changed = true;
380         floppy->set_context_fdc(fdc);
381 #endif
382         floppy->set_context_dma(dma);
383         floppy->set_context_pic(pic);
384         
385 #if defined(SUPPORT_CMT_IF)
386         sio_cmt->set_context_out(cmt, SIG_CMT_OUT);
387 //      sio_cmt->set_context_txrdy(cmt, SIG_CMT_TXRDY, 1);
388 //      sio_cmt->set_context_rxrdy(cmt, SIG_CMT_RXRDY, 1);
389 //      sio_cmt->set_context_txe(cmt, SIG_CMT_TXEMP, 1);
390         cmt->set_context_sio(sio_cmt);
391 #endif
392         
393         // cpu bus
394         cpu->set_context_mem(memory);
395         cpu->set_context_io(io);
396         cpu->set_context_intr(pic);
397 #ifdef SINGLE_MODE_DMA
398         cpu->set_context_dma(dma);
399 #endif
400 #ifdef USE_DEBUGGER
401         cpu->set_context_debugger(new DEBUGGER(this, emu));
402 #endif
403         
404 #if defined(SUPPORT_320KB_FDD_IF)
405         // 320kb fdd drives
406         pc80s31k->set_context_cpu(cpu_sub);
407         pc80s31k->set_context_fdc(fdc_sub);
408         pc80s31k->set_context_pio(pio_sub);
409         pio_fdd->set_context_port_a(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
410         pio_fdd->set_context_port_b(pio_sub, SIG_I8255_PORT_A, 0xff, 0);
411         pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
412         pio_fdd->set_context_port_c(pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
413         pio_fdd->clear_ports_by_cmdreg = true;
414         pio_sub->set_context_port_a(pio_fdd, SIG_I8255_PORT_B, 0xff, 0);
415         pio_sub->set_context_port_b(pio_fdd, SIG_I8255_PORT_A, 0xff, 0);
416         pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0x0f, 4);
417         pio_sub->set_context_port_c(pio_fdd, SIG_I8255_PORT_C, 0xf0, -4);
418         pio_sub->clear_ports_by_cmdreg = true;
419         fdc_sub->set_context_irq(cpu_sub, SIG_CPU_IRQ, 1);
420         fdc_sub->set_context_noise_seek(noise_seek);
421         fdc_sub->set_context_noise_head_down(noise_head_down);
422         fdc_sub->set_context_noise_head_up(noise_head_up);
423         cpu_sub->set_context_mem(pc80s31k);
424         cpu_sub->set_context_io(pc80s31k);
425         cpu_sub->set_context_intr(pc80s31k);
426 #ifdef USE_DEBUGGER
427         cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
428 #endif
429 #endif
430         
431         // memory bus
432         memset(ram, 0, sizeof(ram));
433         memset(ipl, 0xff, sizeof(ipl));
434         memset(sound_bios, 0xff, sizeof(sound_bios));
435 #if defined(_PC9801) || defined(_PC9801E)
436         memset(fd_bios_2hd, 0xff, sizeof(fd_bios_2hd));
437         memset(fd_bios_2dd, 0xff, sizeof(fd_bios_2dd));
438 #endif
439         
440         memory->read_bios(_T("IPL.ROM"), ipl, sizeof(ipl));
441         if(sound_type == 0) {
442                 display->sound_bios_ok = (memory->read_bios(_T("SOUND.ROM"), sound_bios, sizeof(sound_bios)) != 0);
443         } else if(sound_type == 2) {
444                 display->sound_bios_ok = (memory->read_bios(_T("MUSIC.ROM"), sound_bios, sizeof(sound_bios)) != 0);
445         } else {
446                 display->sound_bios_ok = false;
447         }
448 #if defined(_PC9801) || defined(_PC9801E)
449         memory->read_bios(_T("2HDIF.ROM"), fd_bios_2hd, sizeof(fd_bios_2hd));
450         memory->read_bios(_T("2DDIF.ROM"), fd_bios_2dd, sizeof(fd_bios_2dd));
451 #endif
452         
453         memory->set_memory_rw(0x00000, 0x9ffff, ram);
454         // A0000h - A1FFFh: TEXT VRAM
455         // A2000h - A3FFFh: ATTRIBUTE
456         memory->set_memory_mapped_io_rw(0xa0000, 0xa3fff, display);
457         // A8000h - BFFFFh: VRAM
458         memory->set_memory_mapped_io_rw(0xa8000, 0xbffff, display);
459         if(sound_type == 0 || sound_type == 2) {
460                 memory->set_memory_r(0xcc000, 0xcffff, sound_bios);
461         }
462 #if defined(_PC9801) || defined(_PC9801E)
463         memory->set_memory_r(0xd6000, 0xd6fff, fd_bios_2dd);
464         memory->set_memory_r(0xd7000, 0xd7fff, fd_bios_2hd);
465 #endif
466 #if defined(SUPPORT_16_COLORS)
467         // E0000h - E7FFFh: VRAM
468         memory->set_memory_mapped_io_rw(0xe0000, 0xe7fff, display);
469 #endif
470         memory->set_memory_r(0xe8000, 0xfffff, ipl);
471         
472         // i/o bus
473         io->set_iomap_alias_rw(0x00, pic, 0);
474         io->set_iomap_alias_rw(0x02, pic, 1);
475         io->set_iomap_alias_rw(0x08, pic, 2);
476         io->set_iomap_alias_rw(0x0a, pic, 3);
477         
478         io->set_iomap_alias_rw(0x01, dma, 0x00);
479         io->set_iomap_alias_rw(0x03, dma, 0x01);
480         io->set_iomap_alias_rw(0x05, dma, 0x02);
481         io->set_iomap_alias_rw(0x07, dma, 0x03);
482         io->set_iomap_alias_rw(0x09, dma, 0x04);
483         io->set_iomap_alias_rw(0x0b, dma, 0x05);
484         io->set_iomap_alias_rw(0x0d, dma, 0x06);
485         io->set_iomap_alias_rw(0x0f, dma, 0x07);
486         io->set_iomap_alias_rw(0x11, dma, 0x08);
487         io->set_iomap_alias_w(0x13, dma, 0x09);
488         io->set_iomap_alias_w(0x15, dma, 0x0a);
489         io->set_iomap_alias_w(0x17, dma, 0x0b);
490         io->set_iomap_alias_w(0x19, dma, 0x0c);
491         io->set_iomap_alias_rw(0x1b, dma, 0x0d);
492         io->set_iomap_alias_w(0x1d, dma, 0x0e);
493         io->set_iomap_alias_w(0x1f, dma, 0x0f);
494         io->set_iomap_single_w(0x21, dmareg1);
495         io->set_iomap_single_w(0x23, dmareg2);
496         io->set_iomap_single_w(0x25, dmareg3);
497         io->set_iomap_single_w(0x27, dmareg0);
498         
499         io->set_iomap_single_w(0x20, rtcreg);
500         
501         io->set_iomap_alias_rw(0x30, sio_rs, 0);
502         io->set_iomap_alias_rw(0x32, sio_rs, 1);
503         
504         io->set_iomap_alias_rw(0x31, pio_sys, 0);
505         io->set_iomap_alias_rw(0x33, pio_sys, 1);
506         io->set_iomap_alias_rw(0x35, pio_sys, 2);
507         io->set_iomap_alias_w(0x37, pio_sys, 3);
508         
509         io->set_iomap_alias_rw(0x40, pio_prn, 0);
510         io->set_iomap_alias_rw(0x42, pio_prn, 1);
511         io->set_iomap_alias_rw(0x44, pio_prn, 2);
512         io->set_iomap_alias_w(0x46, pio_prn, 3);
513         
514         io->set_iomap_alias_rw(0x41, sio_kbd, 0);
515         io->set_iomap_alias_rw(0x43, sio_kbd, 1);
516         
517         // 50h, 52h: NMI Flip Flop
518         
519 #if defined(SUPPORT_320KB_FDD_IF)
520         io->set_iomap_alias_rw(0x51, pio_fdd, 0);
521         io->set_iomap_alias_rw(0x53, pio_fdd, 1);
522         io->set_iomap_alias_rw(0x55, pio_fdd, 2);
523         io->set_iomap_alias_w(0x57, pio_fdd, 3);
524 #endif
525         
526         io->set_iomap_alias_rw(0x60, gdc_chr, 0);
527         io->set_iomap_alias_rw(0x62, gdc_chr, 1);
528         
529         io->set_iomap_single_w(0x64, display);
530         io->set_iomap_single_w(0x68, display);
531 #if defined(SUPPORT_16_COLORS)
532         io->set_iomap_single_w(0x6a, display);
533 #endif
534         io->set_iomap_single_w(0x6c, display);
535         io->set_iomap_single_w(0x6e, display);
536         
537         io->set_iomap_single_w(0x70, display);
538         io->set_iomap_single_w(0x72, display);
539         io->set_iomap_single_w(0x74, display);
540         io->set_iomap_single_w(0x76, display);
541         io->set_iomap_single_w(0x78, display);
542         io->set_iomap_single_w(0x7a, display);
543 #if defined(SUPPORT_16_COLORS)
544         io->set_iomap_single_w(0x7c, display);
545         io->set_iomap_single_w(0x7e, display);
546 #endif
547         
548         io->set_iomap_alias_rw(0x71, pit, 0);
549         io->set_iomap_alias_rw(0x73, pit, 1);
550         io->set_iomap_alias_rw(0x75, pit, 2);
551         io->set_iomap_alias_w(0x77, pit, 3);
552         
553         // 80h, 82h: SASI
554         
555         io->set_iomap_single_rw(0x90, floppy);
556         io->set_iomap_single_rw(0x92, floppy);
557         io->set_iomap_single_rw(0x94, floppy);
558         
559 #if defined(SUPPORT_CMT_IF)
560         io->set_iomap_alias_rw(0x91, sio_cmt, 0);
561         io->set_iomap_alias_rw(0x93, sio_cmt, 1);
562         io->set_iomap_single_w(0x95, cmt);
563         io->set_iomap_single_w(0x97, cmt);
564 #endif
565         
566         io->set_iomap_alias_rw(0xa0, gdc_gfx, 0);
567         io->set_iomap_alias_rw(0xa2, gdc_gfx, 1);
568         
569 #if defined(SUPPORT_2ND_VRAM)
570         io->set_iomap_single_w(0xa4, display);
571         io->set_iomap_single_w(0xa6, display);
572 #endif
573         io->set_iomap_single_rw(0xa8, display);
574         io->set_iomap_single_rw(0xaa, display);
575         io->set_iomap_single_rw(0xac, display);
576         io->set_iomap_single_rw(0xae, display);
577         
578         io->set_iomap_single_w(0xa1, display);
579         io->set_iomap_single_w(0xa3, display);
580         io->set_iomap_single_w(0xa5, display);
581         io->set_iomap_single_rw(0xa9, display);
582         
583 #if defined(SUPPORT_2HD_2DD_FDD_IF)
584         io->set_iomap_single_rw(0xbe, floppy);
585 #endif
586         io->set_iomap_single_rw(0xc8, floppy);
587         io->set_iomap_single_rw(0xca, floppy);
588         io->set_iomap_single_rw(0xcc, floppy);
589         
590         if(sound_type == 0 || sound_type == 1) {
591                 io->set_iomap_single_rw(0x188, fmsound);
592                 io->set_iomap_single_rw(0x18a, fmsound);
593 #ifdef SUPPORT_PC98_OPNA
594                 io->set_iomap_single_rw(0x18c, fmsound);
595                 io->set_iomap_single_rw(0x18e, fmsound);
596                 io->set_iomap_single_rw(0xa460, fmsound);
597 #endif
598         } else if(sound_type == 2 || sound_type == 3) {
599                 io->set_iomap_alias_rw(0x88, pio_14, 0);
600                 io->set_iomap_alias_rw(0x8a, pio_14, 1);
601                 io->set_iomap_alias_rw(0x8c, pio_14, 2);
602                 io->set_iomap_alias_w(0x8e, pio_14, 3);
603                 io->set_iovalue_single_r(0x8e, 0x08);
604                 io->set_iomap_single_w(0x188, maskreg_14);
605                 io->set_iomap_single_w(0x18a, maskreg_14);
606                 io->set_iomap_alias_rw(0x18c, pit_14, 2);
607                 io->set_iomap_alias_w(0x18e, pit_14, 3);
608 //              io->set_iovalue_single_r(0x18e, 0x00); // INT0
609 //              io->set_iovalue_single_r(0x18e, 0x40); // INT41
610                 io->set_iovalue_single_r(0x18e, 0x80); // INT5
611 //              io->set_iovalue_single_r(0x18e, 0xc0); // INT6
612         }
613         
614 #if !defined(SUPPORT_OLD_BUZZER)
615         io->set_iomap_alias_rw(0x3fd9, pit, 0);
616         io->set_iomap_alias_rw(0x3fdb, pit, 1);
617         io->set_iomap_alias_rw(0x3fdd, pit, 2);
618         io->set_iomap_alias_w(0x3fdf, pit, 3);
619 #endif
620         
621         io->set_iomap_alias_rw(0x7fd9, pio_mouse, 0);
622         io->set_iomap_alias_rw(0x7fdb, pio_mouse, 1);
623         io->set_iomap_alias_rw(0x7fdd, pio_mouse, 2);
624         io->set_iomap_alias_w(0x7fdf, pio_mouse, 3);
625 #if !(defined(_PC9801) || defined(_PC9801E))
626         io->set_iomap_single_w(0xbfdb, mouse);
627 #endif
628         
629 #if defined(_PC98DO) || defined(_PC98DOPLUS)
630         pc88event = new EVENT(this, emu);
631         pc88event->set_device_name(_T("Event Manager (PC-8801)"));
632         pc88event->set_frames_per_sec(60);
633         pc88event->set_lines_per_frame(260);
634         
635         pc88 = new PC88(this, emu);
636         pc88->set_context_event_manager(pc88event);
637         pc88sio = new I8251(this, emu);
638         pc88sio->set_device_name(_T("8251 SIO (PC-8801)"));
639         pc88sio->set_context_event_manager(pc88event);
640         pc88pio = new I8255(this, emu);
641         pc88pio->set_device_name(_T("8255 PIO (PC-8801)"));
642         pc88pio->set_context_event_manager(pc88event);
643         pc88pcm = new PCM1BIT(this, emu);
644         pc88pcm->set_device_name(_T("1-Bit PCM Sound (PC-8801)"));
645         pc88pcm->set_context_event_manager(pc88event);
646         pc88rtc = new UPD1990A(this, emu);
647         pc88rtc->set_device_name(_T("uPD1990A RTC (PC-8801)"));
648         pc88rtc->set_context_event_manager(pc88event);
649         pc88opn = new YM2203(this, emu);
650 #ifdef SUPPORT_PC88_OPNA
651         pc88opn->set_device_name(_T("YM2608 OPNA (PC-8801)"));
652         pc88opn->is_ym2608 = true;
653 #else
654         pc88opn->set_device_name(_T("YM2203 OPN (PC-8801)"));
655 #endif
656         pc88opn->set_context_event_manager(pc88event);
657         pc88cpu = new Z80(this, emu);
658         pc88cpu->set_device_name(_T("Z80 CPU (PC-8801)"));
659         pc88cpu->set_context_event_manager(pc88event);
660         
661         if(config.printer_type == 0) {
662                 pc88prn = new PRNFILE(this, emu);
663                 pc88prn->set_context_event_manager(pc88event);
664 //      } else if(config.printer_type == 1) {
665 //              pc88prn = new PCPR201(this, emu);
666 //              pc88prn->set_context_event_manager(pc88event);
667         } else {
668                 pc88prn = dummy;
669         }
670         
671         pc88sub = new PC80S31K(this, emu);
672         pc88sub->set_device_name(_T("PC-80S31K (PC-8801 Sub)"));
673         pc88sub->set_context_event_manager(pc88event);
674         pc88pio_sub = new I8255(this, emu);
675         pc88pio_sub->set_device_name(_T("8255 PIO (PC-8801 Sub)"));
676         pc88pio_sub->set_context_event_manager(pc88event);
677         pc88fdc_sub = new UPD765A(this, emu);
678         pc88fdc_sub->set_device_name(_T("uPD765A FDC (PC-8801 Sub)"));
679         pc88fdc_sub->set_context_event_manager(pc88event);
680         pc88noise_seek = new NOISE(this, emu);
681         pc88noise_seek->set_context_event_manager(pc88event);
682         pc88noise_head_down = new NOISE(this, emu);
683         pc88noise_head_down->set_context_event_manager(pc88event);
684         pc88noise_head_up = new NOISE(this, emu);
685         pc88noise_head_up->set_context_event_manager(pc88event);
686         pc88cpu_sub = new Z80(this, emu);
687         pc88cpu_sub->set_device_name(_T("Z80 CPU (PC-8801 Sub)"));
688         pc88cpu_sub->set_context_event_manager(pc88event);
689         
690         pc88event->set_context_cpu(pc88cpu, (config.cpu_type != 0) ? 3993624 : 7987248);
691         pc88event->set_context_cpu(pc88cpu_sub, 3993624);
692         pc88event->set_context_sound(pc88opn);
693         pc88event->set_context_sound(pc88pcm);
694         pc88event->set_context_sound(pc88noise_seek);
695         pc88event->set_context_sound(pc88noise_head_down);
696         pc88event->set_context_sound(pc88noise_head_up);
697         
698         pc88->set_context_cpu(pc88cpu);
699         pc88->set_context_opn(pc88opn);
700         pc88->set_context_pcm(pc88pcm);
701         pc88->set_context_pio(pc88pio);
702         pc88->set_context_prn(pc88prn);
703         pc88->set_context_rtc(pc88rtc);
704         pc88->set_context_sio(pc88sio);
705         pc88cpu->set_context_mem(pc88);
706         pc88cpu->set_context_io(pc88);
707         pc88cpu->set_context_intr(pc88);
708 #ifdef USE_DEBUGGER
709         pc88cpu->set_context_debugger(new DEBUGGER(this, emu));
710 #endif
711         pc88opn->set_context_irq(pc88, SIG_PC88_SOUND_IRQ, 1);
712         pc88sio->set_context_rxrdy(pc88, SIG_PC88_USART_IRQ, 1);
713         pc88sio->set_context_out(pc88, SIG_PC88_USART_OUT);
714         
715         pc88sub->set_context_cpu(pc88cpu_sub);
716         pc88sub->set_context_fdc(pc88fdc_sub);
717         pc88sub->set_context_pio(pc88pio_sub);
718         pc88pio->set_context_port_a(pc88pio_sub, SIG_I8255_PORT_B, 0xff, 0);
719         pc88pio->set_context_port_b(pc88pio_sub, SIG_I8255_PORT_A, 0xff, 0);
720         pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0x0f, 4);
721         pc88pio->set_context_port_c(pc88pio_sub, SIG_I8255_PORT_C, 0xf0, -4);
722         pc88pio->clear_ports_by_cmdreg = true;
723         pc88pio_sub->set_context_port_a(pc88pio, SIG_I8255_PORT_B, 0xff, 0);
724         pc88pio_sub->set_context_port_b(pc88pio, SIG_I8255_PORT_A, 0xff, 0);
725         pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0x0f, 4);
726         pc88pio_sub->set_context_port_c(pc88pio, SIG_I8255_PORT_C, 0xf0, -4);
727         pc88pio_sub->clear_ports_by_cmdreg = true;
728         pc88fdc_sub->set_context_irq(pc88cpu_sub, SIG_CPU_IRQ, 1);
729         pc88fdc_sub->set_context_noise_seek(pc88noise_seek);
730         pc88fdc_sub->set_context_noise_head_down(pc88noise_head_down);
731         pc88fdc_sub->set_context_noise_head_up(pc88noise_head_up);
732         pc88cpu_sub->set_context_mem(pc88sub);
733         pc88cpu_sub->set_context_io(pc88sub);
734         pc88cpu_sub->set_context_intr(pc88sub);
735 #ifdef USE_DEBUGGER
736         pc88cpu_sub->set_context_debugger(new DEBUGGER(this, emu));
737 #endif
738 #endif
739         
740         // initialize all devices
741         for(DEVICE* device = first_device; device; device = device->next_device) {
742                 device->initialize();
743         }
744 #if defined(_PC9801) || defined(_PC9801E)
745         fdc_2hd->get_disk_handler(0)->drive_num = 0;
746         fdc_2hd->get_disk_handler(1)->drive_num = 1;
747         fdc_2dd->get_disk_handler(0)->drive_num = 2;
748         fdc_2dd->get_disk_handler(1)->drive_num = 3;
749         fdc_sub->get_disk_handler(0)->drive_num = 4;
750         fdc_sub->get_disk_handler(1)->drive_num = 5;
751 #elif defined(_PC9801VF) || defined(_PC9801U)
752         fdc_2dd->get_disk_handler(0)->drive_num = 0;
753         fdc_2dd->get_disk_handler(1)->drive_num = 1;
754 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
755         fdc->get_disk_handler(0)->drive_num = 0;
756         fdc->get_disk_handler(1)->drive_num = 1;
757         pc88fdc_sub->get_disk_handler(0)->drive_num = 2;
758         pc88fdc_sub->get_disk_handler(1)->drive_num = 3;
759 #else
760         fdc->get_disk_handler(0)->drive_num = 0;
761         fdc->get_disk_handler(1)->drive_num = 1;
762 #endif
763 }
764
765 VM::~VM()
766 {
767         // delete all devices
768         for(DEVICE* device = first_device; device;) {
769                 DEVICE *next_device = device->next_device;
770                 device->release();
771                 delete device;
772                 device = next_device;
773         }
774 }
775
776 DEVICE* VM::get_device(int id)
777 {
778         for(DEVICE* device = first_device; device; device = device->next_device) {
779                 if(device->this_device_id == id) {
780                         return device;
781                 }
782         }
783         return NULL;
784 }
785
786 // ----------------------------------------------------------------------------
787 // drive virtual machine
788 // ----------------------------------------------------------------------------
789
790 void VM::reset()
791 {
792         // reset all devices
793         for(DEVICE* device = first_device; device; device = device->next_device) {
794                 device->reset();
795         }
796 #if defined(_PC98DO) || defined(_PC98DOPLUS)
797         for(DEVICE* device = first_device; device; device = device->next_device) {
798                 device->reset();
799         }
800 #endif
801         
802         // initial device settings
803         pio_mouse->write_signal(SIG_I8255_PORT_A, 0xf0, 0xff);  // clear mouse status
804         pio_mouse->write_signal(SIG_I8255_PORT_B, 0x40, 0xff);  // cpu high & sw3-6
805         uint8_t port_c = 0x08;  // normal mode & sw1-5 & sw1-6
806 #if defined(HAS_V30) || defined(HAS_V33)
807         port_c |= 0x04;         // V30
808 #endif
809         pio_mouse->write_signal(SIG_I8255_PORT_C, 0x40, 0xff);
810         
811         pio_sys->write_signal(SIG_I8255_PORT_A, 0xe3, 0xff);
812         pio_sys->write_signal(SIG_I8255_PORT_B, 0xf8, 0xff);//0xe8??
813         
814 #if defined(_PC9801)
815         uint8_t prn_b = 0x00;   // system type = first PC-9801
816 #elif defined(_PC9801U)
817         uint8_t prn_b = 0xc0;   // system type = PC-9801U,PC-98LT,PC-98HA
818 #else
819         uint8_t prn_b = 0x80;   // system type = others
820 #endif
821         if(pit_clock_8mhz) {
822                 prn_b |= 0x20;          // system clock is 8MHz
823         }
824         prn_b |= 0x10;          // don't use LCD display
825 #if !defined(SUPPORT_16_COLORS)
826         prn_b |= 0x08;          // standard graphics
827 #endif
828         prn_b |= 0x04;          // printer is not busy
829 #if defined(HAS_V30) || defined(HAS_V33)
830         prn_b |= 0x02;
831 #endif
832 #if defined(_PC9801VF) || defined(_PC9801U)
833         prn_b |= 0x01;          // PC-9801VF or PC-9801U
834 #endif
835         pio_prn->write_signal(SIG_I8255_PORT_B, prn_b, 0xff);
836         
837 #if defined(SUPPORT_320KB_FDD_IF)
838         pio_fdd->write_signal(SIG_I8255_PORT_A, 0xff, 0xff);
839         pio_fdd->write_signal(SIG_I8255_PORT_B, 0xff, 0xff);
840         pio_fdd->write_signal(SIG_I8255_PORT_C, 0xff, 0xff);
841 #endif
842 #if defined(SUPPORT_2DD_FDD_IF)
843         fdc_2dd->write_signal(SIG_UPD765A_FREADY, 1, 1);        // 2DD FDC RDY is pulluped
844 #endif
845         
846         if(sound_type == 0 || sound_type == 1) {
847 //              opn->write_signal(SIG_YM2203_PORT_A, 0x3f, 0xff);       // PC-9801-26(K) INT0
848 //              opn->write_signal(SIG_YM2203_PORT_A, 0xbf, 0xff);       // PC-9801-26(K) INT41
849                 opn->write_signal(SIG_YM2203_PORT_A, 0xff, 0xff);       // PC-9801-26(K) INT5
850 //              opn->write_signal(SIG_YM2203_PORT_A, 0x7f, 0xff);       // PC-9801-26(K) INT6
851         }
852         
853 #if defined(SUPPORT_OLD_BUZZER)
854         beep->write_signal(SIG_BEEP_ON, 1, 1);
855         beep->write_signal(SIG_BEEP_MUTE, 1, 1);
856 #else
857         beep->write_signal(SIG_PCM1BIT_ON, 1, 1);
858         beep->write_signal(SIG_PCM1BIT_MUTE, 1, 1);
859 #endif
860         
861 #if defined(_PC98DO) || defined(_PC98DOPLUS)
862         pc88opn->set_reg(0x29, 3); // for Misty Blue
863         pc88pio->write_signal(SIG_I8255_PORT_C, 0, 0xff);
864         pc88pio_sub->write_signal(SIG_I8255_PORT_C, 0, 0xff);
865 #endif
866 }
867
868 void VM::run()
869 {
870 #if defined(_PC98DO) || defined(_PC98DOPLUS)
871         if(boot_mode != 0) {
872                 pc88event->drive();
873         } else
874 #endif
875         event->drive();
876 }
877
878 double VM::get_frame_rate()
879 {
880 #if defined(_PC98DO) || defined(_PC98DOPLUS)
881         if(config.boot_mode != 0) {
882                 return pc88event->get_frame_rate();
883         } else
884 #endif
885         return event->get_frame_rate();
886 }
887
888 // ----------------------------------------------------------------------------
889 // debugger
890 // ----------------------------------------------------------------------------
891
892 #ifdef USE_DEBUGGER
893 DEVICE *VM::get_cpu(int index)
894 {
895 #if defined(_PC98DO) || defined(_PC98DOPLUS)
896         if(index == 0 && boot_mode == 0) {
897                 return cpu;
898         } else if(index == 1 && boot_mode != 0) {
899                 return pc88cpu;
900         } else if(index == 2 && boot_mode != 0) {
901                 return pc88cpu_sub;
902         }
903 #else
904         if(index == 0) {
905                 return cpu;
906 #if defined(SUPPORT_320KB_FDD_IF)
907         } else if(index == 1) {
908                 return cpu_sub;
909 #endif
910         }
911 #endif
912         return NULL;
913 }
914 #endif
915
916 // ----------------------------------------------------------------------------
917 // draw screen
918 // ----------------------------------------------------------------------------
919
920 void VM::draw_screen()
921 {
922 #if defined(_PC98DO) || defined(_PC98DOPLUS)
923         if(boot_mode != 0) {
924                 pc88->draw_screen();
925         } else
926 #endif
927         display->draw_screen();
928 }
929
930 // ----------------------------------------------------------------------------
931 // soud manager
932 // ----------------------------------------------------------------------------
933
934 void VM::initialize_sound(int rate, int samples)
935 {
936         // init sound manager
937         event->initialize_sound(rate, samples);
938         
939         // init sound gen
940 #if defined(SUPPORT_OLD_BUZZER)
941         beep->initialize_sound(rate, 2400, 8000);
942 #else
943         beep->initialize_sound(rate, 8000);
944 #endif
945         if(sound_type == 0 || sound_type == 1) {
946 #ifdef HAS_YM2608
947                 opn->initialize_sound(rate, 7987248, samples, 0, 0);
948 #else
949                 opn->initialize_sound(rate, 3993624, samples, 0, 0);
950 #endif
951         } else if(sound_type == 2 || sound_type == 3) {
952                 tms3631->initialize_sound(rate, 8000);
953         }
954         
955 #if defined(_PC98DO) || defined(_PC98DOPLUS)
956         // init sound manager
957         pc88event->initialize_sound(rate, samples);
958         
959         // init sound gen
960 #ifdef HAS_YM2608
961         pc88opn->initialize_sound(rate, 7987248, samples, 0, 0);
962 #else
963         pc88opn->initialize_sound(rate, 3993624, samples, 0, 0);
964 #endif
965         pc88pcm->initialize_sound(rate, 8000);
966 #endif
967 }
968
969 uint16_t* VM::create_sound(int* extra_frames)
970 {
971 #if defined(_PC98DO) || defined(_PC98DOPLUS)
972         if(boot_mode != 0) {
973                 return pc88event->create_sound(extra_frames);
974         } else
975 #endif
976         return event->create_sound(extra_frames);
977 }
978
979 int VM::get_sound_buffer_ptr()
980 {
981 #if defined(_PC98DO) || defined(_PC98DOPLUS)
982         if(boot_mode != 0) {
983                 return pc88event->get_sound_buffer_ptr();
984         } else
985 #endif
986         return event->get_sound_buffer_ptr();
987 }
988
989 #ifdef USE_SOUND_VOLUME
990 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
991 {
992         if(ch-- == 0) {
993                 if(sound_type == 0 || sound_type == 1) {
994                         opn->set_volume(0, decibel_l, decibel_r);
995                 }
996         } else if(ch-- == 0) {
997                 if(sound_type == 0 || sound_type == 1) {
998                         opn->set_volume(1, decibel_l, decibel_r);
999                 }
1000 #if defined(SUPPORT_PC98_OPNA)
1001         } else if(ch-- == 0) {
1002                 if(sound_type == 0 || sound_type == 1) {
1003                         opn->set_volume(2, decibel_l, decibel_r);
1004                 }
1005         } else if(ch-- == 0) {
1006                 if(sound_type == 0 || sound_type == 1) {
1007                         opn->set_volume(3, decibel_l, decibel_r);
1008                 }
1009 #endif
1010         } else if(ch-- == 0) {
1011                 if(sound_type == 2 || sound_type == 3) {
1012                         tms3631->set_volume(0, decibel_l, decibel_r);
1013                 }
1014         } else if(ch-- == 0) {
1015                 beep->set_volume(0, decibel_l, decibel_r);
1016 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1017         } else if(ch-- == 0) {
1018                 pc88opn->set_volume(0, decibel_l, decibel_r);
1019         } else if(ch-- == 0) {
1020                 pc88opn->set_volume(1, decibel_l, decibel_r);
1021 #if defined(SUPPORT_PC88_OPNA)
1022         } else if(ch-- == 0) {
1023                 pc88opn->set_volume(2, decibel_l, decibel_r);
1024         } else if(ch-- == 0) {
1025                 pc88opn->set_volume(3, decibel_l, decibel_r);
1026 #endif
1027         } else if(ch-- == 0) {
1028                 pc88pcm->set_volume(0, decibel_l, decibel_r);
1029 #endif
1030         } else if(ch-- == 0) {
1031                 noise_seek->set_volume(0, decibel_l, decibel_r);
1032                 noise_head_down->set_volume(0, decibel_l, decibel_r);
1033                 noise_head_up->set_volume(0, decibel_l, decibel_r);
1034 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1035                 pc88noise_seek->set_volume(0, decibel_l, decibel_r);
1036                 pc88noise_head_down->set_volume(0, decibel_l, decibel_r);
1037                 pc88noise_head_up->set_volume(0, decibel_l, decibel_r);
1038 #endif
1039         }
1040 }
1041 #endif
1042
1043 // ----------------------------------------------------------------------------
1044 // notify key
1045 // ----------------------------------------------------------------------------
1046
1047 void VM::key_down(int code, bool repeat)
1048 {
1049 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1050         if(boot_mode != 0) {
1051                 pc88->key_down(code, repeat);
1052         } else
1053 #endif
1054         keyboard->key_down(code, repeat);
1055 }
1056
1057 void VM::key_up(int code)
1058 {
1059 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1060         if(boot_mode != 0) {
1061 //              pc88->key_up(code);
1062         } else
1063 #endif
1064         keyboard->key_up(code);
1065 }
1066
1067 // ----------------------------------------------------------------------------
1068 // user interface
1069 // ----------------------------------------------------------------------------
1070
1071 void VM::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
1072 {
1073 #if defined(_PC9801) || defined(_PC9801E)
1074         if(drv == 0 || drv == 1) {
1075                 fdc_2hd->open_disk(drv, file_path, bank);
1076         } else if(drv == 2 || drv == 3) {
1077                 fdc_2dd->open_disk(drv - 2, file_path, bank);
1078         } else if(drv == 4 || drv == 5) {
1079                 fdc_sub->open_disk(drv - 4, file_path, bank);
1080         }
1081 #elif defined(_PC9801VF) || defined(_PC9801U)
1082         if(drv == 0 || drv == 1) {
1083                 fdc_2dd->open_disk(drv, file_path, bank);
1084         }
1085 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1086         if(drv == 0 || drv == 1) {
1087                 fdc->open_disk(drv, file_path, bank);
1088         } else if(drv == 2 || drv == 3) {
1089                 pc88fdc_sub->open_disk(drv - 2, file_path, bank);
1090         }
1091 #else
1092         if(drv == 0 || drv == 1) {
1093                 fdc->open_disk(drv, file_path, bank);
1094         }
1095 #endif
1096 }
1097
1098 void VM::close_floppy_disk(int drv)
1099 {
1100 #if defined(_PC9801) || defined(_PC9801E)
1101         if(drv == 0 || drv == 1) {
1102                 fdc_2hd->close_disk(drv);
1103         } else if(drv == 2 || drv == 3) {
1104                 fdc_2dd->close_disk(drv - 2);
1105         } else if(drv == 4 || drv == 5) {
1106                 fdc_sub->close_disk(drv - 4);
1107         }
1108 #elif defined(_PC9801VF) || defined(_PC9801U)
1109         if(drv == 0 || drv == 1) {
1110                 fdc_2dd->close_disk(drv);
1111         }
1112 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1113         if(drv == 0 || drv == 1) {
1114                 fdc->close_disk(drv);
1115         } else if(drv == 2 || drv == 3) {
1116                 pc88fdc_sub->close_disk(drv - 2);
1117         }
1118 #else
1119         if(drv == 0 || drv == 1) {
1120                 fdc->close_disk(drv);
1121         }
1122 #endif
1123 }
1124
1125 bool VM::is_floppy_disk_inserted(int drv)
1126 {
1127 #if defined(_PC9801) || defined(_PC9801E)
1128         if(drv == 0 || drv == 1) {
1129                 return fdc_2hd->is_disk_inserted(drv);
1130         } else if(drv == 2 || drv == 3) {
1131                 return fdc_2dd->is_disk_inserted(drv - 2);
1132         } else if(drv == 4 || drv == 5) {
1133                 return fdc_sub->is_disk_inserted(drv - 4);
1134         }
1135 #elif defined(_PC9801VF) || defined(_PC9801U)
1136         if(drv == 0 || drv == 1) {
1137                 return fdc_2dd->is_disk_inserted(drv);
1138         }
1139 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1140         if(drv == 0 || drv == 1) {
1141                 return fdc->is_disk_inserted(drv);
1142         } else if(drv == 2 || drv == 3) {
1143                 return pc88fdc_sub->is_disk_inserted(drv - 2);
1144         }
1145 #else
1146         if(drv == 0 || drv == 1) {
1147                 return fdc->is_disk_inserted(drv);
1148         }
1149 #endif
1150         return false;
1151 }
1152
1153 void VM::is_floppy_disk_protected(int drv, bool value)
1154 {
1155 #if defined(_PC9801) || defined(_PC9801E)
1156         if(drv == 0 || drv == 1) {
1157                 fdc_2hd->is_disk_protected(drv, value);
1158         } else if(drv == 2 || drv == 3) {
1159                 fdc_2dd->is_disk_protected(drv - 2, value);
1160         } else if(drv == 4 || drv == 5) {
1161                 fdc_sub->is_disk_protected(drv - 4, value);
1162         }
1163 #elif defined(_PC9801VF) || defined(_PC9801U)
1164         if(drv == 0 || drv == 1) {
1165                 fdc_2dd->is_disk_protected(drv, value);
1166         }
1167 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1168         if(drv == 0 || drv == 1) {
1169                 fdc->is_disk_protected(drv, value);
1170         } else if(drv == 2 || drv == 3) {
1171                 pc88fdc_sub->is_disk_protected(drv - 2, value);
1172         }
1173 #else
1174         if(drv == 0 || drv == 1) {
1175                 fdc->is_disk_protected(drv, value);
1176         }
1177 #endif
1178 }
1179
1180 bool VM::is_floppy_disk_protected(int drv)
1181 {
1182 #if defined(_PC9801) || defined(_PC9801E)
1183         if(drv == 0 || drv == 1) {
1184                 return fdc_2hd->is_disk_protected(drv);
1185         } else if(drv == 2 || drv == 3) {
1186                 return fdc_2dd->is_disk_protected(drv - 2);
1187         } else if(drv == 4 || drv == 5) {
1188                 return fdc_sub->is_disk_protected(drv - 4);
1189         }
1190 #elif defined(_PC9801VF) || defined(_PC9801U)
1191         if(drv == 0 || drv == 1) {
1192                 return fdc_2dd->is_disk_protected(drv);
1193         }
1194 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1195         if(drv == 0 || drv == 1) {
1196                 return fdc->is_disk_protected(drv);
1197         } else if(drv == 2 || drv == 3) {
1198                 return pc88fdc_sub->is_disk_protected(drv - 2);
1199         }
1200 #else
1201         if(drv == 0 || drv == 1) {
1202                 return fdc->is_disk_protected(drv);
1203         }
1204 #endif
1205         return false;
1206 }
1207
1208 uint32_t VM::is_floppy_disk_accessed()
1209 {
1210 #if defined(_PC9801) || defined(_PC9801E)
1211         return (fdc_2hd->read_signal(0) & 3) | ((fdc_2dd->read_signal(0) & 3) << 2) | ((fdc_sub->read_signal(0) & 3) << 4);
1212 #elif defined(_PC9801VF) || defined(_PC9801U)
1213         return fdc_2dd->read_signal(0);
1214 #elif defined(_PC98DO) || defined(_PC98DOPLUS)
1215         if(boot_mode != 0) {
1216                 return pc88fdc_sub->read_signal(0);
1217         } else {
1218                 return fdc->read_signal(0);
1219         }
1220 #else
1221         return fdc->read_signal(0);
1222 #endif
1223 }
1224
1225 #if defined(SUPPORT_CMT_IF) || defined(_PC98DO) || defined(_PC98DOPLUS)
1226 void VM::play_tape(int drv, const _TCHAR* file_path)
1227 {
1228 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1229         pc88->play_tape(file_path);
1230 #else
1231         cmt->play_tape(file_path);
1232 #endif
1233 }
1234
1235 void VM::rec_tape(int drv, const _TCHAR* file_path)
1236 {
1237 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1238         pc88->rec_tape(file_path);
1239 #else
1240         cmt->rec_tape(file_path);
1241 #endif
1242 }
1243
1244 void VM::close_tape(int drv)
1245 {
1246 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1247         pc88->close_tape();
1248 #else
1249         cmt->close_tape();
1250 #endif
1251 }
1252
1253 bool VM::is_tape_inserted(int drv)
1254 {
1255 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1256         return pc88->is_tape_inserted();
1257 #else
1258         return cmt->is_tape_inserted();
1259 #endif
1260 }
1261 #endif
1262
1263 bool VM::is_frame_skippable()
1264 {
1265 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1266         if(boot_mode != 0) {
1267 //              return pc88event->is_frame_skippable();
1268                 return pc88->is_frame_skippable();
1269         } else
1270 #endif
1271         return event->is_frame_skippable();
1272 }
1273
1274 void VM::update_config()
1275 {
1276 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1277         if(boot_mode != config.boot_mode) {
1278                 // boot mode is changed !!!
1279                 boot_mode = config.boot_mode;
1280                 reset();
1281         } else
1282 #endif
1283         for(DEVICE* device = first_device; device; device = device->next_device) {
1284                 device->update_config();
1285         }
1286 }
1287
1288 #define STATE_VERSION   8
1289
1290 void VM::save_state(FILEIO* state_fio)
1291 {
1292         state_fio->FputUint32(STATE_VERSION);
1293         
1294         for(DEVICE* device = first_device; device; device = device->next_device) {
1295                 device->save_state(state_fio);
1296         }
1297         state_fio->Fwrite(ram, sizeof(ram), 1);
1298         state_fio->FputBool(pit_clock_8mhz);
1299 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1300         state_fio->FputInt32(boot_mode);
1301 #endif
1302         state_fio->FputInt32(sound_type);
1303 }
1304
1305 bool VM::load_state(FILEIO* state_fio)
1306 {
1307         if(state_fio->FgetUint32() != STATE_VERSION) {
1308                 return false;
1309         }
1310         for(DEVICE* device = first_device; device; device = device->next_device) {
1311                 if(!device->load_state(state_fio)) {
1312                         return false;
1313                 }
1314         }
1315         state_fio->Fread(ram, sizeof(ram), 1);
1316         pit_clock_8mhz = state_fio->FgetBool();
1317 #if defined(_PC98DO) || defined(_PC98DOPLUS)
1318         boot_mode = state_fio->FgetInt32();
1319 #endif
1320         sound_type = state_fio->FgetInt32();
1321         return true;
1322 }
1323