OSDN Git Service

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