OSDN Git Service

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