OSDN Git Service

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