OSDN Git Service

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