OSDN Git Service

[VM][FAMILYBASIC][WIP] Fix wrong string for romaji-kana (and auto key).Still imcoplet...
[csp-qt/common_source_project-fm7.git] / source / src / emu.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.08.18 -
6
7         [ win32 emulation i/f ]
8 */
9
10 #if defined(_USE_QT)
11 #include <string>
12 #endif
13 #include "emu.h"
14 #include "vm/vm.h"
15 #include "fifo.h"
16 #include "fileio.h"
17
18 // ----------------------------------------------------------------------------
19 // initialize
20 // ----------------------------------------------------------------------------
21 static const int sound_frequency_table[8] = {
22         2000, 4000, 8000, 11025, 22050, 44100,
23 #ifdef OVERRIDE_SOUND_FREQ_48000HZ
24         OVERRIDE_SOUND_FREQ_48000HZ,
25 #else
26         48000,
27 #endif
28         96000,
29 };
30 static const double sound_latency_table[5] = {0.05, 0.1, 0.2, 0.3, 0.4};
31
32 #if defined(_USE_QT)
33 // Please permit at least them m(.. )m
34 //extern void get_long_full_path_name(_TCHAR* src, _TCHAR* dst);
35 #include <string>
36 extern CSP_Logger *csp_logger;
37 #endif
38
39 #if defined(_USE_QT)
40 EMU::EMU(class Ui_MainWindow *hwnd, GLDrawClass *hinst, USING_FLAGS *p)
41 #elif defined(OSD_WIN32)
42 EMU::EMU(HWND hwnd, HINSTANCE hinst)
43 #else
44 EMU::EMU()
45 #endif
46 {
47         message_count = 0;
48         // store main window handle
49 #ifdef USE_FLOPPY_DISK
50         // initialize d88 file info
51         memset(d88_file, 0, sizeof(d88_file));
52 #endif
53 #ifdef USE_BUBBLE
54         // initialize d88 file info
55         memset(b77_file, 0, sizeof(b77_file));
56 #endif
57         // load sound config
58         
59         if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
60                 config.sound_frequency = 6;     // default: 48KHz
61         }
62         if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
63                 config.sound_latency = 1;       // default: 100msec
64         }
65         sound_frequency = config.sound_frequency;
66         sound_latency = config.sound_latency;
67         sound_rate = sound_frequency_table[config.sound_frequency];
68         sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
69
70 #ifdef USE_CPU_TYPE
71         cpu_type = config.cpu_type;
72 #endif
73 #ifdef USE_DIPSWITCH
74         dipswitch = config.dipswitch;
75 #endif
76 #ifdef USE_SOUND_TYPE
77         sound_type = config.sound_type;
78 #endif
79 #ifdef USE_PRINTER_TYPE
80         printer_type = config.printer_type;
81 #endif
82 #ifdef USE_BUBBLE
83         // initialize b77 file info
84         memset(b77_file, 0, sizeof(b77_file));
85 #endif
86         
87         // initialize osd
88 #if defined(OSD_QT)
89         osd = new OSD(p, csp_logger);
90         osd->main_window_handle = hwnd;
91         //osd->p_glv = hinst;
92         osd->host_cpus = 4;
93 #elif defined(OSD_WIN32)
94         osd = new OSD();
95         osd->main_window_handle = hwnd;
96         osd->instance_handle = hinst;
97 #endif
98         int presented_rate, presented_samples;
99         osd->initialize(sound_rate, sound_samples, &presented_rate, &presented_samples);
100         sound_rate = presented_rate;
101         sound_samples = presented_samples;
102         // initialize vm
103         vm = new VM(this);
104         osd->vm = vm;
105 # if defined(_USE_QT)
106         osd->reset_vm_node();
107         osd->update_keyname_table();
108 # endif 
109 #ifdef USE_AUTO_KEY
110         initialize_auto_key();
111 #endif
112 #ifdef USE_DEBUGGER
113         initialize_debugger();
114 #endif
115         now_waiting_in_debugger = false;
116         initialize_media();
117         vm->initialize_sound(sound_rate, sound_samples);
118 #ifdef USE_SOUND_VOLUME
119         for(int i = 0; i < USE_SOUND_VOLUME; i++) {
120                 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
121         }
122 #endif
123 #ifdef USE_HARD_DISK
124         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
125                 if(config.last_hard_disk_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(config.last_hard_disk_path[drv])) {
126                         vm->open_hard_disk(drv, config.last_hard_disk_path[drv]);
127                         my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, config.last_hard_disk_path[drv]);
128                 }
129         }
130 #endif
131         vm->reset();
132         now_suspended = false;
133 }
134
135 EMU::~EMU()
136 {
137 #ifdef USE_AUTO_KEY
138         release_auto_key();
139 #endif
140 #ifdef USE_DEBUGGER
141         release_debugger();
142 #endif
143         delete vm;
144         osd->release();
145         delete osd;
146 #ifdef _DEBUG_LOG
147         release_debug_log();
148 #endif
149 }
150
151
152
153 #ifdef OSD_QT
154 EmuThreadClass *EMU::get_parent_handler()
155 {
156         return osd->get_parent_handler();
157 }
158
159 void EMU::set_parent_handler(EmuThreadClass *p, DrawThreadClass *q)
160 {
161         osd->set_parent_thread(p);
162         osd->set_draw_thread(q);
163 }
164
165 void EMU::set_host_cpus(int v)
166 {
167         osd->host_cpus = (v <= 0) ? 1 : v;
168 }
169
170 int EMU::get_host_cpus()
171 {
172         return osd->host_cpus;
173 }
174 #endif
175
176 // ----------------------------------------------------------------------------
177 // drive machine
178 // ----------------------------------------------------------------------------
179
180 double EMU::get_frame_rate()
181 {
182         return vm->get_frame_rate();
183 }
184
185 int EMU::get_frame_interval()
186 {
187         static int prev_interval = 0;
188         static double prev_fps = -1;
189         double fps = vm->get_frame_rate();
190         if(prev_fps != fps) {
191                 prev_interval = (int)(1024. * 1000. / fps + 0.5);
192                 prev_fps = fps;
193         }
194         return prev_interval;
195 }
196
197 bool EMU::is_frame_skippable()
198 {
199         return vm->is_frame_skippable();
200 }
201
202 int EMU::run()
203 {
204         if(now_suspended) {
205                 osd->restore();
206                 now_suspended = false;
207         }
208         osd->update_input();
209 #ifdef USE_AUTO_KEY
210         update_auto_key();
211 #endif
212 #ifdef USE_JOYSTICK
213         update_joystick();
214 #endif
215         
216 #ifdef USE_SOCKET
217 #if !defined(_USE_QT) // Temporally
218         osd->update_socket();
219 #endif
220 #endif
221         update_media();
222         
223         // virtual machine may be driven to fill sound buffer
224         int extra_frames = 0;
225         osd->update_sound(&extra_frames);
226         
227         // drive virtual machine
228         if(extra_frames == 0) {
229                 osd->lock_vm();
230                 vm->run();
231                 extra_frames = 1;
232                 osd->unlock_vm();
233         }
234         osd->add_extra_frames(extra_frames);
235         return extra_frames;
236 }
237
238 void EMU::reset()
239 {
240 #ifdef USE_AUTO_KEY
241         stop_auto_key();
242         config.romaji_to_kana = false;
243 #endif
244         
245         // check if virtual machine should be reinitialized
246         bool reinitialize = false;
247 #ifdef USE_CPU_TYPE
248         reinitialize |= (cpu_type != config.cpu_type);
249         cpu_type = config.cpu_type;
250 #endif
251 #ifdef USE_DIPSWITCH
252         reinitialize |= (dipswitch != config.dipswitch);
253         dipswitch = config.dipswitch;
254 #endif
255 #ifdef USE_SOUND_TYPE
256         reinitialize |= (sound_type != config.sound_type);
257         sound_type = config.sound_type;
258 #endif
259 #ifdef USE_PRINTER_TYPE
260         reinitialize |= (printer_type != config.printer_type);
261         printer_type = config.printer_type;
262 #endif
263         if(reinitialize) {
264                 // stop sound
265                 osd->stop_sound();
266                 // reinitialize virtual machine
267                 osd->lock_vm();         
268                 delete vm;
269                 vm = new VM(this);
270                 osd->vm = vm;;
271 #if defined(_USE_QT)
272                 osd->reset_vm_node();
273                 osd->update_keyname_table();
274 #endif
275                 int presented_rate;
276                 int presented_samples;
277                 sound_rate = sound_frequency_table[config.sound_frequency];
278                 sound_samples = (int)(sound_rate * sound_latency_table[config.sound_latency] + 0.5);
279                 osd->initialize_sound(sound_rate, sound_samples, &presented_rate, &presented_samples);
280                 if((sound_rate != presented_rate) ||
281                    (sound_samples != presented_samples)) {
282                         sound_rate = presented_rate;
283                         sound_samples = presented_samples;
284                 }
285                 vm->initialize_sound(sound_rate, sound_samples);
286 #ifdef USE_SOUND_VOLUME
287                 for(int i = 0; i < USE_SOUND_VOLUME; i++) {
288                         vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
289                 }
290 #endif
291                 // restore inserted medias
292                 restore_media();
293                 vm->reset();
294                 osd->unlock_vm();
295         } else {
296                 // reset virtual machine
297                 osd->lock_vm();         
298                 vm->reset();
299                 osd->unlock_vm();               
300         }
301         
302 #if !defined(_USE_QT) // Temporally
303         // restart recording
304         osd->restart_record_sound();
305         osd->restart_record_video();
306 #endif  
307 }
308
309 #ifdef USE_SPECIAL_RESET
310 void EMU::special_reset()
311 {
312 #ifdef USE_AUTO_KEY
313         stop_auto_key();
314         config.romaji_to_kana = false;
315 #endif
316         
317         // reset virtual machine
318         osd->lock_vm();         
319         vm->special_reset();
320         osd->unlock_vm();
321         // restart recording
322 #if !defined(_USE_QT) // Temporally
323         restart_record_sound();
324         restart_record_video();
325 #endif  
326 }
327 #endif
328
329 #ifdef USE_NOTIFY_POWER_OFF
330 void EMU::notify_power_off()
331 {
332         vm->notify_power_off();
333 }
334 #endif
335
336 void EMU::power_off()
337 {
338         osd->power_off();
339 }
340
341 void EMU::suspend()
342 {
343         if(!now_suspended) {
344                 osd->suspend();
345                 now_suspended = true;
346         }
347 }
348
349 void EMU::lock_vm()
350 {
351         osd->lock_vm();
352 }
353
354 void EMU::unlock_vm()
355 {
356         osd->unlock_vm();
357 }
358
359 void EMU::force_unlock_vm()
360 {
361         osd->force_unlock_vm();
362 }
363
364 bool EMU::is_vm_locked()
365 {
366         return osd->is_vm_locked();
367 }
368
369 // ----------------------------------------------------------------------------
370 // input
371 // ----------------------------------------------------------------------------
372
373
374 void EMU::key_down(int code, bool extended, bool repeat)
375 {
376 #ifdef USE_AUTO_KEY
377         if(code == 0x10) {
378                 shift_pressed = true;
379         }
380         if(config.romaji_to_kana) {
381                 if(!repeat) {
382                         // Page Up, Page Down, End, Home, Left, Up, Right, Down, Ins, Del, Help, and F1-F12
383                         if((code >= 0x21 && code <= 0x2f) || (code >= 0x70 && code <= 0x7b)) {
384                                 if(shift_pressed) {
385                                         auto_key_buffer->write(code | 0x100);
386                                 } else {
387                                         auto_key_buffer->write(code);
388                                 }
389                                 if(!is_auto_key_running()) {
390                                         start_auto_key();
391                                 }
392                         }
393                 }
394         } else if(!is_auto_key_running())
395 #endif
396         osd->key_down(code, extended, repeat);
397 }
398
399 void EMU::key_up(int code, bool extended)
400 {
401 #ifdef USE_AUTO_KEY
402         if(code == 0x10) {
403                 shift_pressed = false;
404         }
405         if(config.romaji_to_kana) {
406                 // do nothing
407         } else if(!is_auto_key_running())
408 #endif
409         osd->key_up(code, extended);
410 }
411
412 void EMU::key_char(char code)
413 {
414 #ifdef USE_AUTO_KEY
415         if(config.romaji_to_kana) {
416                 set_auto_key_char(code);
417         }
418 #endif
419 }
420
421 #ifdef USE_KEY_LOCKED
422 bool EMU::get_caps_locked()
423 {
424         return vm->get_caps_locked();
425 }
426
427 bool EMU::get_kana_locked()
428 {
429         return vm->get_kana_locked();
430 }
431 #endif
432
433 void EMU::key_lost_focus()
434 {
435         osd->key_lost_focus();
436 }
437
438 #ifdef ONE_BOARD_MICRO_COMPUTER
439 void EMU::press_button(int num)
440 {
441         int code = vm_buttons[num].code;
442         
443         if(code) {
444                 osd->key_down_native(code, false);
445                 osd->get_key_buffer()[code] = KEY_KEEP_FRAMES;
446         } else {
447                 // code=0: reset virtual machine
448                 vm->reset();
449         }
450 }
451 #endif
452
453 #ifdef USE_MOUSE
454 void EMU::enable_mouse()
455 {
456         osd->enable_mouse();
457 }
458
459 void EMU::disable_mouse()
460 {
461         osd->disable_mouse();
462 }
463
464 void EMU::toggle_mouse()
465 {
466         osd->toggle_mouse();
467 }
468
469 bool EMU::is_mouse_enabled()
470 {
471         return osd->is_mouse_enabled();
472 }
473 #endif
474
475 #ifdef USE_AUTO_KEY
476 static const int auto_key_table_base[][2] = {
477         // 0x100: shift
478         // 0x200: kana
479         // 0x400: alphabet
480         // 0x800: ALPHABET
481         // 0x1000 : LOCK
482         // 0x2000 : UNLOCK
483         {0x08,  0x000 | 0x08},  // BS
484         {0x09,  0x000 | 0x09},  // Tab
485         {0x0d,  0x000 | 0x0d},  // Enter
486         {0x1b,  0x000 | 0x1b},  // Escape
487         {0x20,  0x000 | 0x20},  // ' '
488 #ifdef AUTO_KEY_US
489         {0x21,  0x100 | 0x31},  // '!'
490         {0x22,  0x100 | 0xba},  // '"'
491         {0x23,  0x100 | 0x33},  // '#'
492         {0x24,  0x100 | 0x34},  // '$'
493         {0x25,  0x100 | 0x35},  // '%'
494         {0x26,  0x100 | 0x37},  // '&'
495         {0x27,  0x000 | 0xba},  // '''
496         {0x28,  0x100 | 0x39},  // '('
497         {0x29,  0x100 | 0x30},  // ')'
498         {0x2a,  0x100 | 0x38},  // '*'
499         {0x2b,  0x100 | 0xde},  // '+'
500         {0x2c,  0x000 | 0xbc},  // ','
501         {0x2d,  0x000 | 0xbd},  // '-'
502         {0x2e,  0x000 | 0xbe},  // '.'
503         {0x2f,  0x000 | 0xbf},  // '/'
504 #else
505         {0x21,  0x100 | 0x31},  // '!'
506         {0x22,  0x100 | 0x32},  // '"'
507         {0x23,  0x100 | 0x33},  // '#'
508         {0x24,  0x100 | 0x34},  // '$'
509         {0x25,  0x100 | 0x35},  // '%'
510         {0x26,  0x100 | 0x36},  // '&'
511         {0x27,  0x100 | 0x37},  // '''
512         {0x28,  0x100 | 0x38},  // '('
513         {0x29,  0x100 | 0x39},  // ')'
514         {0x2a,  0x100 | 0xba},  // '*'
515         {0x2b,  0x100 | 0xbb},  // '+'
516         {0x2c,  0x000 | 0xbc},  // ','
517         {0x2d,  0x000 | 0xbd},  // '-'
518         {0x2e,  0x000 | 0xbe},  // '.'
519         {0x2f,  0x000 | 0xbf},  // '/'
520 #endif
521         {0x30,  0x000 | 0x30},  // '0'
522         {0x31,  0x000 | 0x31},  // '1'
523         {0x32,  0x000 | 0x32},  // '2'
524         {0x33,  0x000 | 0x33},  // '3'
525         {0x34,  0x000 | 0x34},  // '4'
526         {0x35,  0x000 | 0x35},  // '5'
527         {0x36,  0x000 | 0x36},  // '6'
528         {0x37,  0x000 | 0x37},  // '7'
529         {0x38,  0x000 | 0x38},  // '8'
530         {0x39,  0x000 | 0x39},  // '9'
531 #ifdef AUTO_KEY_US
532         {0x3a,  0x100 | 0xbb},  // ':'
533         {0x3b,  0x000 | 0xbb},  // ';'
534         {0x3c,  0x100 | 0xbc},  // '<'
535         {0x3d,  0x000 | 0xde},  // '='
536         {0x3e,  0x100 | 0xbe},  // '>'
537         {0x3f,  0x100 | 0xbf},  // '?'
538         {0x40,  0x100 | 0x32},  // '@'
539 #else
540         {0x3a,  0x000 | 0xba},  // ':'
541         {0x3b,  0x000 | 0xbb},  // ';'
542         {0x3c,  0x100 | 0xbc},  // '<'
543         {0x3d,  0x100 | 0xbd},  // '='
544         {0x3e,  0x100 | 0xbe},  // '>'
545         {0x3f,  0x100 | 0xbf},  // '?'
546         {0x40,  0x000 | 0xc0},  // '@'
547 #endif
548         {0x41,  0x400 | 0x41},  // 'A'
549         {0x42,  0x400 | 0x42},  // 'B'
550         {0x43,  0x400 | 0x43},  // 'C'
551         {0x44,  0x400 | 0x44},  // 'D'
552         {0x45,  0x400 | 0x45},  // 'E'
553         {0x46,  0x400 | 0x46},  // 'F'
554         {0x47,  0x400 | 0x47},  // 'G'
555         {0x48,  0x400 | 0x48},  // 'H'
556         {0x49,  0x400 | 0x49},  // 'I'
557         {0x4a,  0x400 | 0x4a},  // 'J'
558         {0x4b,  0x400 | 0x4b},  // 'K'
559         {0x4c,  0x400 | 0x4c},  // 'L'
560         {0x4d,  0x400 | 0x4d},  // 'M'
561         {0x4e,  0x400 | 0x4e},  // 'N'
562         {0x4f,  0x400 | 0x4f},  // 'O'
563         {0x50,  0x400 | 0x50},  // 'P'
564         {0x51,  0x400 | 0x51},  // 'Q'
565         {0x52,  0x400 | 0x52},  // 'R'
566         {0x53,  0x400 | 0x53},  // 'S'
567         {0x54,  0x400 | 0x54},  // 'T'
568         {0x55,  0x400 | 0x55},  // 'U'
569         {0x56,  0x400 | 0x56},  // 'V'
570         {0x57,  0x400 | 0x57},  // 'W'
571         {0x58,  0x400 | 0x58},  // 'X'
572         {0x59,  0x400 | 0x59},  // 'Y'
573         {0x5a,  0x400 | 0x5a},  // 'Z'
574 #ifdef AUTO_KEY_US
575         {0x5b,  0x000 | 0xc0},  // '['
576         {0x5c,  0x000 | 0xe2},  // '\'
577         {0x5d,  0x000 | 0xdb},  // ']'
578         {0x5e,  0x100 | 0x36},  // '^'
579         {0x5f,  0x100 | 0xbd},  // '_'
580         {0x60,  0x000 | 0xdd},  // '`'
581 #else
582         {0x5b,  0x000 | 0xdb},  // '['
583         {0x5c,  0x000 | 0xdc},  // '\'
584         {0x5d,  0x000 | 0xdd},  // ']'
585         {0x5e,  0x000 | 0xde},  // '^'
586         {0x5f,  0x100 | 0xe2},  // '_'
587         {0x60,  0x100 | 0xc0},  // '`'
588 #endif
589         {0x61,  0x800 | 0x41},  // 'a'
590         {0x62,  0x800 | 0x42},  // 'b'
591         {0x63,  0x800 | 0x43},  // 'c'
592         {0x64,  0x800 | 0x44},  // 'd'
593         {0x65,  0x800 | 0x45},  // 'e'
594         {0x66,  0x800 | 0x46},  // 'f'
595         {0x67,  0x800 | 0x47},  // 'g'
596         {0x68,  0x800 | 0x48},  // 'h'
597         {0x69,  0x800 | 0x49},  // 'i'
598         {0x6a,  0x800 | 0x4a},  // 'j'
599         {0x6b,  0x800 | 0x4b},  // 'k'
600         {0x6c,  0x800 | 0x4c},  // 'l'
601         {0x6d,  0x800 | 0x4d},  // 'm'
602         {0x6e,  0x800 | 0x4e},  // 'n'
603         {0x6f,  0x800 | 0x4f},  // 'o'
604         {0x70,  0x800 | 0x50},  // 'p'
605         {0x71,  0x800 | 0x51},  // 'q'
606         {0x72,  0x800 | 0x52},  // 'r'
607         {0x73,  0x800 | 0x53},  // 's'
608         {0x74,  0x800 | 0x54},  // 't'
609         {0x75,  0x800 | 0x55},  // 'u'
610         {0x76,  0x800 | 0x56},  // 'v'
611         {0x77,  0x800 | 0x57},  // 'w'
612         {0x78,  0x800 | 0x58},  // 'x'
613         {0x79,  0x800 | 0x59},  // 'y'
614         {0x7a,  0x800 | 0x5a},  // 'z'
615 #ifdef AUTO_KEY_US
616         {0x7b,  0x100 | 0xc0},  // '{'
617         {0x7c,  0x100 | 0xe2},  // '|'
618         {0x7d,  0x100 | 0xdb},  // '}'
619         {0x7e,  0x100 | 0xdd},  // '~'
620 #else
621         {0x7b,  0x100 | 0xdb},  // '{'
622         {0x7c,  0x100 | 0xdc},  // '|'
623         {0x7d,  0x100 | 0xdd},  // '}'
624         {0x7e,  0x100 | 0xde},  // '~'
625 #endif
626         {-1, -1},
627 };
628
629 static const int auto_key_table_kana_base[][2] = {
630         {0xa1,  0x300 | 0xbe},  // '¡'
631         {0xa2,  0x300 | 0xdb},  // '¢'
632         {0xa3,  0x300 | 0xdd},  // '£'
633         {0xa4,  0x300 | 0xbc},  // '¤'
634         {0xa5,  0x300 | 0xbf},  // '¥'
635         {0xa6,  0x300 | 0x30},  // '¦'
636         {0xa7,  0x300 | 0x33},  // '§'
637         {0xa8,  0x300 | 0x45},  // '¨'
638         {0xa9,  0x300 | 0x34},  // '©'
639         {0xaa,  0x300 | 0x35},  // 'ª'
640         {0xab,  0x300 | 0x36},  // '«'
641         {0xac,  0x300 | 0x37},  // '¬'
642         {0xad,  0x300 | 0x38},  // '­'
643         {0xae,  0x300 | 0x39},  // '®'
644         {0xaf,  0x300 | 0x5a},  // '¯'
645         {0xb0,  0x200 | 0xdc},  // '°'
646         {0xb1,  0x200 | 0x33},  // '±'
647         {0xb2,  0x200 | 0x45},  // '²'
648         {0xb3,  0x200 | 0x34},  // '³'
649         {0xb4,  0x200 | 0x35},  // '´'
650         {0xb5,  0x200 | 0x36},  // 'µ'
651         {0xb6,  0x200 | 0x54},  // '¶'
652         {0xb7,  0x200 | 0x47},  // '·'
653         {0xb8,  0x200 | 0x48},  // '¸'
654         {0xb9,  0x200 | 0xba},  // '¹'
655         {0xba,  0x200 | 0x42},  // 'º'
656         {0xbb,  0x200 | 0x58},  // '»'
657         {0xbc,  0x200 | 0x44},  // '¼'
658         {0xbd,  0x200 | 0x52},  // '½'
659         {0xbe,  0x200 | 0x50},  // '¾'
660         {0xbf,  0x200 | 0x43},  // '¿'
661         {0xc0,  0x200 | 0x51},  // 'À'
662         {0xc1,  0x200 | 0x41},  // 'Á'
663         {0xc2,  0x200 | 0x5a},  // 'Â'
664         {0xc3,  0x200 | 0x57},  // 'Ã'
665         {0xc4,  0x200 | 0x53},  // 'Ä'
666         {0xc5,  0x200 | 0x55},  // 'Å'
667         {0xc6,  0x200 | 0x49},  // 'Æ'
668         {0xc7,  0x200 | 0x31},  // 'Ç'
669         {0xc8,  0x200 | 0xbc},  // 'È'
670         {0xc9,  0x200 | 0x4b},  // 'É'
671         {0xca,  0x200 | 0x46},  // 'Ê'
672         {0xcb,  0x200 | 0x56},  // 'Ë'
673         {0xcc,  0x200 | 0x32},  // 'Ì'
674         {0xcd,  0x200 | 0xde},  // 'Í'
675         {0xce,  0x200 | 0xbd},  // 'Î'
676         {0xcf,  0x200 | 0x4a},  // 'Ï'
677         {0xd0,  0x200 | 0x4e},  // 'Ð'
678         {0xd1,  0x200 | 0xdd},  // 'Ñ'
679         {0xd2,  0x200 | 0xbf},  // 'Ò'
680         {0xd3,  0x200 | 0x4d},  // 'Ó'
681         {0xd4,  0x200 | 0x37},  // 'Ô'
682         {0xd5,  0x200 | 0x38},  // 'Õ'
683         {0xd6,  0x200 | 0x39},  // 'Ö'
684         {0xd7,  0x200 | 0x4f},  // '×'
685         {0xd8,  0x200 | 0x4c},  // 'Ø'
686         {0xd9,  0x200 | 0xbe},  // 'Ù'
687         {0xda,  0x200 | 0xbb},  // 'Ú'
688         {0xdb,  0x200 | 0xe2},  // 'Û'
689         {0xdc,  0x200 | 0x30},  // 'Ü'
690         {0xdd,  0x200 | 0x59},  // 'Ý'
691         {0xde,  0x200 | 0xc0},  // 'Þ'
692         {0xdf,  0x200 | 0xdb},  // 'ß'
693         {-1, -1},
694 };
695
696 static const int auto_key_table_50on_base[][2] = {
697         {0xa1,  0x300 | 0xbf},  // '¡'
698         {0xa2,  0x300 | 0xdb},  // '¢'
699         {0xa3,  0x300 | 0xdd},  // '£'
700         {0xa4,  0x300 | 0xbe},  // '¤'
701         {0xa5,  0x300 | 0xe2},  // '¥'
702         {0xa6,  0x200 | 0xbf},  // '¦'
703         {0xa7,  0x300 | 0x31},  // '§'
704         {0xa8,  0x300 | 0x32},  // '¨'
705         {0xa9,  0x300 | 0x33},  // '©'
706         {0xaa,  0x300 | 0x34},  // 'ª'
707         {0xab,  0x300 | 0x35},  // '«'
708         {0xac,  0x300 | 0x4e},  // '¬'
709         {0xad,  0x300 | 0x4d},  // '­'
710         {0xae,  0x300 | 0xbc},  // '®'
711         {0xaf,  0x300 | 0x43},  // '¯'
712         {0xb0,  0x300 | 0xba},  // '°'
713         {0xb1,  0x200 | 0x31},  // '±'
714         {0xb2,  0x200 | 0x32},  // '²'
715         {0xb3,  0x200 | 0x33},  // '³'
716         {0xb4,  0x200 | 0x34},  // '´'
717         {0xb5,  0x200 | 0x35},  // 'µ'
718         {0xb6,  0x200 | 0x51},  // '¶'
719         {0xb7,  0x200 | 0x57},  // '·'
720         {0xb8,  0x200 | 0x45},  // '¸'
721         {0xb9,  0x200 | 0x52},  // '¹'
722         {0xba,  0x200 | 0x54},  // 'º'
723         {0xbb,  0x200 | 0x41},  // '»'
724         {0xbc,  0x200 | 0x53},  // '¼'
725         {0xbd,  0x200 | 0x44},  // '½'
726         {0xbe,  0x200 | 0x46},  // '¾'
727         {0xbf,  0x200 | 0x47},  // '¿'
728         {0xc0,  0x200 | 0x5a},  // 'À'
729         {0xc1,  0x200 | 0x58},  // 'Á'
730         {0xc2,  0x200 | 0x43},  // 'Â'
731         {0xc3,  0x200 | 0x56},  // 'Ã'
732         {0xc4,  0x200 | 0x42},  // 'Ä'
733         {0xc5,  0x200 | 0x36},  // 'Å'
734         {0xc6,  0x200 | 0x37},  // 'Æ'
735         {0xc7,  0x200 | 0x38},  // 'Ç'
736         {0xc8,  0x200 | 0x39},  // 'È'
737         {0xc9,  0x200 | 0x30},  // 'É'
738         {0xca,  0x200 | 0x59},  // 'Ê'
739         {0xcb,  0x200 | 0x55},  // 'Ë'
740         {0xcc,  0x200 | 0x49},  // 'Ì'
741         {0xcd,  0x200 | 0x4f},  // 'Í'
742         {0xce,  0x200 | 0x50},  // 'Î'
743         {0xcf,  0x200 | 0x48},  // 'Ï'
744         {0xd0,  0x200 | 0x4a},  // 'Ð'
745         {0xd1,  0x200 | 0x4b},  // 'Ñ'
746         {0xd2,  0x200 | 0x4c},  // 'Ò'
747         {0xd3,  0x200 | 0xbb},  // 'Ó'
748         {0xd4,  0x200 | 0x4e},  // 'Ô'
749         {0xd5,  0x200 | 0x4d},  // 'Õ'
750         {0xd6,  0x200 | 0xbc},  // 'Ö'
751         {0xd7,  0x200 | 0xbd},  // '×'
752         {0xd8,  0x200 | 0xde},  // 'Ø'
753         {0xd9,  0x200 | 0xdc},  // 'Ù'
754         {0xda,  0x200 | 0xc0},  // 'Ú'
755         {0xdb,  0x200 | 0xdb},  // 'Û'
756         {0xdc,  0x200 | 0xbe},  // 'Ü'
757         {0xdd,  0x200 | 0xe2},  // 'Ý'
758         {0xde,  0x200 | 0xba},  // 'Þ'
759         {0xdf,  0x200 | 0xdd},  // 'ß'
760         {-1, -1},
761 };
762
763 static const struct {
764         const char *romaji;
765         const uint8_t kana[4];
766 } romaji_table[] = {
767         {"ltsu",        {0xaf, 0x00}},
768         {"xtsu",        {0xaf, 0x00}},
769         {"ltu",         {0xaf, 0x00}},
770         {"xtu",         {0xaf, 0x00}},
771         {"bya",         {0xcb, 0xde, 0xac, 0x00}},
772         {"byi",         {0xcb, 0xde, 0xa8, 0x00}},
773         {"byu",         {0xcb, 0xde, 0xad, 0x00}},
774         {"bye",         {0xcb, 0xde, 0xaa, 0x00}},
775         {"byo",         {0xcb, 0xde, 0xae, 0x00}},
776         {"cha",         {0xc1, 0xac, 0x00}},
777         {"chi",         {0xc1, 0x00}},
778         {"chu",         {0xc1, 0xad, 0x00}},
779         {"che",         {0xc1, 0xaa, 0x00}},
780         {"cho",         {0xc1, 0xae, 0x00}},
781         {"cya",         {0xc1, 0xac, 0x00}},
782         {"cyi",         {0xc1, 0xa8, 0x00}},
783         {"cyu",         {0xc1, 0xad, 0x00}},
784         {"cye",         {0xc1, 0xaa, 0x00}},
785         {"cyo",         {0xc1, 0xae, 0x00}},
786         {"dha",         {0xc3, 0xde, 0xac, 0x00}},
787         {"dhi",         {0xc3, 0xde, 0xa8, 0x00}},
788         {"dhu",         {0xc3, 0xde, 0xad, 0x00}},
789         {"dhe",         {0xc3, 0xde, 0xaa, 0x00}},
790         {"dho",         {0xc3, 0xde, 0xae, 0x00}},
791         {"dwa",         {0xc4, 0xde, 0xa7, 0x00}},
792         {"dwi",         {0xc4, 0xde, 0xa8, 0x00}},
793         {"dwu",         {0xc4, 0xde, 0xa9, 0x00}},
794         {"dwe",         {0xc4, 0xde, 0xaa, 0x00}},
795         {"dwo",         {0xc4, 0xde, 0xab, 0x00}},
796         {"dya",         {0xc1, 0xde, 0xac, 0x00}},
797         {"dyi",         {0xc1, 0xde, 0xa8, 0x00}},
798         {"dyu",         {0xc1, 0xde, 0xad, 0x00}},
799         {"dye",         {0xc1, 0xde, 0xaa, 0x00}},
800         {"dyo",         {0xc1, 0xde, 0xae, 0x00}},
801         {"fwa",         {0xcc, 0xa7, 0x00}},
802         {"fwi",         {0xcc, 0xa8, 0x00}},
803         {"fwu",         {0xcc, 0xa9, 0x00}},
804         {"fwe",         {0xcc, 0xaa, 0x00}},
805         {"fwo",         {0xcc, 0xab, 0x00}},
806         {"fya",         {0xcc, 0xac, 0x00}},
807         {"fyi",         {0xcc, 0xa8, 0x00}},
808         {"fyu",         {0xcc, 0xad, 0x00}},
809         {"fye",         {0xcc, 0xaa, 0x00}},
810         {"fyo",         {0xcc, 0xae, 0x00}},
811         {"gwa",         {0xb8, 0xde, 0xa7, 0x00}},
812         {"gwi",         {0xb8, 0xde, 0xa8, 0x00}},
813         {"gwu",         {0xb8, 0xde, 0xa9, 0x00}},
814         {"gwe",         {0xb8, 0xde, 0xaa, 0x00}},
815         {"gwo",         {0xb8, 0xde, 0xab, 0x00}},
816         {"gya",         {0xb7, 0xde, 0xac, 0x00}},
817         {"gyi",         {0xb7, 0xde, 0xa8, 0x00}},
818         {"gyu",         {0xb7, 0xde, 0xad, 0x00}},
819         {"gye",         {0xb7, 0xde, 0xaa, 0x00}},
820         {"gyo",         {0xb7, 0xde, 0xae, 0x00}},
821         {"hya",         {0xcb, 0xac, 0x00}},
822         {"hyi",         {0xcb, 0xa8, 0x00}},
823         {"hyu",         {0xcb, 0xad, 0x00}},
824         {"hye",         {0xcb, 0xaa, 0x00}},
825         {"hyo",         {0xcb, 0xae, 0x00}},
826         {"jya",         {0xbc, 0xde, 0xac, 0x00}},
827         {"jyi",         {0xbc, 0xde, 0xa8, 0x00}},
828         {"jyu",         {0xbc, 0xde, 0xad, 0x00}},
829         {"jye",         {0xbc, 0xde, 0xaa, 0x00}},
830         {"jyo",         {0xbc, 0xde, 0xae, 0x00}},
831         {"kya",         {0xb7, 0xac, 0x00}},
832         {"kyi",         {0xb7, 0xa8, 0x00}},
833         {"kyu",         {0xb7, 0xad, 0x00}},
834         {"kye",         {0xb7, 0xaa, 0x00}},
835         {"kyo",         {0xb7, 0xae, 0x00}},
836         {"lya",         {0xac, 0x00}},
837         {"lyi",         {0xa8, 0x00}},
838         {"lyu",         {0xad, 0x00}},
839         {"lye",         {0xaa, 0x00}},
840         {"lyo",         {0xae, 0x00}},
841         {"mya",         {0xd0, 0xac, 0x00}},
842         {"myi",         {0xd0, 0xa8, 0x00}},
843         {"myu",         {0xd0, 0xad, 0x00}},
844         {"mye",         {0xd0, 0xaa, 0x00}},
845         {"myo",         {0xd0, 0xae, 0x00}},
846         {"nya",         {0xc6, 0xac, 0x00}},
847         {"nyi",         {0xc6, 0xa8, 0x00}},
848         {"nyu",         {0xc6, 0xad, 0x00}},
849         {"nye",         {0xc6, 0xaa, 0x00}},
850         {"nyo",         {0xc6, 0xae, 0x00}},
851         {"pya",         {0xcb, 0xdf, 0xac, 0x00}},
852         {"pyi",         {0xcb, 0xdf, 0xa8, 0x00}},
853         {"pyu",         {0xcb, 0xdf, 0xad, 0x00}},
854         {"pye",         {0xcb, 0xdf, 0xaa, 0x00}},
855         {"pyo",         {0xcb, 0xdf, 0xae, 0x00}},
856         {"qwa",         {0xb8, 0xa7, 0x00}},
857         {"qwi",         {0xb8, 0xa8, 0x00}},
858         {"qwu",         {0xb8, 0xa9, 0x00}},
859         {"qwe",         {0xb8, 0xaa, 0x00}},
860         {"qwo",         {0xb8, 0xab, 0x00}},
861         {"qya",         {0xb8, 0xac, 0x00}},
862         {"qyi",         {0xb8, 0xa8, 0x00}},
863         {"qyu",         {0xb8, 0xad, 0x00}},
864         {"qye",         {0xb8, 0xaa, 0x00}},
865         {"qyo",         {0xb8, 0xae, 0x00}},
866         {"rya",         {0xd8, 0xac, 0x00}},
867         {"ryi",         {0xd8, 0xa8, 0x00}},
868         {"ryu",         {0xd8, 0xad, 0x00}},
869         {"rye",         {0xd8, 0xaa, 0x00}},
870         {"ryo",         {0xd8, 0xae, 0x00}},
871         {"sha",         {0xbc, 0xac, 0x00}},
872         {"shi",         {0xbc, 0x00}},
873         {"shu",         {0xbc, 0xad, 0x00}},
874         {"she",         {0xbc, 0xaa, 0x00}},
875         {"sho",         {0xbc, 0xae, 0x00}},
876         {"swa",         {0xbd, 0xa7, 0x00}},
877         {"swi",         {0xbd, 0xa8, 0x00}},
878         {"swu",         {0xbd, 0xa9, 0x00}},
879         {"swe",         {0xbd, 0xaa, 0x00}},
880         {"swo",         {0xbd, 0xab, 0x00}},
881         {"sya",         {0xbc, 0xac, 0x00}},
882         {"syi",         {0xbc, 0xa8, 0x00}},
883         {"syu",         {0xbc, 0xad, 0x00}},
884         {"sye",         {0xbc, 0xaa, 0x00}},
885         {"syo",         {0xbc, 0xae, 0x00}},
886         {"tha",         {0xc3, 0xac, 0x00}},
887         {"thi",         {0xc3, 0xa8, 0x00}},
888         {"thu",         {0xc3, 0xad, 0x00}},
889         {"the",         {0xc3, 0xaa, 0x00}},
890         {"tho",         {0xc3, 0xae, 0x00}},
891         {"tsa",         {0xc2, 0xa7, 0x00}},
892         {"tsi",         {0xc2, 0xa8, 0x00}},
893         {"tsu",         {0xc2, 0x00}},
894         {"tse",         {0xc2, 0xaa, 0x00}},
895         {"tso",         {0xc2, 0xab, 0x00}},
896         {"twa",         {0xc4, 0xa7, 0x00}},
897         {"twi",         {0xc4, 0xa8, 0x00}},
898         {"twu",         {0xc4, 0xa9, 0x00}},
899         {"twe",         {0xc4, 0xaa, 0x00}},
900         {"two",         {0xc4, 0xab, 0x00}},
901         {"tya",         {0xc1, 0xac, 0x00}},
902         {"tyi",         {0xc1, 0xa8, 0x00}},
903         {"tyu",         {0xc1, 0xad, 0x00}},
904         {"tye",         {0xc1, 0xaa, 0x00}},
905         {"tyo",         {0xc1, 0xae, 0x00}},
906         {"vya",         {0xb3, 0xde, 0xac, 0x00}},
907         {"vyi",         {0xb3, 0xde, 0xa8, 0x00}},
908         {"vyu",         {0xb3, 0xde, 0xad, 0x00}},
909         {"vye",         {0xb3, 0xde, 0xaa, 0x00}},
910         {"vyo",         {0xb3, 0xde, 0xae, 0x00}},
911         {"wha",         {0xb3, 0xa7, 0x00}},
912         {"whi",         {0xb3, 0xa8, 0x00}},
913         {"whu",         {0xb3, 0x00}},
914         {"whe",         {0xb3, 0xaa, 0x00}},
915         {"who",         {0xb3, 0xab, 0x00}},
916         {"xya",         {0xac, 0x00}},
917         {"xyi",         {0xa8, 0x00}},
918         {"xyu",         {0xad, 0x00}},
919         {"xye",         {0xaa, 0x00}},
920         {"xyo",         {0xae, 0x00}},
921         {"zya",         {0xbc, 0xde, 0xac, 0x00}},
922         {"zyi",         {0xbc, 0xde, 0xa8, 0x00}},
923         {"zyu",         {0xbc, 0xde, 0xad, 0x00}},
924         {"zye",         {0xbc, 0xde, 0xaa, 0x00}},
925         {"zyo",         {0xbc, 0xde, 0xae, 0x00}},
926         {"ba",          {0xca, 0xde, 0x00}},
927         {"bi",          {0xcb, 0xde, 0x00}},
928         {"bu",          {0xcc, 0xde, 0x00}},
929         {"be",          {0xcd, 0xde, 0x00}},
930         {"bo",          {0xce, 0xde, 0x00}},
931         {"ca",          {0xb6, 0x00}},
932         {"ci",          {0xbc, 0x00}},
933         {"cu",          {0xb8, 0x00}},
934         {"ce",          {0xbe, 0x00}},
935         {"co",          {0xba, 0x00}},
936         {"da",          {0xc0, 0xde, 0x00}},
937         {"di",          {0xc1, 0xde, 0x00}},
938         {"du",          {0xc2, 0xde, 0x00}},
939         {"de",          {0xc3, 0xde, 0x00}},
940         {"do",          {0xc4, 0xde, 0x00}},
941         {"fa",          {0xcc, 0xa7, 0x00}},
942         {"fi",          {0xcc, 0xa8, 0x00}},
943         {"fu",          {0xcc, 0x00}},
944         {"fe",          {0xcc, 0xaa, 0x00}},
945         {"fo",          {0xcc, 0xab, 0x00}},
946         {"ga",          {0xb6, 0xde, 0x00}},
947         {"gi",          {0xb7, 0xde, 0x00}},
948         {"gu",          {0xb8, 0xde, 0x00}},
949         {"ge",          {0xb9, 0xde, 0x00}},
950         {"go",          {0xba, 0xde, 0x00}},
951         {"ha",          {0xca, 0x00}},
952         {"hi",          {0xcb, 0x00}},
953         {"hu",          {0xcc, 0x00}},
954         {"he",          {0xcd, 0x00}},
955         {"ho",          {0xce, 0x00}},
956         {"ja",          {0xbc, 0xde, 0xac, 0x00}},
957         {"ji",          {0xbc, 0xde, 0x00}},
958         {"ju",          {0xbc, 0xde, 0xad, 0x00}},
959         {"je",          {0xbc, 0xde, 0xaa, 0x00}},
960         {"jo",          {0xbc, 0xde, 0xae, 0x00}},
961         {"ka",          {0xb6, 0x00}},
962         {"ki",          {0xb7, 0x00}},
963         {"ku",          {0xb8, 0x00}},
964         {"ke",          {0xb9, 0x00}},
965         {"ko",          {0xba, 0x00}},
966         {"la",          {0xa7, 0x00}},
967         {"li",          {0xa8, 0x00}},
968         {"lu",          {0xa9, 0x00}},
969         {"le",          {0xaa, 0x00}},
970         {"lo",          {0xab, 0x00}},
971         {"ma",          {0xcf, 0x00}},
972         {"mi",          {0xd0, 0x00}},
973         {"mu",          {0xd1, 0x00}},
974         {"me",          {0xd2, 0x00}},
975         {"mo",          {0xd3, 0x00}},
976         {"na",          {0xc5, 0x00}},
977         {"ni",          {0xc6, 0x00}},
978         {"nu",          {0xc7, 0x00}},
979         {"ne",          {0xc8, 0x00}},
980         {"no",          {0xc9, 0x00}},
981 //      {"nn",          {0xdd, 0x00}},
982         {"pa",          {0xca, 0xdf, 0x00}},
983         {"pi",          {0xcb, 0xdf, 0x00}},
984         {"pu",          {0xcc, 0xdf, 0x00}},
985         {"pe",          {0xcd, 0xdf, 0x00}},
986         {"po",          {0xce, 0xdf, 0x00}},
987         {"qa",          {0xb8, 0xa7, 0x00}},
988         {"qi",          {0xb8, 0xa8, 0x00}},
989         {"qu",          {0xb8, 0x00}},
990         {"qe",          {0xb8, 0xaa, 0x00}},
991         {"qo",          {0xb8, 0xab, 0x00}},
992         {"ra",          {0xd7, 0x00}},
993         {"ri",          {0xd8, 0x00}},
994         {"ru",          {0xd9, 0x00}},
995         {"re",          {0xda, 0x00}},
996         {"ro",          {0xdb, 0x00}},
997         {"sa",          {0xbb, 0x00}},
998         {"si",          {0xbc, 0x00}},
999         {"su",          {0xbd, 0x00}},
1000         {"se",          {0xbe, 0x00}},
1001         {"so",          {0xbf, 0x00}},
1002         {"ta",          {0xc0, 0x00}},
1003         {"ti",          {0xc1, 0x00}},
1004         {"tu",          {0xc2, 0x00}},
1005         {"te",          {0xc3, 0x00}},
1006         {"to",          {0xc4, 0x00}},
1007         {"va",          {0xb3, 0xde, 0xa7, 0x00}},
1008         {"vi",          {0xb3, 0xde, 0xa8, 0x00}},
1009         {"vu",          {0xb3, 0xde, 0x00}},
1010         {"ve",          {0xb3, 0xde, 0xaa, 0x00}},
1011         {"vo",          {0xb3, 0xde, 0xab, 0x00}},
1012         {"wa",          {0xdc, 0x00}},
1013         {"wi",          {0xb3, 0xa8, 0x00}},
1014         {"wu",          {0xb3, 0x00}},
1015         {"we",          {0xb3, 0xaa, 0x00}},
1016         {"wo",          {0xa6, 0x00}},
1017         {"xa",          {0xa7, 0x00}},
1018         {"xi",          {0xa8, 0x00}},
1019         {"xu",          {0xa9, 0x00}},
1020         {"xe",          {0xaa, 0x00}},
1021         {"xo",          {0xab, 0x00}},
1022         {"ya",          {0xd4, 0x00}},
1023         {"yi",          {0xb2, 0x00}},
1024         {"yu",          {0xd5, 0x00}},
1025         {"ye",          {0xb2, 0xaa, 0x00}},
1026         {"yo",          {0xd6, 0x00}},
1027         {"za",          {0xbb, 0xde, 0x00}},
1028         {"zi",          {0xbc, 0xde, 0x00}},
1029         {"zu",          {0xbd, 0xde, 0x00}},
1030         {"ze",          {0xbe, 0xde, 0x00}},
1031         {"zo",          {0xbf, 0xde, 0x00}},
1032         {"a",           {0xb1, 0x00}},
1033         {"i",           {0xb2, 0x00}},
1034         {"u",           {0xb3, 0x00}},
1035         {"e",           {0xb4, 0x00}},
1036         {"o",           {0xb5, 0x00}},
1037         {"[",           {0xa2, 0x00}},
1038         {"]",           {0xa3, 0x00}},
1039         {"-",           {0xb0, 0x00}},
1040         {",",           {0xa4, 0x00}},
1041         {".",           {0xa1, 0x00}},
1042         {"/",           {0xa5, 0x00}},
1043         {"",            {0x00}},
1044 };
1045
1046 void EMU::initialize_auto_key()
1047 {
1048         auto_key_buffer = new FIFO(65536);
1049         auto_key_buffer->clear();
1050         auto_key_phase = auto_key_shift = 0;
1051         shift_pressed = false;
1052         osd->now_auto_key = false;
1053 }
1054
1055 void EMU::release_auto_key()
1056 {
1057         if(auto_key_buffer) {
1058                 auto_key_buffer->release();
1059                 delete auto_key_buffer;
1060         }
1061 }
1062
1063 int EMU::get_auto_key_code(int code)
1064 {
1065         static int auto_key_table[256];
1066         static bool initialized = false;
1067 #ifdef USE_KEYBOARD_TYPE
1068         static int keyboard_type = -1;
1069         
1070         if(keyboard_type != config.keyboard_type) {
1071                 initialized = false;
1072                 keyboard_type = config.keyboard_type;
1073         }
1074 #endif
1075         if(!initialized) {
1076                 memset(auto_key_table, 0, sizeof(auto_key_table));
1077                 for(int i = 0;; i++) {
1078                         if(auto_key_table_base[i][0] == -1) {
1079                                 break;
1080                         }
1081                         auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
1082                 }
1083 #if defined(_X1TURBO) || defined(_X1TURBOZ)
1084                 // FIXME
1085                 if(config.keyboard_type) {
1086                         for(int i = 0;; i++) {
1087                                 if(auto_key_table_50on_base[i][0] == -1) {
1088                                         break;
1089                                 }
1090                                 auto_key_table[auto_key_table_50on_base[i][0]] = auto_key_table_50on_base[i][1];
1091                         }
1092                 } else
1093 #endif
1094                 for(int i = 0;; i++) {
1095                         if(auto_key_table_kana_base[i][0] == -1) {
1096                                 break;
1097                         }
1098                         auto_key_table[auto_key_table_kana_base[i][0]] = auto_key_table_kana_base[i][1];
1099                 }
1100 #ifdef USE_VM_AUTO_KEY_TABLE
1101                 for(int i = 0;; i++) {
1102                         if(vm_auto_key_table_base[i][0] == -1) {
1103                                 break;
1104                         }
1105                         auto_key_table[vm_auto_key_table_base[i][0]] = vm_auto_key_table_base[i][1];
1106                 }
1107 #endif
1108                 initialized = true;
1109         }
1110         return auto_key_table[code];
1111 }
1112
1113 void EMU::set_auto_key_code(int code)
1114 {
1115         if(code == 0xf2 || (code = get_auto_key_code(code)) != 0) {
1116                 if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20 || code == 0xf2) {
1117                         // VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE, VK_OEM_COPY(Katakana/Hiragana)
1118                         auto_key_buffer->write(code);
1119 #ifdef USE_AUTO_KEY_NUMPAD
1120                 } else if(code >= 0x30 && code <= 0x39) {
1121                         // numpad
1122                         auto_key_buffer->write(code - 0x30 + 0x60);
1123 #endif
1124                 } else if(code & 0x200) {
1125                         // kana
1126                         auto_key_buffer->write(code & 0x1ff);
1127                 } else {
1128                         // ank other than alphabet and kana
1129                         auto_key_buffer->write(0xf2); // kana unlock
1130                         auto_key_buffer->write(code & 0x1ff);
1131                         auto_key_buffer->write(0xf2); // kana lock
1132                 }
1133                 if(!is_auto_key_running()) {
1134                         start_auto_key();
1135                 }
1136         }
1137 }
1138
1139 void EMU::set_auto_key_list(char *buf, int size)
1140 {
1141 #if defined(USE_KEY_LOCKED)
1142         bool prev_caps = get_caps_locked();
1143         bool prev_kana = get_kana_locked();
1144 #else
1145         bool prev_caps = false;
1146         bool prev_kana = false;
1147 #endif
1148         auto_key_buffer->clear();
1149         
1150         for(int i = 0; i < size; i++) {
1151                 int code = buf[i] & 0xff;
1152                 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
1153                         i++;    // kanji ?
1154                         continue;
1155                 } else if(code == 0x0a) {
1156                         continue;       // cr-lf
1157                 }
1158                 if((code = get_auto_key_code(code)) != 0) {
1159                         // kana lock
1160                         bool kana = ((code & 0x200) != 0);
1161                         if(prev_kana != kana) {
1162                                 auto_key_buffer->write(0xf2);
1163                         }
1164                         prev_kana = kana;
1165 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1166                         // use caps lock key to switch uppercase/lowercase of alphabet
1167                         // USE_AUTO_KEY_CAPS_LOCK shows the caps lock key code
1168                         bool caps = ((code & 0x400) != 0);
1169                         if(prev_caps != caps) {
1170                                 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1171                         }
1172                         prev_caps = caps;
1173 #endif
1174 #if defined(USE_AUTO_KEY_CAPS_LOCK) || defined(USE_AUTO_KEY_NO_CAPS)
1175                         code &= ~(0x400 | 0x800); // don't press shift key for both alphabet and ALPHABET
1176 #elif defined(USE_KEY_LOCKED)
1177                         if(get_caps_locked()) {
1178                                 code &= ~0x400; // don't press shift key for ALPHABET
1179                         } else {
1180                                 code &= ~0x800; // don't press shift key for alphabet
1181                         }
1182 #elif defined(USE_AUTO_KEY_CAPS)
1183                         code &= ~0x400; // don't press shift key for ALPHABET
1184 #else
1185                         code &= ~0x800; // don't press shift key for alphabet
1186 #endif
1187                         if(code & (0x100 | 0x400 | 0x800)) {
1188                                 auto_key_buffer->write((code & 0xff) | 0x100);
1189                         } else {
1190                                 auto_key_buffer->write(code & 0xff);
1191                         }
1192                 }
1193         }
1194         // release kana lock
1195         if(prev_kana) {
1196                 auto_key_buffer->write(0xf2);
1197         }
1198 #if defined(USE_AUTO_KEY_CAPS_LOCK)
1199         // release caps lock
1200         if(prev_caps) {
1201                 auto_key_buffer->write(USE_AUTO_KEY_CAPS_LOCK);
1202         }
1203 #endif
1204 }
1205
1206 bool is_alphabet(char code)
1207 {
1208         return (code >= 'a' && code <= 'z');
1209 }
1210
1211 bool is_vowel(char code)
1212 {
1213         return (code == 'a' || code == 'i' || code == 'u' || code == 'e' || code == 'o');
1214 }
1215
1216 bool is_consonant(char code)
1217 {
1218         return (is_alphabet(code) && !is_vowel(code));
1219 }
1220
1221 void EMU::set_auto_key_char(char code)
1222 {
1223         static char codes[5] = {0};
1224         if(code == 1) {
1225                 // start
1226 #ifdef USE_KEY_LOCKED
1227                 if(!get_kana_locked())
1228 #endif
1229                 set_auto_key_code(0xf2);
1230                 memset(codes, 0, sizeof(codes));
1231         } else if(code == 0) {
1232                 // end
1233                 if(codes[3] == 'n') {
1234                         set_auto_key_code(0xdd); // 'Ý'
1235                 }
1236                 set_auto_key_code(0xf2);
1237                 memset(codes, 0, sizeof(codes));
1238         } else if(code == 0x08 || code == 0x09 || code == 0x0d || code == 0x1b || code == 0x20) {
1239                 if(codes[3] == 'n') {
1240                         set_auto_key_code(0xdd); // 'Ý'
1241                 }
1242                 set_auto_key_code(code);
1243                 memset(codes, 0, sizeof(codes));
1244 #ifdef USE_AUTO_KEY_NUMPAD
1245         } else if(code >= 0x30 && code <= 0x39) {
1246                 if(codes[3] == 'n') {
1247                         set_auto_key_code(0xdd); // 'Ý'
1248                 }
1249                 set_auto_key_code(code);
1250                 memset(codes, 0, sizeof(codes));
1251 #endif
1252         } else {
1253                 codes[0] = codes[1];
1254                 codes[1] = codes[2];
1255                 codes[2] = codes[3];
1256                 codes[3] = (code >= 'A' && code <= 'Z') ? ('a' + (code - 'A')) : code;
1257                 codes[4] = '\0';
1258                 
1259                 if(codes[2] == 'n' && !is_vowel(codes[3])) {
1260                         set_auto_key_code(0xdd); // 'Ý'
1261                         if(codes[3] == 'n') {
1262                                 memset(codes, 0, sizeof(codes));
1263                                 return;
1264                         }
1265                 } else if(codes[2] == codes[3] && is_consonant(codes[3])) {
1266                         set_auto_key_code(0xaf); // '¯'
1267                         return;
1268                 }
1269                 for(int i = 0;; i++) {
1270                         int len = strlen(romaji_table[i].romaji), comp = -1;
1271                         if(len == 0) {
1272                                 // end of table
1273                                 if(!is_alphabet(codes[3])) {
1274                                         set_auto_key_code(codes[3]);
1275                                         memset(codes, 0, sizeof(codes));
1276                                 }
1277                                 break;
1278                         } else if(len == 1) {
1279                                 comp = strcmp(romaji_table[i].romaji, &codes[3]);
1280                         } else if(len == 2) {
1281                                 comp = strcmp(romaji_table[i].romaji, &codes[2]);
1282                         } else if(len == 3) {
1283                                 comp = strcmp(romaji_table[i].romaji, &codes[1]);
1284                         } else if(len == 4) {
1285                                 comp = strcmp(romaji_table[i].romaji, &codes[0]);
1286                         }
1287                         if(comp == 0) {
1288                                 for(int j = 0; j < 4; j++) {
1289                                         if(!romaji_table[i].kana[j]) {
1290                                                 break;
1291                                         }
1292                                         if(j == 0) {
1293                                                 bool handakuon_found = false;
1294                                                 bool dakuon_found = false;
1295 #if defined(USE_TWO_STROKE_AUTOKEY_HANDAKUON)
1296                                                 if(romaji_table[i].kana[1] == 0xdf) {
1297                                                         // HANDAKUON
1298                                                         for(int jj = 0;;jj++) {
1299                                                                 if(kana_handakuon_keyboard_table[jj][0] == -1) break;
1300                                                                 if(kana_handakuon_keyboard_table[jj][0] == romaji_table[i].kana[0]) {
1301                                                                         for(int l = 1; l < 6; l++) {
1302                                                                                 if(kana_handakuon_keyboard_table[jj][l] == 0x00) break;
1303                                                                                 auto_key_buffer->write(kana_handakuon_keyboard_table[jj][l] & 0x31ff);
1304                                                                                 if(!is_auto_key_running()) {
1305                                                                                         start_auto_key();
1306                                                                                 }
1307                                                                         }
1308                                                                         j += 1;
1309                                                                         handakuon_found = true;
1310                                                                         break;
1311                                                                 }
1312                                                         }
1313                                                 }
1314 #endif
1315 #if defined(USE_TWO_STROKE_AUTOKEY_DAKUON)
1316                                                 if(romaji_table[i].kana[1] == 0xde) {
1317                                                         // DAKUON
1318                                                         for(int jj = 0;;jj++) {
1319                                                                 if(kana_dakuon_keyboard_table[jj][0] == -1) break;
1320                                                                 if(kana_dakuon_keyboard_table[jj][0] == romaji_table[i].kana[0]) {
1321                                                                         for(int l = 1; l < 6; l++) {
1322                                                                                 if(kana_dakuon_keyboard_table[jj][l] == 0x00) break;
1323                                                                                 auto_key_buffer->write(kana_dakuon_keyboard_table[jj][l] & 0x31ff);
1324                                                                                 if(!is_auto_key_running()) {
1325                                                                                         start_auto_key();
1326                                                                                 }
1327                                                                         }
1328                                                                         j += 1;
1329                                                                         dakuon_found = true;
1330                                                                         break;
1331                                                                 }
1332                                                         }
1333                                                 }
1334 #endif
1335                                                 if((handakuon_found) || (dakuon_found)) {
1336 //                                                      if(!romaji_table[i].kana[j]) {
1337 //                                                              break;
1338 //                                                      }
1339                                                         continue;
1340                                                 }
1341                                         }
1342                                         set_auto_key_code(romaji_table[i].kana[j]);
1343                                 }
1344                                 memset(codes, 0, sizeof(codes));
1345                                 break;
1346                         }
1347                 }
1348         }
1349 }
1350
1351 void EMU::start_auto_key()
1352 {
1353         auto_key_phase = 1;
1354         auto_key_shift = 0;
1355         osd->now_auto_key = true;
1356 }
1357
1358 void EMU::stop_auto_key()
1359 {
1360         if(auto_key_shift) {
1361                 osd->key_up_native(VK_LSHIFT);
1362         }
1363         auto_key_phase = auto_key_shift = 0;
1364         osd->now_auto_key = false;
1365 }
1366
1367 #ifndef USE_AUTO_KEY_SHIFT
1368 #define USE_AUTO_KEY_SHIFT 0
1369 #endif
1370 #ifndef VK_LSHIFT
1371 #define VK_LSHIFT 0xA0
1372 #endif
1373
1374 void EMU::update_auto_key()
1375 {
1376         switch(auto_key_phase) {
1377         case 1:
1378                 if(auto_key_buffer && !auto_key_buffer->empty()) {
1379                         // update shift key status
1380                         int shift = auto_key_buffer->read_not_remove(0) & 0x100;
1381                         if(shift && !auto_key_shift) {
1382                                 osd->key_down_native(VK_LSHIFT, false);
1383                         } else if(!shift && auto_key_shift) {
1384                                 osd->key_up_native(VK_LSHIFT);
1385                         }
1386                         auto_key_shift = shift;
1387                         auto_key_phase++;
1388                         break;
1389                 }
1390         case 3 + USE_AUTO_KEY_SHIFT:
1391                 if(auto_key_buffer && !auto_key_buffer->empty()) {
1392                         if(!(auto_key_buffer->read_not_remove(0) & 0x2000)) {
1393                                 osd->key_down_native(auto_key_buffer->read_not_remove(0) & 0xff, false);
1394                         }
1395                 }
1396                 auto_key_phase++;
1397                 break;
1398         case USE_AUTO_KEY + USE_AUTO_KEY_SHIFT:
1399                 if(auto_key_buffer && !auto_key_buffer->empty()) {
1400                         if(!(auto_key_buffer->read_not_remove(0) & 0x1000)) {
1401                                 osd->key_up_native(auto_key_buffer->read_not_remove(0) & 0xff);
1402                         }
1403                 }
1404                 auto_key_phase++;
1405                 break;
1406         case USE_AUTO_KEY_RELEASE + USE_AUTO_KEY_SHIFT:
1407                 if(auto_key_buffer && !auto_key_buffer->empty()) {
1408                         // wait enough while vm analyzes one line
1409                         if(auto_key_buffer->read() == 0xd) {
1410                                 auto_key_phase++;
1411                                 break;
1412                         }
1413                 }
1414         case 30:
1415                 if(auto_key_buffer && !auto_key_buffer->empty()) {
1416                         auto_key_phase = 1;
1417                 } else {
1418                         stop_auto_key();
1419                 }
1420                 break;
1421         default:
1422                 if(auto_key_phase) {
1423                         auto_key_phase++;
1424                 }
1425         }
1426 }
1427 #endif
1428
1429 #ifdef USE_JOYSTICK
1430 void EMU::update_joystick()
1431 {
1432         uint32_t *joy_buffer = osd->get_joy_buffer();
1433         uint8_t *key_buffer = osd->get_key_buffer();
1434         
1435         memset(joy_status, 0, sizeof(joy_status));
1436         
1437         for(int i = 0; i < 4; i++) {
1438                 for(int j = 0; j < 16; j++) {
1439                         if(config.joy_buttons[i][j] < 0) {
1440                                 int code = -config.joy_buttons[i][j];
1441                                 if(code < 256 && key_buffer[code]) {
1442                                         joy_status[i] |= (1 << j);
1443                                         //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1444                                 }
1445                         } else {
1446                                 int stick = config.joy_buttons[i][j] >> 5;
1447                                 int button = config.joy_buttons[i][j] & 0x1f;
1448                                 if(stick < 4 && (joy_buffer[stick & 3] & (1 << button))) {
1449                                         joy_status[i] |= (1 << j);
1450                                         //printf("%d %d %02x %02x\n", i, j, config.joy_buttons[i][j], joy_status[i]);
1451                                 }
1452                         }
1453                 }
1454         }
1455 }
1456 #endif
1457
1458 const uint8_t* EMU::get_key_buffer()
1459 {
1460         return (const uint8_t*)osd->get_key_buffer();
1461 }
1462
1463 #ifdef USE_JOYSTICK
1464 const uint32_t* EMU::get_joy_buffer()
1465 {
1466         return (const uint32_t*)joy_status;
1467 }
1468 #endif
1469
1470 #ifdef USE_MOUSE
1471 const int32_t* EMU::get_mouse_buffer()
1472 {
1473         return (const int32_t*)osd->get_mouse_buffer();
1474 }
1475 #endif
1476
1477 // ----------------------------------------------------------------------------
1478 // screen
1479 // ----------------------------------------------------------------------------
1480
1481 double EMU::get_window_mode_power(int mode)
1482 {
1483         return osd->get_window_mode_power(mode);
1484 }
1485
1486 int EMU::get_window_mode_width(int mode)
1487 {
1488         return osd->get_window_mode_width(mode);
1489 }
1490
1491 int EMU::get_window_mode_height(int mode)
1492 {
1493         return osd->get_window_mode_height(mode);
1494 }
1495
1496 void EMU::set_host_window_size(int window_width, int window_height, bool window_mode)
1497 {
1498         osd->set_host_window_size(window_width, window_height, window_mode);
1499 }
1500
1501 void EMU::set_vm_screen_size(int screen_width, int screen_height, int window_width, int window_height, int window_width_aspect, int window_height_aspect)
1502 {
1503         osd->set_vm_screen_size(screen_width, screen_height, window_width, window_height, window_width_aspect, window_height_aspect);
1504 }
1505
1506 void EMU::set_vm_screen_lines(int lines)
1507 {
1508         osd->set_vm_screen_lines(lines);
1509 }
1510
1511
1512 int EMU::get_vm_window_width()
1513 {
1514         return osd->get_vm_window_width();
1515 }
1516
1517 int EMU::get_vm_window_height()
1518 {
1519         return osd->get_vm_window_height();
1520 }
1521
1522 int EMU::get_vm_window_width_aspect()
1523 {
1524         return osd->get_vm_window_width_aspect();
1525 }
1526
1527 int EMU::get_vm_window_height_aspect()
1528 {
1529         return osd->get_vm_window_height_aspect();
1530 }
1531
1532 #if defined(USE_MINIMUM_RENDERING)
1533 bool EMU::is_screen_changed()
1534 {
1535         return vm->is_screen_changed();
1536 }
1537 #endif
1538
1539 int EMU::draw_screen()
1540 {
1541 #ifdef ONE_BOARD_MICRO_COMPUTER
1542         if(now_waiting_in_debugger) {
1543                 osd->reload_bitmap();
1544         }
1545 #endif
1546         return osd->draw_screen();
1547 }
1548
1549 scrntype_t* EMU::get_screen_buffer(int y)
1550 {
1551         return osd->get_vm_screen_buffer(y);
1552 }
1553
1554 #ifdef USE_SCREEN_FILTER
1555 void EMU::screen_skip_line(bool skip_line)
1556 {
1557         osd->screen_skip_line = skip_line;
1558 }
1559 #endif
1560
1561 #ifdef ONE_BOARD_MICRO_COMPUTER
1562 void EMU::get_invalidated_rect(int *left, int *top, int *right, int *bottom)
1563 {
1564 #ifdef MAX_DRAW_RANGES
1565         for(int i = 0; i < MAX_DRAW_RANGES; i++) {
1566 #else
1567         for(int i = 0; i < vm->max_draw_ranges(); i++) { // for TK-80BS
1568 #endif
1569                 int x1 = vm_ranges[i].x;
1570                 int y1 = vm_ranges[i].y;
1571                 int x2 = x1 + vm_ranges[i].width;
1572                 int y2 = y1 + vm_ranges[i].height;
1573                 
1574                 *left   = (i == 0) ? x1 : min(x1, *left  );
1575                 *top    = (i == 0) ? y1 : min(y1, *top   );
1576                 *right  = (i == 0) ? x2 : max(x2, *right );
1577                 *bottom = (i == 0) ? y2 : max(y2, *bottom);
1578         }
1579 }
1580
1581 void EMU::reload_bitmap()
1582 {
1583         osd->reload_bitmap();
1584 }
1585 #endif
1586
1587 #ifdef OSD_WIN32
1588 void EMU::invalidate_screen()
1589 {
1590         osd->invalidate_screen();
1591 }
1592
1593 void EMU::update_screen(HDC hdc)
1594 {
1595         osd->update_screen(hdc);
1596 }
1597 #endif
1598
1599 void EMU::capture_screen()
1600 {
1601         osd->capture_screen();
1602 }
1603
1604 bool EMU::start_record_video(int fps)
1605 {
1606         return osd->start_record_video(fps);
1607 }
1608
1609 void EMU::stop_record_video()
1610 {
1611         osd->stop_record_video();
1612 }
1613
1614 bool EMU::is_video_recording()
1615 {
1616         return osd->now_record_video;
1617 }
1618
1619 // ----------------------------------------------------------------------------
1620 // sound
1621 // ----------------------------------------------------------------------------
1622
1623 void EMU::mute_sound()
1624 {
1625         osd->mute_sound();
1626 }
1627
1628 void EMU::start_record_sound()
1629 {
1630         osd->start_record_sound();
1631 }
1632
1633 void EMU::stop_record_sound()
1634 {
1635         osd->stop_record_sound();
1636 }
1637
1638 bool EMU::is_sound_recording()
1639 {
1640         return osd->now_record_sound;
1641 }
1642
1643 // ----------------------------------------------------------------------------
1644 // video
1645 // ----------------------------------------------------------------------------
1646
1647 #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE)
1648 void EMU::get_video_buffer()
1649 {
1650         osd->get_video_buffer();
1651 }
1652
1653 void EMU::mute_video_dev(bool l, bool r)
1654 {
1655         osd->mute_video_dev(l, r);
1656 }
1657 #endif
1658
1659 #ifdef USE_MOVIE_PLAYER
1660 bool EMU::open_movie_file(const _TCHAR* file_path)
1661 {
1662         return osd->open_movie_file(file_path);
1663 }
1664
1665 void EMU::close_movie_file()
1666 {
1667         osd->close_movie_file();
1668 }
1669
1670 void EMU::play_movie()
1671 {
1672         osd->play_movie();
1673 }
1674
1675 void EMU::stop_movie()
1676 {
1677         osd->stop_movie();
1678 }
1679
1680 void EMU::pause_movie()
1681 {
1682         osd->pause_movie();
1683 }
1684
1685 double EMU::get_movie_frame_rate()
1686 {
1687         return osd->get_movie_frame_rate();
1688 }
1689
1690 int EMU::get_movie_sound_rate()
1691 {
1692         return osd->get_movie_sound_rate();
1693 }
1694
1695 void EMU::set_cur_movie_frame(int frame, bool relative)
1696 {
1697         osd->set_cur_movie_frame(frame, relative);
1698 }
1699
1700 uint32_t EMU::get_cur_movie_frame()
1701 {
1702         return osd->get_cur_movie_frame();
1703 }
1704 #endif
1705
1706 #ifdef USE_VIDEO_CAPTURE
1707 int EMU::get_cur_capture_dev_index()
1708 {
1709         return osd->get_cur_capture_dev_index();
1710 }
1711
1712 int EMU::get_num_capture_devs()
1713 {
1714         return osd->get_num_capture_devs();
1715 }
1716
1717 _TCHAR* EMU::get_capture_dev_name(int index)
1718 {
1719         return osd->get_capture_dev_name(index);
1720 }
1721
1722 void EMU::open_capture_dev(int index, bool pin)
1723 {
1724         osd->open_capture_dev(index, pin);
1725 }
1726
1727 void EMU::close_capture_dev()
1728 {
1729         osd->close_capture_dev();
1730 }
1731
1732 void EMU::show_capture_dev_filter()
1733 {
1734         osd->show_capture_dev_filter();
1735 }
1736
1737 void EMU::show_capture_dev_pin()
1738 {
1739         osd->show_capture_dev_pin();
1740 }
1741
1742 void EMU::show_capture_dev_source()
1743 {
1744         osd->show_capture_dev_source();
1745 }
1746
1747 void EMU::set_capture_dev_channel(int ch)
1748 {
1749         osd->set_capture_dev_channel(ch);
1750 }
1751 #endif
1752
1753 // ----------------------------------------------------------------------------
1754 // printer
1755 // ----------------------------------------------------------------------------
1756
1757 #ifdef USE_PRINTER
1758 void EMU::create_bitmap(bitmap_t *bitmap, int width, int height)
1759 {
1760         osd->create_bitmap(bitmap, width, height);
1761 }
1762
1763 void EMU::release_bitmap(bitmap_t *bitmap)
1764 {
1765         osd->release_bitmap(bitmap);
1766 }
1767
1768 void EMU::create_font(font_t *font, const _TCHAR *family, int width, int height, int rotate, bool bold, bool italic)
1769 {
1770         osd->create_font(font, family, width, height, rotate, bold, italic);
1771 }
1772
1773 void EMU::release_font(font_t *font)
1774 {
1775         osd->release_font(font);
1776 }
1777
1778 void EMU::create_pen(pen_t *pen, int width, uint8_t r, uint8_t g, uint8_t b)
1779 {
1780         osd->create_pen(pen, width, r, g, b);
1781 }
1782
1783 void EMU::release_pen(pen_t *pen)
1784 {
1785         osd->release_pen(pen);
1786 }
1787
1788 void EMU::clear_bitmap(bitmap_t *bitmap, uint8_t r, uint8_t g, uint8_t b)
1789 {
1790         osd->clear_bitmap(bitmap, r, g, b);
1791 }
1792
1793 int EMU::get_text_width(bitmap_t *bitmap, font_t *font, const char *text)
1794 {
1795         return osd->get_text_width(bitmap, font, text);
1796 }
1797
1798 void EMU::draw_text_to_bitmap(bitmap_t *bitmap, font_t *font, int x, int y, const char *text, uint8_t r, uint8_t g, uint8_t b)
1799 {
1800         osd->draw_text_to_bitmap(bitmap, font, x, y, text, r, g, b);
1801 }
1802
1803 void EMU::draw_line_to_bitmap(bitmap_t *bitmap, pen_t *pen, int sx, int sy, int ex, int ey)
1804 {
1805         osd->draw_line_to_bitmap(bitmap, pen, sx, sy, ex, ey);
1806 }
1807
1808 void EMU::draw_rectangle_to_bitmap(bitmap_t *bitmap, int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b)
1809 {
1810         osd->draw_rectangle_to_bitmap(bitmap, x, y, width, height, r, g, b);
1811 }
1812
1813 void EMU::draw_point_to_bitmap(bitmap_t *bitmap, int x, int y, uint8_t r, uint8_t g, uint8_t b)
1814 {
1815         osd->draw_point_to_bitmap(bitmap, x, y, r, g, b);
1816 }
1817
1818 void EMU::stretch_bitmap(bitmap_t *dest, int dest_x, int dest_y, int dest_width, int dest_height, bitmap_t *source, int source_x, int source_y, int source_width, int source_height)
1819 {
1820         osd->stretch_bitmap(dest, dest_x, dest_y, dest_width, dest_height, source, source_x, source_y, source_width, source_height);
1821 }
1822
1823 void EMU::write_bitmap_to_file(bitmap_t *bitmap, const _TCHAR *file_path)
1824 {
1825         osd->write_bitmap_to_file(bitmap, file_path);
1826 }
1827 #endif
1828
1829 // ----------------------------------------------------------------------------
1830 // socket
1831 // ----------------------------------------------------------------------------
1832
1833 #ifdef USE_SOCKET
1834 int EMU::get_socket(int ch)
1835 {
1836         return osd->get_socket(ch);
1837 }
1838
1839 void EMU::notify_socket_connected(int ch)
1840 {
1841         osd->notify_socket_connected(ch);
1842 }
1843
1844 void EMU::notify_socket_disconnected(int ch)
1845 {
1846         osd->notify_socket_disconnected(ch);
1847 }
1848
1849 bool EMU::initialize_socket_tcp(int ch)
1850 {
1851         return osd->initialize_socket_tcp(ch);
1852 }
1853
1854 bool EMU::initialize_socket_udp(int ch)
1855 {
1856         return osd->initialize_socket_udp(ch);
1857 }
1858
1859 bool EMU::connect_socket(int ch, uint32_t ipaddr, int port)
1860 {
1861         return osd->connect_socket(ch, ipaddr, port);
1862 }
1863
1864 void EMU::disconnect_socket(int ch)
1865 {
1866         osd->disconnect_socket(ch);
1867 }
1868  
1869 bool EMU::listen_socket(int ch)
1870 {
1871         return osd->listen_socket(ch);
1872 }
1873
1874 void EMU::send_socket_data_tcp(int ch)
1875 {
1876         osd->send_socket_data_tcp(ch);
1877 }
1878
1879 void EMU::send_socket_data_udp(int ch, uint32_t ipaddr, int port)
1880 {
1881         osd->send_socket_data_udp(ch, ipaddr, port);
1882 }
1883
1884 void EMU::send_socket_data(int ch)
1885 {
1886         osd->send_socket_data(ch);
1887 }
1888
1889 void EMU::recv_socket_data(int ch)
1890 {
1891         osd->recv_socket_data(ch);
1892 }
1893 #endif
1894
1895 // ---------------------------------------------------------------------------
1896 // debugger (some functions needed by libCSPcommon_vm 20190221 K.O)
1897 // ---------------------------------------------------------------------------
1898
1899 void EMU::start_waiting_in_debugger()
1900 {
1901 #ifdef USE_DEBUGGER
1902         now_waiting_in_debugger = true;
1903 #endif
1904         osd->mute_sound();
1905 #ifdef USE_DEBUGGER
1906         osd->start_waiting_in_debugger();
1907 #endif
1908 }
1909
1910 void EMU::finish_waiting_in_debugger()
1911 {
1912 #ifdef USE_DEBUGGER
1913         osd->finish_waiting_in_debugger();
1914         now_waiting_in_debugger = false;
1915 #endif
1916 }
1917
1918 void EMU::process_waiting_in_debugger()
1919 {
1920 #ifdef USE_DEBUGGER
1921         osd->process_waiting_in_debugger();
1922 #else
1923         osd->sleep(10);
1924 #endif
1925 }
1926
1927 // ----------------------------------------------------------------------------
1928 // debug log
1929 // ----------------------------------------------------------------------------
1930
1931 #ifdef _DEBUG_LOG
1932 void EMU::initialize_debug_log()
1933 {
1934         _TCHAR path[_MAX_PATH];
1935         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1936 }
1937
1938 void EMU::release_debug_log()
1939 {
1940         if(debug_log) {
1941                 fclose(debug_log);
1942                 debug_log = NULL;
1943         }
1944 }
1945 #endif
1946
1947 #ifdef _DEBUG_LOG
1948 static _TCHAR prev_buffer[1024] = {0};
1949 #endif
1950
1951 void EMU::out_debug_log(const _TCHAR* format, ...)
1952 {
1953         common_initialize();
1954         
1955 #ifdef _DEBUG_LOG
1956         va_list ap;
1957         _TCHAR buffer[1024];
1958         
1959         va_start(ap, format);
1960         my_vstprintf_s(buffer, 1024, format, ap);
1961         va_end(ap);
1962         
1963         if(_tcscmp(prev_buffer, buffer) == 0) {
1964                 return;
1965         }
1966         my_tcscpy_s(prev_buffer, 1024, buffer);
1967         
1968 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1969         csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1970 #else
1971         if(debug_log) {
1972                 _ftprintf(debug_log, _T("%s"), buffer);
1973                 static int size = 0;
1974                 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
1975                         fclose(debug_log);
1976                         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
1977                         size = 0;
1978                 }
1979         }
1980 #endif
1981 #endif
1982 }
1983
1984 void EMU::force_out_debug_log(const _TCHAR* format, ...)
1985 {
1986 #ifdef _DEBUG_LOG
1987         va_list ap;
1988         _TCHAR buffer[1024];
1989         
1990         va_start(ap, format);
1991         my_vstprintf_s(buffer, 1024, format, ap);
1992         va_end(ap);
1993         my_tcscpy_s(prev_buffer, 1024, buffer);
1994         
1995 #if defined(_USE_QT) || defined(_USE_AGAR) || defined(_USE_SDL)
1996         csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", buffer);
1997 #else
1998         if(debug_log) {
1999                 _ftprintf(debug_log, _T("%s"), buffer);
2000                 static int size = 0;
2001                 if((size += _tcslen(buffer)) > 0x8000000) { // 128MB
2002                         fclose(debug_log);
2003                         debug_log = _tfopen(create_date_file_path(_T("log")), _T("w"));
2004                         size = 0;
2005                 }
2006         }
2007 #endif
2008 #endif
2009 }
2010
2011 void EMU::out_message(const _TCHAR* format, ...)
2012 {
2013 //#if defined(_USE_QT)
2014 //      _TCHAR mes_buf[1024];
2015 //#endif        
2016         va_list ap;
2017         va_start(ap, format);
2018         my_vstprintf_s(message, 1024, format, ap); // Security for MSVC:C6386.
2019 //#if defined(_USE_QT)
2020 //      memset(mes_buf, 0x00, sizeof(mes_buf));
2021 //      my_vstprintf_s(mes_buf, 1024, format, ap); // Security for MSVC:C6386.
2022 //      csp_logger->debug_log(CSP_LOG_DEBUG, CSP_LOG_TYPE_EMU, "%s", mes_buf);
2023 //#endif
2024         va_end(ap);
2025         message_count = 4; // 4sec
2026 }
2027
2028 // ----------------------------------------------------------------------------
2029 // misc
2030 // ----------------------------------------------------------------------------
2031
2032
2033 void EMU::sleep(uint32_t ms)
2034 {
2035         osd->sleep(ms);
2036 }
2037
2038
2039 // ----------------------------------------------------------------------------
2040 // user interface
2041 // ----------------------------------------------------------------------------
2042
2043 static uint8_t hex2uint8(char *value)
2044 {
2045         char tmp[3];
2046         memset(tmp, 0, sizeof(tmp));
2047         memcpy(tmp, value, 2);
2048         return (uint8_t)strtoul(tmp, NULL, 16);
2049 }
2050
2051 static uint16_t hex2uint16(char *value)
2052 {
2053         char tmp[5];
2054         memset(tmp, 0, sizeof(tmp));
2055         memcpy(tmp, value, 4);
2056         return (uint16_t)strtoul(tmp, NULL, 16);
2057 }
2058
2059 static bool hex2bin(const _TCHAR* file_path, const _TCHAR* dest_path)
2060 {
2061         bool result = false;
2062         FILEIO *fio_s = new FILEIO();
2063         if(fio_s->Fopen(file_path, FILEIO_READ_BINARY)) {
2064                 int length = 0;
2065                 char line[1024];
2066                 uint8_t buffer[0x10000];
2067                 memset(buffer, 0xff, sizeof(buffer));
2068                 while(fio_s->Fgets(line, sizeof(line)) != NULL) {
2069                         if(line[0] != ':') continue;
2070                         int bytes = hex2uint8(line + 1);
2071                         int offset = hex2uint16(line + 3);
2072                         uint8_t record_type = hex2uint8(line + 7);
2073                         if(record_type == 0x01) break;
2074                         if(record_type != 0x00) continue;
2075                         for(int i = 0; i < bytes; i++) {
2076                                 if((offset + i) < (int)sizeof(buffer)) {
2077                                         if(length < (offset + i)) {
2078                                                 length = offset + i;
2079                                         }
2080                                         buffer[offset + i] = hex2uint8(line + 9 + 2 * i);
2081                                 }
2082                         }
2083                 }
2084                 if(length > 0) {
2085                         FILEIO *fio_d = new FILEIO();
2086                         if(fio_d->Fopen(dest_path, FILEIO_WRITE_BINARY)) {
2087                                 fio_d->Fwrite(buffer, length, 1);
2088                                 fio_d->Fclose();
2089                                 result = true;
2090                         }
2091                         delete fio_d;
2092                 }
2093                 fio_s->Fclose();
2094         }
2095         delete fio_s;
2096         return result;
2097 }
2098
2099 void EMU::initialize_media()
2100 {
2101 #ifdef USE_CART
2102         memset(&cart_status, 0, sizeof(cart_status));
2103 #endif
2104 #ifdef USE_FLOPPY_DISK
2105         memset(floppy_disk_status, 0, sizeof(floppy_disk_status));
2106 #endif
2107 #ifdef USE_QUICK_DISK
2108         memset(&quick_disk_status, 0, sizeof(quick_disk_status));
2109 #endif
2110 #ifdef USE_HARD_DISK
2111         memset(&hard_disk_status, 0, sizeof(hard_disk_status));
2112 #endif
2113 #ifdef USE_TAPE
2114         memset(&tape_status, 0, sizeof(tape_status));
2115 #endif
2116 #ifdef USE_COMPACT_DISC
2117         memset(&compact_disc_status, 0, sizeof(compact_disc_status));
2118 #endif
2119 #ifdef USE_LASER_DISC
2120         memset(&laser_disc_status, 0, sizeof(laser_disc_status));
2121 #endif
2122 #ifdef USE_BUBBLE
2123         memset(&bubble_casette_status, 0, sizeof(bubble_casette_status));
2124 #endif
2125 }
2126
2127
2128 void EMU::update_media()
2129 {
2130 #ifdef USE_FLOPPY_DISK
2131         for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2132                 if(floppy_disk_status[drv].wait_count != 0 && --floppy_disk_status[drv].wait_count == 0) {
2133                         vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2134 #if USE_FLOPPY_DISK > 1
2135                         out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, floppy_disk_status[drv].path);
2136 #else
2137                         out_message(_T("FD: %s"), floppy_disk_status[drv].path);
2138 #endif
2139                 }
2140         }
2141 #endif
2142 #ifdef USE_QUICK_DISK
2143         for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2144                 if(quick_disk_status[drv].wait_count != 0 && --quick_disk_status[drv].wait_count == 0) {
2145                         vm->open_quick_disk(drv, quick_disk_status[drv].path);
2146 #if USE_QUICK_DISK > 1
2147                         out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, quick_disk_status[drv].path);
2148 #else
2149                         out_message(_T("QD: %s"), quick_disk_status[drv].path);
2150 #endif
2151                 }
2152         }
2153 #endif
2154 #ifdef USE_HARD_DISK
2155         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2156                 if(hard_disk_status[drv].wait_count != 0 && --hard_disk_status[drv].wait_count == 0) {
2157                         vm->open_hard_disk(drv, hard_disk_status[drv].path);
2158 #if USE_HARD_DISK > 1
2159                         out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, hard_disk_status[drv].path);
2160 #else
2161                         out_message(_T("HD: %s"), hard_disk_status[drv].path);
2162 #endif
2163                 }
2164         }
2165 #endif
2166 #ifdef USE_TAPE
2167         for(int drv = 0; drv < USE_TAPE; drv++) {
2168                 if(tape_status[drv].wait_count != 0 && --tape_status[drv].wait_count == 0) {
2169                         if(tape_status[drv].play) {
2170                                 vm->play_tape(drv, tape_status[drv].path);
2171                         } else {
2172                                 vm->rec_tape(drv, tape_status[drv].path);
2173                         }
2174 #if USE_TAPE > 1
2175                         out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, tape_status[drv].path);
2176 #else
2177                         out_message(_T("CMT: %s"), tape_status[drv].path);
2178 #endif
2179                 }
2180         }
2181 #endif
2182 #ifdef USE_COMPACT_DISC
2183         for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2184                 if(compact_disc_status[drv].wait_count != 0 && --compact_disc_status[drv].wait_count == 0) {
2185                         vm->open_compact_disc(drv, compact_disc_status[drv].path);
2186 #if USE_COMPACT_DISC > 1
2187                         out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, compact_disc_status[drv].path);
2188 #else
2189                         out_message(_T("CD: %s"), compact_disc_status[drv].path);
2190 #endif
2191                 }
2192         }
2193 #endif
2194 #ifdef USE_LASER_DISC
2195         for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2196                 if(laser_disc_status[drv].wait_count != 0 && --laser_disc_status[drv].wait_count == 0) {
2197                         vm->open_laser_disc(drv, laser_disc_status[drv].path);
2198 #if USE_LASER_DISC > 1
2199                         out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, laser_disc_status[drv].path);
2200 #else
2201                         out_message(_T("LD: %s"), laser_disc_status[drv].path);
2202 #endif
2203                 }
2204         }
2205 #endif
2206 #ifdef USE_BUBBLE
2207         for(int drv = 0; drv < USE_BUBBLE; drv++) {
2208                 if(bubble_casette_status[drv].wait_count != 0 && --bubble_casette_status[drv].wait_count == 0) {
2209                         vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2210 #if USE_BUBBLE > 1
2211                         out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, bubble_casette_status[drv].path);
2212 #else
2213                         out_message(_T("Bubble: %s"), bubble_casette_status[drv].path);
2214 #endif
2215                 }
2216         }
2217 #endif
2218 }
2219
2220 void EMU::restore_media()
2221 {
2222 #ifdef USE_CART
2223         for(int drv = 0; drv < USE_CART; drv++) {
2224                 if(cart_status[drv].path[0] != _T('\0')) {
2225                         if(check_file_extension(cart_status[drv].path, _T(".hex")) && hex2bin(cart_status[drv].path, create_local_path(_T("hex2bin.$$$")))) {
2226                                 vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2227                                 FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2228                         } else {
2229                                 vm->open_cart(drv, cart_status[drv].path);
2230                         }
2231                 }
2232         }
2233 #endif
2234 #ifdef USE_FLOPPY_DISK
2235         for(int drv = 0; drv < USE_FLOPPY_DISK; drv++) {
2236                 if(floppy_disk_status[drv].path[0] != _T('\0')) {
2237                         vm->open_floppy_disk(drv, floppy_disk_status[drv].path, floppy_disk_status[drv].bank);
2238                 }
2239         }
2240 #endif
2241 #ifdef USE_QUICK_DISK
2242         for(int drv = 0; drv < USE_QUICK_DISK; drv++) {
2243                 if(quick_disk_status[drv].path[0] != _T('\0')) {
2244                         vm->open_quick_disk(drv, quick_disk_status[drv].path);
2245                 }
2246         }
2247 #endif
2248 #ifdef USE_HARD_DISK
2249         for(int drv = 0; drv < USE_HARD_DISK; drv++) {
2250                 if(hard_disk_status[drv].path[0] != _T('\0')) {
2251                         vm->open_hard_disk(drv, hard_disk_status[drv].path);
2252                 }
2253         }
2254 #endif
2255 #ifdef USE_TAPE
2256         for(int drv = 0; drv < USE_TAPE; drv++) {
2257                 if(tape_status[drv].path[0] != _T('\0')) {
2258                         if(tape_status[drv].play) {
2259                                 vm->play_tape(drv, tape_status[drv].path);
2260                         } else {
2261                                 tape_status[drv].path[0] = _T('\0');
2262                         }
2263                 }
2264         }
2265 #endif
2266 #ifdef USE_COMPACT_DISC
2267         for(int drv = 0; drv < USE_COMPACT_DISC; drv++) {
2268                 if(compact_disc_status[drv].path[0] != _T('\0')) {
2269                         vm->open_compact_disc(drv, compact_disc_status[drv].path);
2270                 }
2271         }
2272 #endif
2273 #ifdef USE_LASER_DISC
2274         for(int drv = 0; drv < USE_LASER_DISC; drv++) {
2275                 if(laser_disc_status[drv].path[0] != _T('\0')) {
2276                         vm->open_laser_disc(drv, laser_disc_status[drv].path);
2277                 }
2278         }
2279 #endif
2280 #ifdef USE_BUBBLE
2281         for(int drv = 0; drv < USE_BUBBLE; drv++) {
2282                 if(bubble_casette_status[drv].path[0] != _T('\0')) {
2283                         vm->open_bubble_casette(drv, bubble_casette_status[drv].path, bubble_casette_status[drv].bank);
2284                 }
2285         }
2286 #endif
2287 }
2288
2289 #ifdef USE_CART
2290 void EMU::open_cart(int drv, const _TCHAR* file_path)
2291 {
2292         if(drv < USE_CART) {
2293                 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2294                         vm->open_cart(drv, create_local_path(_T("hex2bin.$$$")));
2295                         FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2296                 } else {
2297                         vm->open_cart(drv, file_path);
2298                 }
2299                 my_tcscpy_s(cart_status[drv].path, _MAX_PATH, file_path);
2300                 out_message(_T("Cart%d: %s"), drv + 1, file_path);
2301 #if !defined(_USE_QT)           
2302                 // restart recording
2303                 bool s = osd->now_record_sound;
2304                 bool v = osd->now_record_video;
2305                 stop_record_sound();
2306                 stop_record_video();
2307
2308                 if(s) osd->start_record_sound();
2309                 if(v) osd->start_record_video(-1);
2310 #endif          
2311         }
2312 }
2313
2314 void EMU::close_cart(int drv)
2315 {
2316         if(drv < USE_CART) {
2317                 vm->close_cart(drv);
2318                 clear_media_status(&cart_status[drv]);
2319 #if USE_CART > 1
2320                 out_message(_T("Cart%d: Ejected"), drv + BASE_CART_NUM);
2321 #else
2322                 out_message(_T("Cart: Ejected"));
2323 #endif
2324 #if !defined(_USE_QT)           
2325                 // stop recording
2326                 stop_record_video();
2327                 stop_record_sound();
2328 #endif          
2329         }
2330 }
2331
2332 bool EMU::is_cart_inserted(int drv)
2333 {
2334         if(drv < USE_CART) {
2335                 return vm->is_cart_inserted(drv);
2336         } else {
2337                 return false;
2338         }
2339 }
2340 #endif
2341
2342 #ifdef USE_FLOPPY_DISK
2343 void EMU::create_bank_floppy_disk(const _TCHAR* file_path, uint8_t type)
2344 {
2345         /*
2346                 type: 0x00 = 2D, 0x10 = 2DD, 0x20 = 2HD
2347         */
2348         struct {
2349                 char title[17];
2350                 uint8_t rsrv[9];
2351                 uint8_t protect;
2352                 uint8_t type;
2353                 uint32_t size;
2354                 uint32_t trkptr[164];
2355         } d88_hdr;
2356         
2357         memset(&d88_hdr, 0, sizeof(d88_hdr));
2358         my_strcpy_s(d88_hdr.title, sizeof(d88_hdr.title), "BLANK");
2359         d88_hdr.type = type;
2360         d88_hdr.size = sizeof(d88_hdr);
2361         
2362         FILEIO *fio = new FILEIO();
2363         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
2364                 fio->Fwrite(&d88_hdr, sizeof(d88_hdr), 1);
2365                 fio->Fclose();
2366         }
2367         delete fio;
2368 }
2369
2370 void EMU::open_floppy_disk(int drv, const _TCHAR* file_path, int bank)
2371 {
2372         if(drv < USE_FLOPPY_DISK) {
2373                 if(vm->is_floppy_disk_inserted(drv)) {
2374                         vm->close_floppy_disk(drv);
2375                         // wait 0.5sec
2376                         floppy_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2377 #if USE_FLOPPY_DISK > 1
2378                         out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2379 #else
2380                         out_message(_T("FD: Ejected"));
2381 #endif
2382                 } else if(floppy_disk_status[drv].wait_count == 0) {
2383                         vm->open_floppy_disk(drv, file_path, bank);
2384 #if USE_FLOPPY_DISK > 1
2385                         out_message(_T("FD%d: %s"), drv + BASE_FLOPPY_DISK_NUM, file_path);
2386 #else
2387                         out_message(_T("FD: %s"), file_path);
2388 #endif
2389                 }
2390                 my_tcscpy_s(floppy_disk_status[drv].path, _MAX_PATH, file_path);
2391                 floppy_disk_status[drv].bank = bank;
2392         }
2393 }
2394
2395 void EMU::close_floppy_disk(int drv)
2396 {
2397         if(drv < USE_FLOPPY_DISK) {
2398                 vm->close_floppy_disk(drv);
2399                 clear_media_status(&floppy_disk_status[drv]);
2400 #if USE_FLOPPY_DISK > 1
2401                 out_message(_T("FD%d: Ejected"), drv + BASE_FLOPPY_DISK_NUM);
2402 #else
2403                 out_message(_T("FD: Ejected"));
2404 #endif
2405         }
2406 }
2407
2408 bool EMU::is_floppy_disk_inserted(int drv)
2409 {
2410         if(drv < USE_FLOPPY_DISK) {
2411                 return vm->is_floppy_disk_inserted(drv);
2412         } else {
2413                 return false;
2414         }
2415 }
2416
2417 void EMU::is_floppy_disk_protected(int drv, bool value)
2418 {
2419         if(drv < USE_FLOPPY_DISK) {
2420                 vm->is_floppy_disk_protected(drv, value);
2421         }
2422 }
2423
2424 bool EMU::is_floppy_disk_protected(int drv)
2425 {
2426         if(drv < USE_FLOPPY_DISK) {
2427                 return vm->is_floppy_disk_protected(drv);
2428         } else {
2429                 return false;
2430         }
2431 }
2432
2433 uint32_t EMU::is_floppy_disk_accessed()
2434 {
2435         return vm->is_floppy_disk_accessed();
2436 }
2437 #endif
2438
2439 #ifdef USE_QUICK_DISK
2440 void EMU::open_quick_disk(int drv, const _TCHAR* file_path)
2441 {
2442         if(drv < USE_QUICK_DISK) {
2443                 if(vm->is_quick_disk_inserted(drv)) {
2444                         vm->close_quick_disk(drv);
2445                         // wait 0.5sec
2446                         quick_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2447 #if USE_QUICK_DISK > 1
2448                         out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2449 #else
2450                         out_message(_T("QD: Ejected"));
2451 #endif
2452                 } else if(quick_disk_status[drv].wait_count == 0) {
2453                         vm->open_quick_disk(drv, file_path);
2454 #if USE_QUICK_DISK > 1
2455                         out_message(_T("QD%d: %s"), drv + BASE_QUICK_DISK_NUM, file_path);
2456 #else
2457                         out_message(_T("QD: %s"), file_path);
2458 #endif
2459                 }
2460                 my_tcscpy_s(quick_disk_status[drv].path, _MAX_PATH, file_path);
2461         }
2462 }
2463
2464 void EMU::close_quick_disk(int drv)
2465 {
2466         if(drv < USE_QUICK_DISK) {
2467                 vm->close_quick_disk(drv);
2468                 clear_media_status(&quick_disk_status[drv]);
2469 #if USE_QUICK_DISK > 1
2470                 out_message(_T("QD%d: Ejected"), drv + BASE_QUICK_DISK_NUM);
2471 #else
2472                 out_message(_T("QD: Ejected"));
2473 #endif
2474         }
2475 }
2476
2477 bool EMU::is_quick_disk_inserted(int drv)
2478 {
2479         if(drv < USE_QUICK_DISK) {
2480                 return vm->is_quick_disk_inserted(drv);
2481         } else {
2482                 return false;
2483         }
2484 }
2485
2486 uint32_t EMU::is_quick_disk_accessed()
2487 {
2488         return vm->is_quick_disk_accessed();
2489 }
2490 #endif
2491
2492 #ifdef USE_HARD_DISK
2493 void EMU::open_hard_disk(int drv, const _TCHAR* file_path)
2494 {
2495         if(drv < USE_HARD_DISK) {
2496                 if(vm->is_hard_disk_inserted(drv)) {
2497                         vm->close_hard_disk(drv);
2498                         // wait 0.5sec
2499                         hard_disk_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2500 #if USE_HARD_DISK > 1
2501                         out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
2502 #else
2503                         out_message(_T("HD: Unmounted"));
2504 #endif
2505                 } else if(hard_disk_status[drv].wait_count == 0) {
2506                         vm->open_hard_disk(drv, file_path);
2507 #if USE_HARD_DISK > 1
2508                         out_message(_T("HD%d: %s"), drv + BASE_HARD_DISK_NUM, file_path);
2509 #else
2510                         out_message(_T("HD: %s"), file_path);
2511 #endif
2512                 }
2513                 my_tcscpy_s(hard_disk_status[drv].path, _MAX_PATH, file_path);
2514                 my_tcscpy_s(config.last_hard_disk_path[drv], _MAX_PATH, file_path);
2515         }
2516 }
2517
2518 void EMU::close_hard_disk(int drv)
2519 {
2520         if(drv < USE_HARD_DISK) {
2521                 vm->close_hard_disk(drv);
2522                 clear_media_status(&hard_disk_status[drv]);
2523 #if USE_HARD_DISK > 1
2524                 out_message(_T("HD%d: Unmounted"), drv + BASE_HARD_DISK_NUM);
2525 #else
2526                 out_message(_T("HD: Unmounted"));
2527 #endif
2528                 config.last_hard_disk_path[drv][0] = '\0';
2529         }
2530 }
2531
2532 bool EMU::is_hard_disk_inserted(int drv)
2533 {
2534         if(drv < USE_HARD_DISK) {
2535                 return vm->is_hard_disk_inserted(drv);
2536         } else {
2537                 return false;
2538         }
2539 }
2540
2541 uint32_t EMU::is_hard_disk_accessed()
2542 {
2543         return vm->is_hard_disk_accessed();
2544 }
2545 #endif
2546
2547 #ifdef USE_TAPE
2548 void EMU::play_tape(int drv, const _TCHAR* file_path)
2549 {
2550         if(drv < USE_TAPE) {
2551                 if(vm->is_tape_inserted(drv)) {
2552                         vm->close_tape(drv);
2553                         // wait 0.5sec
2554                         tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2555 #if USE_TAPE > 1
2556                         out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2557 #else
2558                         out_message(_T("CMT: Ejected"));
2559 #endif
2560                 } else if(tape_status[drv].wait_count == 0) {
2561                         vm->play_tape(drv, file_path);
2562 #if USE_TAPE > 1
2563                         out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2564 #else
2565                         out_message(_T("CMT: %s"), file_path);
2566 #endif
2567                 }
2568                 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2569                 tape_status[drv].play = true;
2570         }
2571 }
2572
2573 void EMU::rec_tape(int drv, const _TCHAR* file_path)
2574 {
2575         if(drv < USE_TAPE) {
2576                 if(vm->is_tape_inserted(drv)) {
2577                         vm->close_tape(drv);
2578                         // wait 0.5sec
2579                         tape_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2580 #if USE_TAPE > 1
2581                         out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2582 #else
2583                         out_message(_T("CMT: Ejected"));
2584 #endif
2585                 } else if(tape_status[drv].wait_count == 0) {
2586                         vm->rec_tape(drv, file_path);
2587 #if USE_TAPE > 1
2588                         out_message(_T("CMT%d: %s"), drv + BASE_TAPE_NUM, file_path);
2589 #else
2590                         out_message(_T("CMT: %s"), file_path);
2591 #endif
2592                 }
2593                 my_tcscpy_s(tape_status[drv].path, _MAX_PATH, file_path);
2594                 tape_status[drv].play = false;
2595         }
2596 }
2597
2598 void EMU::close_tape(int drv)
2599 {
2600         if(drv < USE_TAPE) {
2601                 vm->close_tape(drv);
2602                 clear_media_status(&tape_status[drv]);
2603 #if USE_TAPE > 1
2604                 out_message(_T("CMT%d: Ejected"), drv + BASE_TAPE_NUM);
2605 #else
2606                 out_message(_T("CMT: Ejected"));
2607 #endif
2608         }
2609 }
2610
2611 bool EMU::is_tape_inserted(int drv)
2612 {
2613         if(drv < USE_TAPE) {
2614                 return vm->is_tape_inserted(drv);
2615         } else {
2616                 return false;
2617         }
2618 }
2619
2620 bool EMU::is_tape_playing(int drv)
2621 {
2622         if(drv < USE_TAPE) {
2623                 return vm->is_tape_playing(drv);
2624         } else {
2625                 return false;
2626         }
2627 }
2628
2629 bool EMU::is_tape_recording(int drv)
2630 {
2631         if(drv < USE_TAPE) {
2632                 return vm->is_tape_recording(drv);
2633         } else {
2634                 return false;
2635         }
2636 }
2637
2638 int EMU::get_tape_position(int drv)
2639 {
2640         if(drv < USE_TAPE) {
2641                 return vm->get_tape_position(drv);
2642         } else {
2643                 return 0;
2644         }
2645 }
2646
2647 const _TCHAR* EMU::get_tape_message(int drv)
2648 {
2649         if(drv < USE_TAPE) {
2650                 return vm->get_tape_message(drv);
2651         } else {
2652                 return NULL;
2653         }
2654 }
2655
2656 void EMU::push_play(int drv)
2657 {
2658         if(drv < USE_TAPE) {
2659                 vm->push_play(drv);
2660         }
2661 }
2662
2663 void EMU::push_stop(int drv)
2664 {
2665         if(drv < USE_TAPE) {
2666                 vm->push_stop(drv);
2667         }
2668 }
2669
2670 void EMU::push_fast_forward(int drv)
2671 {
2672         if(drv < USE_TAPE) {
2673                 vm->push_fast_forward(drv);
2674         }
2675 }
2676
2677 void EMU::push_fast_rewind(int drv)
2678 {
2679         if(drv < USE_TAPE) {
2680                 vm->push_fast_rewind(drv);
2681         }
2682 }
2683
2684 void EMU::push_apss_forward(int drv)
2685 {
2686         if(drv < USE_TAPE) {
2687                 vm->push_apss_forward(drv);
2688         }
2689 }
2690
2691 void EMU::push_apss_rewind(int drv)
2692 {
2693         if(drv < USE_TAPE) {
2694                 vm->push_apss_rewind(drv);
2695         }
2696 }
2697 #endif
2698
2699 #ifdef USE_COMPACT_DISC
2700 void EMU::open_compact_disc(int drv, const _TCHAR* file_path)
2701 {
2702         if(vm->is_compact_disc_inserted(drv)) {
2703                 vm->close_compact_disc(drv);
2704                 // wait 0.5sec
2705                 compact_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2706 #if USE_COMPACT_DISC > 1
2707                 out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2708 #else
2709                 out_message(_T("CD: Ejected"));
2710 #endif
2711         } else if(compact_disc_status[drv].wait_count == 0) {
2712                 vm->open_compact_disc(drv, file_path);
2713 #if USE_COMPACT_DISC > 1
2714                 out_message(_T("CD%d: %s"), drv + BASE_COMPACT_DISC_NUM, file_path);
2715 #else
2716                 out_message(_T("CD: %s"), file_path);
2717 #endif
2718         }
2719         my_tcscpy_s(compact_disc_status[drv].path, _MAX_PATH, file_path);
2720 }
2721
2722 void EMU::close_compact_disc(int drv)
2723 {
2724         vm->close_compact_disc(drv);
2725         clear_media_status(&compact_disc_status[drv]);
2726 #if USE_COMPACT_DISC > 1
2727         out_message(_T("CD%d: Ejected"), drv + BASE_COMPACT_DISC_NUM);
2728 #else
2729         out_message(_T("CD: Ejected"));
2730 #endif
2731 }
2732
2733 bool EMU::is_compact_disc_inserted(int drv)
2734 {
2735         return vm->is_compact_disc_inserted(drv);
2736 }
2737
2738 uint32_t EMU::is_compact_disc_accessed()
2739 {
2740         return vm->is_compact_disc_accessed();
2741 }
2742 #endif
2743
2744 #ifdef USE_LASER_DISC
2745 void EMU::open_laser_disc(int drv, const _TCHAR* file_path)
2746 {
2747         if(vm->is_laser_disc_inserted(drv)) {
2748                 vm->close_laser_disc(drv);
2749                 // wait 0.5sec
2750                 laser_disc_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2751 #if USE_LASER_DISC > 1
2752                 out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2753 #else
2754                 out_message(_T("LD: Ejected"));
2755 #endif
2756         } else if(laser_disc_status[drv].wait_count == 0) {
2757                 vm->open_laser_disc(drv, file_path);
2758 #if USE_LASER_DISC > 1
2759                 out_message(_T("LD%d: %s"), drv + BASE_LASER_DISC_NUM, file_path);
2760 #else
2761                 out_message(_T("LD: %s"), file_path);
2762 #endif
2763         }
2764         my_tcscpy_s(laser_disc_status[drv].path, _MAX_PATH, file_path);
2765 }
2766
2767 void EMU::close_laser_disc(int drv)
2768 {
2769         vm->close_laser_disc(drv);
2770         clear_media_status(&laser_disc_status[drv]);
2771 #if USE_LASER_DISC > 1
2772         out_message(_T("LD%d: Ejected"), drv + BASE_LASER_DISC_NUM);
2773 #else
2774         out_message(_T("LD: Ejected"));
2775 #endif
2776 }
2777
2778 bool EMU::is_laser_disc_inserted(int drv)
2779 {
2780         return vm->is_laser_disc_inserted(drv);
2781 }
2782
2783 uint32_t EMU::is_laser_disc_accessed()
2784 {
2785         return vm->is_laser_disc_accessed();
2786 }
2787 #endif
2788
2789 #ifdef USE_BINARY_FILE
2790 void EMU::load_binary(int drv, const _TCHAR* file_path)
2791 {
2792         if(drv < USE_BINARY_FILE) {
2793                 if(check_file_extension(file_path, _T(".hex")) && hex2bin(file_path, create_local_path(_T("hex2bin.$$$")))) {
2794                         vm->load_binary(drv, create_local_path(_T("hex2bin.$$$")));
2795                         FILEIO::RemoveFile(create_local_path(_T("hex2bin.$$$")));
2796                 } else {
2797                         vm->load_binary(drv, file_path);
2798                 }
2799 #if USE_BINARY_FILE > 1
2800                 out_message(_T("Load Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2801 #else
2802                 out_message(_T("Load Binary: %s"), file_path);
2803 #endif
2804         }
2805 }
2806
2807 void EMU::save_binary(int drv, const _TCHAR* file_path)
2808 {
2809         if(drv < USE_BINARY_FILE) {
2810                 vm->save_binary(drv, file_path);
2811 #if USE_BINARY_FILE > 1
2812                 out_message(_T("Save Binary%d: %s"), drv + BASE_BINARY_FILE_NUM, file_path);
2813 #else
2814                 out_message(_T("Save Binary: %s"), file_path);
2815 #endif
2816         }
2817 }
2818
2819 #endif
2820 #ifdef USE_BUBBLE
2821 void EMU::open_bubble_casette(int drv, const _TCHAR* file_path, int bank)
2822 {
2823         if(drv < USE_BUBBLE) {
2824                 if(vm->is_bubble_casette_inserted(drv)) {
2825                         vm->close_bubble_casette(drv);
2826                         // wait 0.5sec
2827                         bubble_casette_status[drv].wait_count = (int)(vm->get_frame_rate() / 2);
2828 #if USE_BUBBLE > 1
2829                         out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2830 #else
2831                         out_message(_T("Bubble: Ejected"));
2832 #endif
2833                 } else if(bubble_casette_status[drv].wait_count == 0) {
2834                         vm->open_bubble_casette(drv, file_path, bank);
2835 #if USE_BUBBLE > 1
2836                         out_message(_T("Bubble%d: %s"), drv + BASE_BUBBLE_NUM, file_path);
2837 #else
2838                         out_message(_T("Bubble: %s"), file_path);
2839 #endif
2840                 }
2841                 my_tcscpy_s(bubble_casette_status[drv].path, _MAX_PATH, file_path);
2842                 bubble_casette_status[drv].bank = bank;
2843         }
2844 }
2845
2846 void EMU::close_bubble_casette(int drv)
2847 {
2848         if(drv < USE_BUBBLE) {
2849                 vm->close_bubble_casette(drv);
2850                 clear_media_status(&bubble_casette_status[drv]);
2851 #if USE_BUBBLE > 1
2852                 out_message(_T("Bubble%d: Ejected"), drv + BASE_BUBBLE_NUM);
2853 #else
2854                 out_message(_T("Bubble: Ejected"));
2855 #endif
2856         }
2857 }
2858
2859 bool EMU::is_bubble_casette_inserted(int drv)
2860 {
2861         if(drv < USE_BUBBLE) {
2862                 return vm->is_bubble_casette_inserted(drv);
2863         } else {
2864                 return false;
2865         }
2866 }
2867
2868 bool EMU::is_bubble_casette_protected(int drv)
2869 {
2870         if(drv < USE_BUBBLE) {
2871                 return vm->is_bubble_casette_protected(drv);
2872         } else {
2873                 return false;
2874         }
2875 }
2876
2877 void EMU::is_bubble_casette_protected(int drv, bool flag)
2878 {
2879         if(drv < USE_BUBBLE) {
2880                 vm->is_bubble_casette_protected(drv, flag);
2881                 return;
2882         } else {
2883                 return;
2884         }
2885 }
2886 #endif
2887
2888 #ifdef USE_LED_DEVICE
2889 uint32_t EMU::get_led_status()
2890 {
2891         return vm->get_led_status();
2892 }
2893 #endif
2894
2895
2896 #ifdef USE_SOUND_VOLUME
2897 void EMU::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
2898 {
2899         vm->set_sound_device_volume(ch, decibel_l, decibel_r);
2900 }
2901 #endif
2902
2903 void EMU::update_config()
2904 {
2905         vm->update_config();
2906 }
2907
2908 #ifdef OSD_QT
2909         // New APIs
2910 void EMU::load_sound_file(int id, const _TCHAR *name, int16_t **data, int *dst_size)
2911 {
2912         osd->load_sound_file(id, name, data, dst_size);
2913 }
2914
2915 void EMU::free_sound_file(int id, int16_t **data)
2916 {
2917         osd->free_sound_file(id, data);
2918 }
2919 #endif
2920
2921
2922 // ----------------------------------------------------------------------------
2923 // state
2924 // ----------------------------------------------------------------------------
2925
2926 #ifdef USE_STATE
2927 #define STATE_VERSION   2
2928
2929 void EMU::save_state(const _TCHAR* file_path)
2930 {
2931         FILEIO* fio = new FILEIO();
2932         osd->lock_vm();
2933 #ifdef USE_ZLIB
2934         if(config.compress_state) {
2935                 fio->Gzopen(file_path, FILEIO_WRITE_BINARY);
2936         }
2937 #endif
2938         if(!fio->IsOpened()) {
2939                 fio->Fopen(file_path, FILEIO_WRITE_BINARY);
2940         }
2941         if(fio->IsOpened()) {
2942                 // save state file version
2943                 fio->FputUint32(STATE_VERSION);
2944                 // save config
2945                 process_config_state((void *)fio, false);
2946                 // save inserted medias
2947 #ifdef USE_CART
2948                 fio->Fwrite(&cart_status, sizeof(cart_status), 1);
2949 #endif
2950 #ifdef USE_FLOPPY_DISK
2951                 fio->Fwrite(floppy_disk_status, sizeof(floppy_disk_status), 1);
2952                 fio->Fwrite(d88_file, sizeof(d88_file), 1);
2953 #endif
2954 #ifdef USE_QUICK_DISK
2955                 fio->Fwrite(&quick_disk_status, sizeof(quick_disk_status), 1);
2956 #endif
2957 #ifdef USE_HARD_DISK
2958                 fio->Fwrite(&hard_disk_status, sizeof(hard_disk_status), 1);
2959 #endif
2960 #ifdef USE_TAPE
2961                 fio->Fwrite(&tape_status, sizeof(tape_status), 1);
2962 #endif
2963 #ifdef USE_COMPACT_DISC
2964                 fio->Fwrite(&compact_disc_status, sizeof(compact_disc_status), 1);
2965 #endif
2966 #ifdef USE_LASER_DISC
2967                 fio->Fwrite(&laser_disc_status, sizeof(laser_disc_status), 1);
2968 #endif
2969 #ifdef USE_BUBBLE
2970                 fio->Fwrite(&bubble_casette_status, sizeof(bubble_casette_status), 1);
2971 #endif
2972                 // save vm state
2973                 vm->process_state(fio, false);
2974                 // end of state file
2975                 fio->FputInt32_LE(-1);
2976                 fio->Fclose();
2977         }
2978         osd->unlock_vm();
2979         delete fio;
2980 }
2981
2982 void EMU::load_state(const _TCHAR* file_path)
2983 {
2984         if(FILEIO::IsFileExisting(file_path)) {
2985 #ifdef USE_AUTO_KEY
2986                 stop_auto_key();
2987                 config.romaji_to_kana = false;
2988 #endif
2989                 
2990                 save_state(create_local_path(_T("$temp$.sta")));
2991                 if(!load_state_tmp(file_path)) {
2992                         out_debug_log(_T("failed to load state file\n"));
2993                         load_state_tmp(create_local_path(_T("$temp$.sta")));
2994                 }
2995                 FILEIO::RemoveFile(create_local_path(_T("$temp$.sta")));
2996         }
2997 }
2998
2999 bool EMU::load_state_tmp(const _TCHAR* file_path)
3000 {
3001         bool result = false;
3002         FILEIO* fio = new FILEIO();
3003         osd->lock_vm();
3004 #ifdef USE_ZLIB
3005         if(config.compress_state) {
3006                 fio->Gzopen(file_path, FILEIO_READ_BINARY);
3007         }
3008 #endif
3009         if(!fio->IsOpened()) {
3010                 fio->Fopen(file_path, FILEIO_READ_BINARY);
3011         }
3012         if(fio->IsOpened()) {
3013                 // check state file version
3014                 if(fio->FgetUint32() == STATE_VERSION) {
3015                         // load config
3016                         if(process_config_state((void *)fio, true)) {
3017                                 // load inserted medias
3018 #ifdef USE_CART
3019                                 fio->Fread(&cart_status, sizeof(cart_status), 1);
3020 #endif
3021 #ifdef USE_FLOPPY_DISK
3022                                 fio->Fread(floppy_disk_status, sizeof(floppy_disk_status), 1);
3023                                 fio->Fread(d88_file, sizeof(d88_file), 1);
3024 #endif
3025 #ifdef USE_QUICK_DISK
3026                                 fio->Fread(&quick_disk_status, sizeof(quick_disk_status), 1);
3027 #endif
3028 #ifdef USE_HARD_DISK
3029                                 fio->Fread(&hard_disk_status, sizeof(hard_disk_status), 1);
3030 #endif
3031 #ifdef USE_TAPE
3032                                 fio->Fread(&tape_status, sizeof(tape_status), 1);
3033 #endif
3034 #ifdef USE_COMPACT_DISC
3035                                 fio->Fread(&compact_disc_status, sizeof(compact_disc_status), 1);
3036 #endif
3037 #ifdef USE_LASER_DISC
3038                                 fio->Fread(&laser_disc_status, sizeof(laser_disc_status), 1);
3039 #endif
3040 #ifdef USE_BUBBLE
3041                                 fio->Fread(&bubble_casette_status, sizeof(bubble_casette_status), 1);
3042 #endif
3043                                 // check if virtual machine should be reinitialized
3044                                 bool reinitialize = false;
3045 #ifdef USE_CPU_TYPE
3046                                 reinitialize |= (cpu_type != config.cpu_type);
3047                                 cpu_type = config.cpu_type;
3048 #endif
3049 #ifdef USE_DIPSWITCH
3050                                 reinitialize |= (dipswitch != config.dipswitch);
3051                                 dipswitch = config.dipswitch;
3052 #endif
3053 #ifdef USE_SOUND_TYPE
3054                                 reinitialize |= (sound_type != config.sound_type);
3055                                 sound_type = config.sound_type;
3056 #endif
3057 #ifdef USE_PRINTER_TYPE
3058                                 reinitialize |= (printer_type != config.printer_type);
3059                                 printer_type = config.printer_type;
3060 #endif
3061                                 if(!(0 <= config.sound_frequency && config.sound_frequency < 8)) {
3062                                         config.sound_frequency = 6;     // default: 48KHz
3063                                 }
3064                                 if(!(0 <= config.sound_latency && config.sound_latency < 5)) {
3065                                         config.sound_latency = 1;       // default: 100msec
3066                                 }
3067                                 reinitialize |= (sound_frequency != config.sound_frequency);
3068                                 reinitialize |= (sound_latency != config.sound_latency);
3069                                 sound_frequency = config.sound_frequency;
3070                                 sound_latency = config.sound_latency;
3071                                 
3072                                 if(reinitialize) {
3073                                         // stop sound
3074                                         //osd->lock_vm();
3075                                         // reinitialize virtual machine
3076                                         osd->stop_sound();
3077                                         delete vm;
3078                                         vm = new VM(this);
3079                                         osd->vm = vm;
3080 # if defined(_USE_QT)
3081                                         osd->reset_vm_node();
3082                                         osd->update_keyname_table();
3083 # endif 
3084                                         vm->initialize_sound(sound_rate, sound_samples);
3085 #ifdef USE_SOUND_VOLUME
3086                                         for(int i = 0; i < USE_SOUND_VOLUME; i++) {
3087                                                 vm->set_sound_device_volume(i, config.sound_volume_l[i], config.sound_volume_r[i]);
3088                                         }
3089 #endif
3090                                         restore_media();
3091                                         vm->reset();
3092                                         //osd->unlock_vm();
3093                                 } else {
3094                                         // restore inserted medias
3095                                         restore_media();
3096                                 }
3097                                 // load vm state
3098                                 if(vm->process_state(fio, true)) {
3099                                         // check end of state
3100                                         result = (fio->FgetInt32_LE() == -1);
3101                                 }
3102                         }
3103                 }
3104                 fio->Fclose();
3105         }
3106         osd->unlock_vm();
3107         delete fio;
3108         return result;
3109 }
3110 #endif