OSDN Git Service

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