OSDN Git Service

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