OSDN Git Service

cd677e7c6f626ae82e69ecc1e75ee98999481a4d
[csp-qt/common_source_project-fm7.git] / source / src / qt / common / emu_thread.cpp
1 /*
2         Skelton for retropc emulator
3         Author : Takeda.Toshiya
4     Port to Qt : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2015.11.10
6         History: 2015.11.10 Split from qt_main.cpp
7         Note: This class must be compiled per VM, must not integrate shared units.
8         [ win32 main ] -> [ Qt main ] -> [Emu Thread]
9 */
10
11 #include <QString>
12 #include <QTextCodec>
13 #include <QWaitCondition>
14
15 #include <SDL.h>
16
17 #include "emu_thread.h"
18
19 #include "qt_gldraw.h"
20 #include "agar_logger.h"
21 #include "menu_flags.h"
22
23 // buttons
24 #ifdef MAX_BUTTONS
25 #define MAX_FONT_SIZE 32
26 #endif
27 #define MAX_SKIP_FRAMES 10
28
29 extern USING_FLAGS *using_flags;
30
31 EmuThreadClass::EmuThreadClass(META_MainWindow *rootWindow, EMU *pp_emu, QObject *parent) : QThread(parent) {
32         MainWindow = rootWindow;
33         p_emu = pp_emu;
34         
35         bRunThread = true;
36         prev_skip = false;
37         tick_timer.start();
38         update_fps_time = tick_timer.elapsed();
39         next_time = update_fps_time;
40         total_frames = 0;
41         draw_frames = 0;
42         skip_frames = 0;
43         calc_message = true;
44         mouse_flag = false;
45         //p_emu->set_parent_handler(this);
46         drawCond = new QWaitCondition();
47         mouse_x = 0;
48         mouse_y = 0;
49         if(using_flags->is_use_tape() && !using_flags->is_tape_binary_only()) {
50                 tape_play_flag = false;
51                 tape_rec_flag = false;
52                 tape_pos = 0;
53         }
54
55         if(using_flags->get_use_sound_volume() > 0) {
56                 for(int i = 0; i < using_flags->get_use_sound_volume(); i++) {
57                         bUpdateVolumeReq[i] = true;
58                         volume_avg[i] = (config.sound_volume_l[i] + config.sound_volume_r[i]) / 2;
59                         volume_balance[i] = (config.sound_volume_r[i] - config.sound_volume_l[i]) / 2;
60                 }
61         }
62 };
63
64 EmuThreadClass::~EmuThreadClass() {
65         delete drawCond;
66 };
67
68 void EmuThreadClass::calc_volume_from_balance(int num, int balance)
69 {
70         int level = volume_avg[num];
71         int right;
72         int left;
73         volume_balance[num] = balance;
74         right = level + balance;
75         left  = level - balance;
76         config.sound_volume_l[num] = left;      
77         config.sound_volume_r[num] = right;
78 }
79
80 void EmuThreadClass::calc_volume_from_level(int num, int level)
81 {
82         int balance = volume_balance[num];
83         int right,left;
84         volume_avg[num] = level;
85         right = level + balance;
86         left  = level - balance;
87         config.sound_volume_l[num] = left;      
88         config.sound_volume_r[num] = right;
89 }
90
91 int EmuThreadClass::get_interval(void)
92 {
93         static int accum = 0;
94         accum += p_emu->get_frame_interval();
95         int interval = accum >> 10;
96         accum -= interval << 10;
97         return interval;
98 }
99
100 void EmuThreadClass::doExit(void)
101 {
102         int status;
103         bRunThread = false;
104 }
105
106 void EmuThreadClass::moved_mouse(int x, int y)
107 {
108         mouse_x = x;
109         mouse_y = y;
110 #if defined(USE_MOUSE)   
111         p_emu->set_mouse_pointer(x, y);
112 #endif   
113 }
114
115 void EmuThreadClass::button_pressed_mouse(Qt::MouseButton button)
116 {
117         if(using_flags->is_use_mouse()) {
118 #if defined(USE_MOUSE)   
119                 int stat = p_emu->get_mouse_button();
120                 bool flag = p_emu->is_mouse_enabled();
121                 switch(button) {
122                 case Qt::LeftButton:
123                         stat |= 0x01;
124                         break;
125                 case Qt::RightButton:
126                         stat |= 0x02;
127                         break;
128                 case Qt::MiddleButton:
129                         flag = !flag;
130                         emit sig_mouse_enable(flag);
131                         break;
132                 }
133                 p_emu->set_mouse_button(stat);
134 #endif     
135         } else {                
136                 if(using_flags->get_max_button() > 0) {
137                         button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
138                         if(vm_buttons_d == NULL) return;
139                         switch(button) {
140                         case Qt::LeftButton:
141                         case Qt::RightButton:
142                                 for(int i = 0; i < using_flags->get_max_button(); i++) {
143                                         if((mouse_x >= vm_buttons_d[i].x) &&
144                                            (mouse_x < (vm_buttons_d[i].x + vm_buttons_d[i].width))) {
145                                                 if((mouse_y >= vm_buttons_d[i].y) &&
146                                                    (mouse_y < (vm_buttons_d[i].y + vm_buttons_d[i].height))) {
147                                                         if(vm_buttons_d[i].code != 0x00) {
148                                                                 p_emu->key_down(vm_buttons_d[i].code, false);
149                                                         } else {
150                                                                 bResetReq = true;
151                                                         }
152                                                 }
153                                         }
154                                 }
155                                 break;
156                         }
157                 }
158         }
159 }
160
161 void EmuThreadClass::button_released_mouse(Qt::MouseButton button)
162 {
163         if(using_flags->is_use_mouse()) {
164 #if defined(USE_MOUSE)   
165                 int stat = p_emu->get_mouse_button();
166                 switch(button) {
167                 case Qt::LeftButton:
168                         stat &= 0x7ffffffe;
169                         break;
170                 case Qt::RightButton:
171                         stat &= 0x7ffffffd;
172                         break;
173                 case Qt::MiddleButton:
174                         //emit sig_mouse_enable(false);
175                         break;
176                 }
177                 p_emu->set_mouse_button(stat);
178 #endif
179         } else {
180                 if(using_flags->get_max_button() > 0) {
181                         button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
182                         if(vm_buttons_d == NULL) return;
183                         
184                         switch(button) {
185                         case Qt::LeftButton:
186                         case Qt::RightButton:
187                                 for(int i = 0; i < using_flags->get_max_button(); i++) {
188                                         if((mouse_x >= vm_buttons_d[i].x) &&
189                                            (mouse_x < (vm_buttons_d[i].x + vm_buttons_d[i].width))) {
190                                                 if((mouse_y >= vm_buttons_d[i].y) &&
191                                                    (mouse_y < (vm_buttons_d[i].y + vm_buttons_d[i].height))) {
192                                                         if(vm_buttons_d[i].code != 0x00) {
193                                                                 p_emu->key_up(vm_buttons_d[i].code);
194                                                         }
195                                                 }
196                                         }
197                                 }
198                                 break;
199                         }
200                 }
201         }
202 }
203
204 void EmuThreadClass::do_key_down(uint32_t vk, uint32_t mod, bool repeat)
205 {
206 //      emu->lock_vm();
207         p_emu->key_modifiers(mod);
208         if(vk != 0) {
209                 p_emu->key_down(vk, repeat);
210         }
211 //      emu->unlock_vm();
212 }
213
214 void EmuThreadClass::do_key_up(uint32_t vk, uint32_t mod)
215 {
216 //      emu->lock_vm();
217         p_emu->key_modifiers(mod);
218         if(vk != 0) {
219                 p_emu->key_up(vk);
220         }
221 //      emu->unlock_vm();
222 }
223
224
225 void EmuThreadClass::set_tape_play(bool flag)
226 {
227         tape_play_flag = flag;
228 }
229
230 EmuThreadClass *EmuThreadClass::currentHandler()
231 {
232         return this;
233 }
234
235 void EmuThreadClass::resize_screen(int screen_width, int screen_height, int stretched_width, int stretched_height)
236 {
237         //emit sig_resize_uibar(stretched_width, stretched_height);
238         emit sig_resize_screen(screen_width, screen_height);
239 }
240
241 const int auto_key_table_base[][2] = {
242         // 0x100: shift
243         // 0x200: kana
244         // 0x400: alphabet
245         // 0x800: ALPHABET
246         {0x0a,  0x000 | 0x0d},  // Enter(Unix)
247         {0x0d,  0x000 | 0x0d},  // Enter
248         {0x20,  0x000 | 0x20},  // ' '
249
250         {0x21,  0x100 | 0x31},  // '!'
251         {0x22,  0x100 | 0x32},  // '"'
252         {0x23,  0x100 | 0x33},  // '#'
253         {0x24,  0x100 | 0x34},  // '$'
254         {0x25,  0x100 | 0x35},  // '%'
255         {0x26,  0x100 | 0x36},  // '&'
256         {0x27,  0x100 | 0x37},  // '''
257         {0x28,  0x100 | 0x38},  // '('
258         {0x29,  0x100 | 0x39},  // ')'
259         {0x2a,  0x100 | 0xba},  // '*'
260         {0x2b,  0x100 | 0xbb},  // '+'
261         {0x2c,  0x000 | 0xbc},  // ','
262         {0x2d,  0x000 | 0xbd},  // '-'
263         {0x2e,  0x000 | 0xbe},  // '.'
264         {0x2f,  0x000 | 0xbf},  // '/'
265
266         {0x30,  0x000 | 0x30},  // '0'
267         {0x31,  0x000 | 0x31},  // '1'
268         {0x32,  0x000 | 0x32},  // '2'
269         {0x33,  0x000 | 0x33},  // '3'
270         {0x34,  0x000 | 0x34},  // '4'
271         {0x35,  0x000 | 0x35},  // '5'
272         {0x36,  0x000 | 0x36},  // '6'
273         {0x37,  0x000 | 0x37},  // '7'
274         {0x38,  0x000 | 0x38},  // '8'
275         {0x39,  0x000 | 0x39},  // '9'
276
277         {0x3a,  0x000 | 0xba},  // ':'
278         {0x3b,  0x000 | 0xbb},  // ';'
279         {0x3c,  0x100 | 0xbc},  // '<'
280         {0x3d,  0x100 | 0xbd},  // '='
281         {0x3e,  0x100 | 0xbe},  // '>'
282         {0x3f,  0x100 | 0xbf},  // '?'
283         {0x40,  0x000 | 0xc0},  // '@'
284
285         {0x41,  0x400 | 0x41},  // 'A'
286         {0x42,  0x400 | 0x42},  // 'B'
287         {0x43,  0x400 | 0x43},  // 'C'
288         {0x44,  0x400 | 0x44},  // 'D'
289         {0x45,  0x400 | 0x45},  // 'E'
290         {0x46,  0x400 | 0x46},  // 'F'
291         {0x47,  0x400 | 0x47},  // 'G'
292         {0x48,  0x400 | 0x48},  // 'H'
293         {0x49,  0x400 | 0x49},  // 'I'
294         {0x4a,  0x400 | 0x4a},  // 'J'
295         {0x4b,  0x400 | 0x4b},  // 'K'
296         {0x4c,  0x400 | 0x4c},  // 'L'
297         {0x4d,  0x400 | 0x4d},  // 'M'
298         {0x4e,  0x400 | 0x4e},  // 'N'
299         {0x4f,  0x400 | 0x4f},  // 'O'
300         {0x50,  0x400 | 0x50},  // 'P'
301         {0x51,  0x400 | 0x51},  // 'Q'
302         {0x52,  0x400 | 0x52},  // 'R'
303         {0x53,  0x400 | 0x53},  // 'S'
304         {0x54,  0x400 | 0x54},  // 'T'
305         {0x55,  0x400 | 0x55},  // 'U'
306         {0x56,  0x400 | 0x56},  // 'V'
307         {0x57,  0x400 | 0x57},  // 'W'
308         {0x58,  0x400 | 0x58},  // 'X'
309         {0x59,  0x400 | 0x59},  // 'Y'
310         {0x5a,  0x400 | 0x5a},  // 'Z'
311
312         {0x5b,  0x000 | 0xdb},  // '['
313         {0x5c,  0x000 | 0xdc},  // '\'
314         {0x5d,  0x000 | 0xdd},  // ']'
315         {0x5e,  0x000 | 0xde},  // '^'
316         {0x5f,  0x100 | 0xe2},  // '_'
317         {0x60,  0x100 | 0xc0},  // '`'
318
319         {0x61,  0x800 | 0x41},  // 'a'
320         {0x62,  0x800 | 0x42},  // 'b'
321         {0x63,  0x800 | 0x43},  // 'c'
322         {0x64,  0x800 | 0x44},  // 'd'
323         {0x65,  0x800 | 0x45},  // 'e'
324         {0x66,  0x800 | 0x46},  // 'f'
325         {0x67,  0x800 | 0x47},  // 'g'
326         {0x68,  0x800 | 0x48},  // 'h'
327         {0x69,  0x800 | 0x49},  // 'i'
328         {0x6a,  0x800 | 0x4a},  // 'j'
329         {0x6b,  0x800 | 0x4b},  // 'k'
330         {0x6c,  0x800 | 0x4c},  // 'l'
331         {0x6d,  0x800 | 0x4d},  // 'm'
332         {0x6e,  0x800 | 0x4e},  // 'n'
333         {0x6f,  0x800 | 0x4f},  // 'o'
334         {0x70,  0x800 | 0x50},  // 'p'
335         {0x71,  0x800 | 0x51},  // 'q'
336         {0x72,  0x800 | 0x52},  // 'r'
337         {0x73,  0x800 | 0x53},  // 's'
338         {0x74,  0x800 | 0x54},  // 't'
339         {0x75,  0x800 | 0x55},  // 'u'
340         {0x76,  0x800 | 0x56},  // 'v'
341         {0x77,  0x800 | 0x57},  // 'w'
342         {0x78,  0x800 | 0x58},  // 'x'
343         {0x79,  0x800 | 0x59},  // 'y'
344         {0x7a,  0x800 | 0x5a},  // 'z'
345
346         {0x7b,  0x100 | 0xdb},  // '{'
347         {0x7c,  0x100 | 0xdc},  // '|'
348         {0x7d,  0x100 | 0xdd},  // '}'
349         {0x7e,  0x100 | 0xde},  // '~'
350
351         {0xa1,  0x300 | 0xbe},  // '
352         {0xa2,  0x300 | 0xdb},  // '
353         {0xa3,  0x300 | 0xdd},  // '
354         {0xa4,  0x300 | 0xbc},  // '
355         {0xa5,  0x300 | 0xbf},  // '・'
356         {0xa6,  0x300 | 0x30},  // 'ヲ'
357         {0xa7,  0x300 | 0x33},  // 'ァ'
358         {0xa8,  0x300 | 0x45},  // 'ィ'
359         {0xa9,  0x300 | 0x34},  // 'ゥ'
360         {0xaa,  0x300 | 0x35},  // 'ェ'
361         {0xab,  0x300 | 0x36},  // 'ォ'
362         {0xac,  0x300 | 0x37},  // 'ャ'
363         {0xad,  0x300 | 0x38},  // 'ュ'
364         {0xae,  0x300 | 0x39},  // 'ョ'
365         {0xaf,  0x300 | 0x5a},  // 'ッ'
366         {0xb0,  0x200 | 0xdc},  // 'ー'
367         {0xb1,  0x200 | 0x33},  // 'ア'
368         {0xb2,  0x200 | 0x45},  // 'イ'
369         {0xb3,  0x200 | 0x34},  // 'ウ'
370         {0xb4,  0x200 | 0x35},  // 'エ'
371         {0xb5,  0x200 | 0x36},  // 'オ'
372         {0xb6,  0x200 | 0x54},  // 'カ'
373         {0xb7,  0x200 | 0x47},  // 'キ'
374         {0xb8,  0x200 | 0x48},  // 'ク'
375         {0xb9,  0x200 | 0xba},  // 'ケ'
376         {0xba,  0x200 | 0x42},  // 'コ'
377         {0xbb,  0x200 | 0x58},  // 'サ'
378         {0xbc,  0x200 | 0x44},  // 'シ'
379         {0xbd,  0x200 | 0x52},  // 'ス'
380         {0xbe,  0x200 | 0x50},  // 'セ'
381         {0xbf,  0x200 | 0x43},  // 'ソ'
382         {0xc0,  0x200 | 0x51},  // 'タ'
383         {0xc1,  0x200 | 0x41},  // 'チ'
384         {0xc2,  0x200 | 0x5a},  // 'ツ'
385         {0xc3,  0x200 | 0x57},  // 'テ'
386         {0xc4,  0x200 | 0x53},  // 'ト'
387         {0xc5,  0x200 | 0x55},  // 'ナ'
388         {0xc6,  0x200 | 0x49},  // 'ニ'
389         {0xc7,  0x200 | 0x31},  // 'ヌ'
390         {0xc8,  0x200 | 0xbc},  // 'ネ'
391         {0xc9,  0x200 | 0x4b},  // 'ノ'
392         {0xca,  0x200 | 0x46},  // 'ハ'
393         {0xcb,  0x200 | 0x56},  // 'ヒ'
394         {0xcc,  0x200 | 0x32},  // 'フ'
395         {0xcd,  0x200 | 0xde},  // 'ヘ'
396         {0xce,  0x200 | 0xbd},  // 'ホ'
397         {0xcf,  0x200 | 0x4a},  // 'マ'
398         {0xd0,  0x200 | 0x4e},  // 'ミ'
399         {0xd1,  0x200 | 0xdd},  // 'ム'
400         {0xd2,  0x200 | 0xbf},  // 'メ'
401         {0xd3,  0x200 | 0x4d},  // 'モ'
402         {0xd4,  0x200 | 0x37},  // 'ヤ'
403         {0xd5,  0x200 | 0x38},  // 'ユ'
404         {0xd6,  0x200 | 0x39},  // 'ヨ'
405         {0xd7,  0x200 | 0x4f},  // 'ラ'
406         {0xd8,  0x200 | 0x4c},  // 'リ'
407         {0xd9,  0x200 | 0xbe},  // 'ル'
408         {0xda,  0x200 | 0xbb},  // 'レ'
409         {0xdb,  0x200 | 0xe2},  // 'ロ'
410         {0xdc,  0x200 | 0x30},  // 'ワ'
411         {0xdd,  0x200 | 0x59},  // 'ン'
412         {0xde,  0x200 | 0xc0},  // '゙'
413         {0xdf,  0x200 | 0xdb},  // '゚'
414         {-1, -1},
415 };
416
417 const int auto_key_table_base_us[][2] = {
418         // 0x100: shift
419         // 0x200: kana
420         // 0x400: alphabet
421         // 0x800: ALPHABET
422         {0x0a,  0x000 | 0x0d},  // Enter(Unix)
423         {0x0d,  0x000 | 0x0d},  // Enter
424         {0x20,  0x000 | 0x20},  // ' '
425         {0x21,  0x100 | 0x31},  // '!'
426         {0x22,  0x100 | 0xba},  // '"'
427         {0x23,  0x100 | 0x33},  // '#'
428         {0x24,  0x100 | 0x34},  // '$'
429         {0x25,  0x100 | 0x35},  // '%'
430         {0x26,  0x100 | 0x37},  // '&'
431         {0x27,  0x000 | 0xba},  // '''
432         {0x28,  0x100 | 0x39},  // '('
433         {0x29,  0x100 | 0x30},  // ')'
434         {0x2a,  0x100 | 0x38},  // '*'
435         {0x2b,  0x100 | 0xde},  // '+'
436         {0x2c,  0x000 | 0xbc},  // ','
437         {0x2d,  0x000 | 0xbd},  // '-'
438         {0x2e,  0x000 | 0xbe},  // '.'
439         {0x2f,  0x000 | 0xbf},  // '/'
440         
441         {0x30,  0x000 | 0x30},  // '0'
442         {0x31,  0x000 | 0x31},  // '1'
443         {0x32,  0x000 | 0x32},  // '2'
444         {0x33,  0x000 | 0x33},  // '3'
445         {0x34,  0x000 | 0x34},  // '4'
446         {0x35,  0x000 | 0x35},  // '5'
447         {0x36,  0x000 | 0x36},  // '6'
448         {0x37,  0x000 | 0x37},  // '7'
449         {0x38,  0x000 | 0x38},  // '8'
450         {0x39,  0x000 | 0x39},  // '9'
451         
452         {0x3a,  0x100 | 0xbb},  // ':'
453         {0x3b,  0x000 | 0xbb},  // ';'
454         {0x3c,  0x100 | 0xbc},  // '<'
455         {0x3d,  0x000 | 0xde},  // '='
456         {0x3e,  0x100 | 0xbe},  // '>'
457         {0x3f,  0x100 | 0xbf},  // '?'
458         {0x40,  0x100 | 0x32},  // '@'
459         
460         {0x41,  0x400 | 0x41},  // 'A'
461         {0x42,  0x400 | 0x42},  // 'B'
462         {0x43,  0x400 | 0x43},  // 'C'
463         {0x44,  0x400 | 0x44},  // 'D'
464         {0x45,  0x400 | 0x45},  // 'E'
465         {0x46,  0x400 | 0x46},  // 'F'
466         {0x47,  0x400 | 0x47},  // 'G'
467         {0x48,  0x400 | 0x48},  // 'H'
468         {0x49,  0x400 | 0x49},  // 'I'
469         {0x4a,  0x400 | 0x4a},  // 'J'
470         {0x4b,  0x400 | 0x4b},  // 'K'
471         {0x4c,  0x400 | 0x4c},  // 'L'
472         {0x4d,  0x400 | 0x4d},  // 'M'
473         {0x4e,  0x400 | 0x4e},  // 'N'
474         {0x4f,  0x400 | 0x4f},  // 'O'
475         {0x50,  0x400 | 0x50},  // 'P'
476         {0x51,  0x400 | 0x51},  // 'Q'
477         {0x52,  0x400 | 0x52},  // 'R'
478         {0x53,  0x400 | 0x53},  // 'S'
479         {0x54,  0x400 | 0x54},  // 'T'
480         {0x55,  0x400 | 0x55},  // 'U'
481         {0x56,  0x400 | 0x56},  // 'V'
482         {0x57,  0x400 | 0x57},  // 'W'
483         {0x58,  0x400 | 0x58},  // 'X'
484         {0x59,  0x400 | 0x59},  // 'Y'
485         {0x5a,  0x400 | 0x5a},  // 'Z'
486
487         {0x5b,  0x000 | 0xc0},  // '['
488         {0x5c,  0x000 | 0xe2},  // '\'
489         {0x5d,  0x000 | 0xdb},  // ']'
490         {0x5e,  0x100 | 0x36},  // '^'
491         {0x5f,  0x100 | 0xbd},  // '_'
492         {0x60,  0x000 | 0xdd},  // '`'
493         
494         {0x61,  0x800 | 0x41},  // 'a'
495         {0x62,  0x800 | 0x42},  // 'b'
496         {0x63,  0x800 | 0x43},  // 'c'
497         {0x64,  0x800 | 0x44},  // 'd'
498         {0x65,  0x800 | 0x45},  // 'e'
499         {0x66,  0x800 | 0x46},  // 'f'
500         {0x67,  0x800 | 0x47},  // 'g'
501         {0x68,  0x800 | 0x48},  // 'h'
502         {0x69,  0x800 | 0x49},  // 'i'
503         {0x6a,  0x800 | 0x4a},  // 'j'
504         {0x6b,  0x800 | 0x4b},  // 'k'
505         {0x6c,  0x800 | 0x4c},  // 'l'
506         {0x6d,  0x800 | 0x4d},  // 'm'
507         {0x6e,  0x800 | 0x4e},  // 'n'
508         {0x6f,  0x800 | 0x4f},  // 'o'
509         {0x70,  0x800 | 0x50},  // 'p'
510         {0x71,  0x800 | 0x51},  // 'q'
511         {0x72,  0x800 | 0x52},  // 'r'
512         {0x73,  0x800 | 0x53},  // 's'
513         {0x74,  0x800 | 0x54},  // 't'
514         {0x75,  0x800 | 0x55},  // 'u'
515         {0x76,  0x800 | 0x56},  // 'v'
516         {0x77,  0x800 | 0x57},  // 'w'
517         {0x78,  0x800 | 0x58},  // 'x'
518         {0x79,  0x800 | 0x59},  // 'y'
519         {0x7a,  0x800 | 0x5a},  // 'z'
520
521         {0x7b,  0x100 | 0xc0},  // '{'
522         {0x7c,  0x100 | 0xe2},  // '|'
523         {0x7d,  0x100 | 0xdb},  // '}'
524         {0x7e,  0x100 | 0xdd},  // '~'
525
526         {0xa1,  0x300 | 0xbe},  // '
527         {0xa2,  0x300 | 0xdb},  // '
528         {0xa3,  0x300 | 0xdd},  // '
529         {0xa4,  0x300 | 0xbc},  // '
530         {0xa5,  0x300 | 0xbf},  // '・'
531         {0xa6,  0x300 | 0x30},  // 'ヲ'
532         {0xa7,  0x300 | 0x33},  // 'ァ'
533         {0xa8,  0x300 | 0x45},  // 'ィ'
534         {0xa9,  0x300 | 0x34},  // 'ゥ'
535         {0xaa,  0x300 | 0x35},  // 'ェ'
536         {0xab,  0x300 | 0x36},  // 'ォ'
537         {0xac,  0x300 | 0x37},  // 'ャ'
538         {0xad,  0x300 | 0x38},  // 'ュ'
539         {0xae,  0x300 | 0x39},  // 'ョ'
540         {0xaf,  0x300 | 0x5a},  // 'ッ'
541         {0xb0,  0x200 | 0xdc},  // 'ー'
542         {0xb1,  0x200 | 0x33},  // 'ア'
543         {0xb2,  0x200 | 0x45},  // 'イ'
544         {0xb3,  0x200 | 0x34},  // 'ウ'
545         {0xb4,  0x200 | 0x35},  // 'エ'
546         {0xb5,  0x200 | 0x36},  // 'オ'
547         {0xb6,  0x200 | 0x54},  // 'カ'
548         {0xb7,  0x200 | 0x47},  // 'キ'
549         {0xb8,  0x200 | 0x48},  // 'ク'
550         {0xb9,  0x200 | 0xba},  // 'ケ'
551         {0xba,  0x200 | 0x42},  // 'コ'
552         {0xbb,  0x200 | 0x58},  // 'サ'
553         {0xbc,  0x200 | 0x44},  // 'シ'
554         {0xbd,  0x200 | 0x52},  // 'ス'
555         {0xbe,  0x200 | 0x50},  // 'セ'
556         {0xbf,  0x200 | 0x43},  // 'ソ'
557         {0xc0,  0x200 | 0x51},  // 'タ'
558         {0xc1,  0x200 | 0x41},  // 'チ'
559         {0xc2,  0x200 | 0x5a},  // 'ツ'
560         {0xc3,  0x200 | 0x57},  // 'テ'
561         {0xc4,  0x200 | 0x53},  // 'ト'
562         {0xc5,  0x200 | 0x55},  // 'ナ'
563         {0xc6,  0x200 | 0x49},  // 'ニ'
564         {0xc7,  0x200 | 0x31},  // 'ヌ'
565         {0xc8,  0x200 | 0xbc},  // 'ネ'
566         {0xc9,  0x200 | 0x4b},  // 'ノ'
567         {0xca,  0x200 | 0x46},  // 'ハ'
568         {0xcb,  0x200 | 0x56},  // 'ヒ'
569         {0xcc,  0x200 | 0x32},  // 'フ'
570         {0xcd,  0x200 | 0xde},  // 'ヘ'
571         {0xce,  0x200 | 0xbd},  // 'ホ'
572         {0xcf,  0x200 | 0x4a},  // 'マ'
573         {0xd0,  0x200 | 0x4e},  // 'ミ'
574         {0xd1,  0x200 | 0xdd},  // 'ム'
575         {0xd2,  0x200 | 0xbf},  // 'メ'
576         {0xd3,  0x200 | 0x4d},  // 'モ'
577         {0xd4,  0x200 | 0x37},  // 'ヤ'
578         {0xd5,  0x200 | 0x38},  // 'ユ'
579         {0xd6,  0x200 | 0x39},  // 'ヨ'
580         {0xd7,  0x200 | 0x4f},  // 'ラ'
581         {0xd8,  0x200 | 0x4c},  // 'リ'
582         {0xd9,  0x200 | 0xbe},  // 'ル'
583         {0xda,  0x200 | 0xbb},  // 'レ'
584         {0xdb,  0x200 | 0xe2},  // 'ロ'
585         {0xdc,  0x200 | 0x30},  // 'ワ'
586         {0xdd,  0x200 | 0x59},  // 'ン'
587         {0xde,  0x200 | 0xc0},  // '゙'
588         {0xdf,  0x200 | 0xdb},  // '゚'
589         {-1, -1},
590 };
591
592 void EmuThreadClass::do_start_auto_key(QString ctext)
593 {
594 #ifdef USE_AUTO_KEY
595         if(using_flags->is_use_auto_key()) {
596                 QTextCodec *codec = QTextCodec::codecForName("Shift-Jis");
597                 QByteArray array;
598                 clipBoardText = ctext;
599                 array = codec->fromUnicode(clipBoardText);
600                 if(clipBoardText.size() > 0) {
601                         static int auto_key_table[256];
602                         static bool initialized = false;
603                         if(!initialized) {
604                                 memset(auto_key_table, 0, sizeof(auto_key_table));
605                                 if(using_flags->is_use_auto_key_us()) {
606                                         for(int i = 0;; i++) {
607                                                 if(auto_key_table_base_us[i][0] == -1) {
608                                                         break;
609                                                 }
610                                                 auto_key_table[auto_key_table_base_us[i][0]] = auto_key_table_base_us[i][1];
611                                         }
612                                 } else {
613                                         for(int i = 0;; i++) {
614                                                 if(auto_key_table_base[i][0] == -1) {
615                                                         break;
616                                                 }
617                                                 auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
618                                         }
619                                 }
620                                 if(using_flags->is_use_vm_auto_key_table()) {
621                                         if(using_flags->is_use_auto_key_us()) {
622                                                 for(int i = 0;; i++) {
623                                                         if(auto_key_table_base_us[i][0] == -1) {
624                                                                 break;
625                                                         }
626                                                         auto_key_table[auto_key_table_base_us[i][0]] = auto_key_table_base_us[i][1];
627                                                 }
628                                         } else {
629                                                 for(int i = 0;; i++) {
630                                                         if(auto_key_table_base[i][0] == -1) {
631                                                                 break;
632                                                         }
633                                                         auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
634                                                 }
635                                         }
636                                 }
637                                 initialized = true;
638                         }
639                         
640                         FIFO* auto_key_buffer = emu->get_auto_key_buffer();
641                         auto_key_buffer->clear();
642                         
643                         int size = strlen(array.constData()), prev_kana = 0;
644                         const char *buf = (char *)(array.constData());
645                         
646                         for(int i = 0; i < size; i++) {
647                                 int code = buf[i] & 0xff;
648                                 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
649                                         i++;    // kanji ?
650                                         continue;
651                                 }
652                                 // Effect [Enter] even Unix etc.(0x0a should not be ignored). 
653                                 //else if(code == 0xa) { 
654                                 //continue;     // cr-lf
655                                 //}
656                                 if((code = auto_key_table[code]) != 0) {
657                                         int kana = code & 0x200;
658                                         if(prev_kana != kana) {
659                                                 auto_key_buffer->write(0xf2);
660                                         }
661                                         prev_kana = kana;
662                                         if(using_flags->is_use_auto_key_no_caps()) {
663                                                 if((code & 0x100) && !(code & (0x400 | 0x800))) {
664                                                         auto_key_buffer->write((code & 0xff) | 0x100);
665                                                 } else {
666                                                         auto_key_buffer->write(code & 0xff);
667                                                 }
668                                         } else if(using_flags->is_use_auto_key_caps()) {
669                                                 if(code & (0x100 | 0x800)) {
670                                                         auto_key_buffer->write((code & 0xff) | 0x100);
671                                                 } else {
672                                                         auto_key_buffer->write(code & 0xff);
673                                                 }
674                                         } else if(code & (0x100 | 0x400)) {
675                                                 auto_key_buffer->write((code & 0xff) | 0x100);
676                                         } else {
677                                                 auto_key_buffer->write(code & 0xff);
678                                         }
679                                 }
680                         }
681                         
682                         if(prev_kana) {
683                                 auto_key_buffer->write(0xf2);
684                         }
685                         p_emu->stop_auto_key();
686                         p_emu->start_auto_key();
687                 }
688         }
689         //clipBoardText.clear();
690 #endif  
691 }
692
693 void EmuThreadClass::do_stop_auto_key(void)
694 {
695         //AGAR_DebugLog(AGAR_LOG_DEBUG, "AutoKey: stop\n");
696 #if defined(USE_AUTO_KEY)   
697         p_emu->stop_auto_key();
698 #endif   
699 }
700
701 void EmuThreadClass::do_write_protect_disk(int drv, bool flag)
702 {
703 #if defined(USE_FD1) || defined(USE_FD2) || defined(USE_FD3) || defined(USE_FD4) || \
704     defined(USE_FD5) || defined(USE_FD6) || defined(USE_FD7) || defined(USE_FD8)
705         p_emu->is_floppy_disk_protected(drv, flag);
706 #endif  
707 }
708
709 void EmuThreadClass::do_close_disk(int drv)
710 {
711 #if defined(USE_FD1) || defined(USE_FD2) || defined(USE_FD3) || defined(USE_FD4) || \
712     defined(USE_FD5) || defined(USE_FD6) || defined(USE_FD7) || defined(USE_FD8)
713         p_emu->close_floppy_disk(drv);
714         p_emu->d88_file[drv].bank_num = 0;
715         p_emu->d88_file[drv].cur_bank = -1;
716 #endif  
717 }
718
719 void EmuThreadClass::do_open_disk(int drv, QString path, int bank)
720 {
721 #if defined(USE_FD1) || defined(USE_FD2) || defined(USE_FD3) || defined(USE_FD4) || \
722     defined(USE_FD5) || defined(USE_FD6) || defined(USE_FD7) || defined(USE_FD8)
723         QByteArray localPath = path.toLocal8Bit();
724    
725         p_emu->d88_file[drv].bank_num = 0;
726         p_emu->d88_file[drv].cur_bank = -1;
727         
728         if(check_file_extension(localPath.constData(), ".d88") || check_file_extension(localPath.constData(), ".d77")) {
729                 
730                 FILEIO *fio = new FILEIO();
731                 if(fio->Fopen(localPath.constData(), FILEIO_READ_BINARY)) {
732                         try {
733                                 fio->Fseek(0, FILEIO_SEEK_END);
734                                 int file_size = fio->Ftell(), file_offset = 0;
735                                 while(file_offset + 0x2b0 <= file_size && p_emu->d88_file[drv].bank_num < MAX_D88_BANKS) {
736                                         fio->Fseek(file_offset, FILEIO_SEEK_SET);
737                                         char tmp[18];
738                                         memset(tmp, 0x00, sizeof(tmp));
739                                         fio->Fread(tmp, 17, 1);
740                                         memset(p_emu->d88_file[drv].disk_name[p_emu->d88_file[drv].bank_num], 0x00, 128);
741                                         if(strlen(tmp) > 0) Convert_CP932_to_UTF8(p_emu->d88_file[drv].disk_name[p_emu->d88_file[drv].bank_num], tmp, 127, 17);
742                                         
743                                         fio->Fseek(file_offset + 0x1c, FILEIO_SEEK_SET);
744                                         file_offset += fio->FgetUint32_LE();
745                                         p_emu->d88_file[drv].bank_num++;
746                                 }
747                                 strcpy(emu->d88_file[drv].path, path.toUtf8().constData());
748                                 if(bank >= p_emu->d88_file[drv].bank_num) bank = p_emu->d88_file[drv].bank_num - 1;
749                                 if(bank < 0) bank = 0;
750                                 p_emu->d88_file[drv].cur_bank = bank;
751                         }
752                         catch(...) {
753                                 bank = 0;
754                                 p_emu->d88_file[drv].bank_num = 0;
755                         }
756                         fio->Fclose();
757                 }
758                 delete fio;
759         } else {
760            bank = 0;
761         }
762         p_emu->open_floppy_disk(drv, localPath.constData(), bank);
763         emit sig_update_recent_disk(drv);
764 #endif  
765 }
766 void EmuThreadClass::do_play_tape(QString name)
767 {
768 #if defined(USE_TAPE)
769         p_emu->play_tape(name.toLocal8Bit().constData());
770 #endif
771 }
772
773 void EmuThreadClass::do_rec_tape(QString name)
774 {
775 #if defined(USE_TAPE)
776         p_emu->rec_tape(name.toLocal8Bit().constData());
777 #endif
778 }
779
780 void EmuThreadClass::do_close_tape(void)
781 {
782 #if defined(USE_TAPE)
783         p_emu->close_tape();
784 #endif
785 }
786
787 void EmuThreadClass::do_cmt_push_play(void)
788 {
789 #if defined(USE_TAPE_BUTTON)
790         p_emu->push_play();
791 #endif
792 }
793
794 void EmuThreadClass::do_cmt_push_stop(void)
795 {
796 #if defined(USE_TAPE_BUTTON)
797         p_emu->push_stop();
798 #endif
799 }
800
801 void EmuThreadClass::do_cmt_push_fast_forward(void)
802 {
803 #if defined(USE_TAPE_BUTTON)
804         p_emu->push_fast_forward();
805 #endif
806 }
807
808 void EmuThreadClass::do_cmt_push_fast_rewind(void)
809 {
810 #if defined(USE_TAPE_BUTTON)
811         p_emu->push_fast_rewind();
812 #endif
813 }
814
815 void EmuThreadClass::do_cmt_push_apss_forward(void)
816 {
817 #if defined(USE_TAPE_BUTTON)
818         p_emu->push_apss_forward();
819 #endif
820 }
821
822 void EmuThreadClass::do_cmt_push_apss_rewind(void)
823 {
824 #if defined(USE_TAPE_BUTTON)
825         p_emu->push_apss_rewind();
826 #endif  
827 }
828
829
830 void EmuThreadClass::do_write_protect_quickdisk(int drv, bool flag)
831 {
832 #if defined(USE_QD1)
833         //p_emu->write_protect_Qd(drv, flag);
834 #endif  
835 }
836
837 void EmuThreadClass::do_close_quickdisk(int drv)
838 {
839 #if defined(USE_QD1)
840         p_emu->close_quick_disk(drv);
841 #endif  
842 }
843
844 void EmuThreadClass::do_open_quickdisk(int drv, QString path)
845 {
846 #if defined(USE_QD1)
847         p_emu->open_quick_disk(drv, path.toLocal8Bit().constData());
848 #endif  
849 }
850
851 void EmuThreadClass::do_open_cdrom(QString path)
852 {
853 #ifdef USE_COMPACT_DISC
854         p_emu->open_compact_disc(path.toLocal8Bit().constData());
855 #endif  
856 }
857 void EmuThreadClass::do_eject_cdrom(void)
858 {
859 #ifdef USE_COMPACT_DISC
860         p_emu->close_compact_disc();
861 #endif  
862 }
863
864 void EmuThreadClass::do_close_cart(int drv)
865 {
866 #ifdef USE_CART1
867         p_emu->close_cart(drv);
868 #endif  
869 }
870
871 void EmuThreadClass::do_open_cart(int drv, QString path)
872 {
873 #ifdef USE_CART1
874         p_emu->open_cart(drv, path.toLocal8Bit().constData());
875 #endif  
876 }
877
878
879 void EmuThreadClass::do_close_laser_disk(void)
880 {
881 #ifdef USE_LASER_DISK
882         p_emu->close_laser_disk();
883 #endif
884 }
885
886 void EmuThreadClass::do_open_laser_disk(QString path)
887 {
888 #ifdef USE_LASER_DISK
889         p_emu->open_laser_disk(path.toLocal8Bit().constData());
890 #endif  
891 }
892
893 void EmuThreadClass::do_load_binary(int drv, QString path)
894 {
895 #ifdef USE_BINARY_FILE1
896         p_emu->load_binary(drv, path.toLocal8Bit().constData());
897 #endif  
898 }
899
900 void EmuThreadClass::do_save_binary(int drv, QString path)
901 {
902 #ifdef USE_BINARY_FILE1
903         p_emu->save_binary(drv, path.toLocal8Bit().constData());
904 #endif  
905 }
906
907
908 void EmuThreadClass::do_write_protect_bubble_casette(int drv, bool flag)
909 {
910 #ifdef USE_BUBBLE1
911         p_emu->is_bubble_casette_protected(drv, flag);
912 #endif  
913 }
914
915 void EmuThreadClass::do_close_bubble_casette(int drv)
916 {
917 #ifdef USE_BUBBLE1
918         p_emu->close_bubble_casette(drv);
919         p_emu->b77_file[drv].bank_num = 0;
920         p_emu->b77_file[drv].cur_bank = -1;
921 #endif  
922 }
923
924 void EmuThreadClass::do_open_bubble_casette(int drv, QString path, int bank)
925 {
926 #ifdef USE_BUBBLE1
927         QByteArray localPath = path.toLocal8Bit();
928    
929         p_emu->b77_file[drv].bank_num = 0;
930         p_emu->b77_file[drv].cur_bank = -1;
931         
932         if(check_file_extension(localPath.constData(), ".b77")) {
933                 
934                 FILEIO *fio = new FILEIO();
935                 if(fio->Fopen(localPath.constData(), FILEIO_READ_BINARY)) {
936                         try {
937                                 fio->Fseek(0, FILEIO_SEEK_END);
938                                 int file_size = fio->Ftell(), file_offset = 0;
939                                 while(file_offset + 0x2b0 <= file_size && p_emu->d88_file[drv].bank_num < MAX_B77_BANKS) {
940                                         fio->Fseek(file_offset, FILEIO_SEEK_SET);
941                                         char tmp[18];
942                                         memset(tmp, 0x00, sizeof(tmp));
943                                         fio->Fread(tmp, 16, 1);
944                                         memset(p_emu->b77_file[drv].bubble_name[p_emu->b77_file[drv].bank_num], 0x00, 128);
945                                         if(strlen(tmp) > 0) Convert_CP932_to_UTF8(p_emu->b77_file[drv].bubble_name[p_emu->b77_file[drv].bank_num], tmp, 127, 17);
946                                         
947                                         fio->Fseek(file_offset + 0x1c, FILEIO_SEEK_SET);
948                                         file_offset += fio->FgetUint32_LE();
949                                         p_emu->b77_file[drv].bank_num++;
950                                 }
951                                 strcpy(p_emu->b77_file[drv].path, path.toUtf8().constData());
952                                 if(bank >= p_emu->b77_file[drv].bank_num) bank = p_emu->b77_file[drv].bank_num - 1;
953                                 if(bank < 0) bank = 0;
954                                 p_emu->b77_file[drv].cur_bank = bank;
955                         }
956                         catch(...) {
957                                 bank = 0;
958                                 p_emu->b77_file[drv].bank_num = 0;
959                         }
960                         fio->Fclose();
961                 }
962                 delete fio;
963         } else {
964            bank = 0;
965         }
966         p_emu->open_bubble_casette(drv, localPath.constData(), bank);
967         emit sig_update_recent_bubble(drv);
968 #endif  
969 }
970
971 void EmuThreadClass::print_framerate(int frames)
972 {
973         if(frames >= 0) draw_frames += frames;
974         if(calc_message) {
975                 qint64 current_time = tick_timer.elapsed();
976                 if(update_fps_time <= current_time && update_fps_time != 0) {
977                         _TCHAR buf[256];
978                         QString message;
979                         int ratio = (int)(100.0 * (double)draw_frames / (double)total_frames + 0.5);
980
981 #ifdef USE_POWER_OFF
982                                 if(MainWindow->GetPowerState() == false){        
983                                         snprintf(buf, 255, _T("*Power OFF*"));
984                                 } else {
985 #endif // USE_POWER_OFF         
986                                         if(p_emu->message_count > 0) {
987                                                 snprintf(buf, 255, _T("%s - %s"), DEVICE_NAME, p_emu->message);
988                                                 p_emu->message_count--;
989                                         } else {
990                                                 snprintf(buf, 255, _T("%s - %d fps (%d %%)"), DEVICE_NAME, draw_frames, ratio);
991                                         }
992 #ifdef USE_POWER_OFF
993                                 } 
994 #endif // USE_POWER_OFF  
995                                 message = buf;
996                                 emit message_changed(message);
997                                 emit window_title_changed(message);
998                                 update_fps_time += 1000;
999                                 total_frames = draw_frames = 0;
1000                                 
1001                         }
1002                         if(update_fps_time <= current_time) {
1003                                 update_fps_time = current_time + 1000;
1004                         }
1005                         calc_message = false;  
1006                 } else {
1007                         calc_message = true;
1008                 }
1009 }
1010
1011 void EmuThreadClass::do_draw_timing(bool f)
1012 {
1013         draw_timing = f;
1014 }
1015
1016 void EmuThreadClass::sample_access_drv(void)
1017 {
1018         uint32_t access_drv;
1019         QString alamp;
1020         QString tmpstr;
1021         QString iname;
1022         int i;
1023 #if defined(USE_QD1)
1024 # if defined(USE_ACCESS_LAMP)      
1025         access_drv = p_emu->get_access_lamp_status();
1026 # endif
1027         for(i = 0; i < MAX_QD ; i++) {
1028                 if(p_emu->is_quick_disk_inserted(i)) {
1029                 //           printf("%d\n", access_drv);
1030 # if defined(USE_ACCESS_LAMP)      
1031                         if(i == (access_drv - 1)) {
1032                                 alamp = QString::fromUtf8("● ");
1033                         } else {
1034                                 alamp = QString::fromUtf8("○ ");
1035                         }
1036                         tmpstr = QString::fromUtf8("QD");
1037                         tmpstr = alamp + tmpstr + QString::number(i) + QString::fromUtf8(":");
1038 # else
1039                         tmpstr = QString::fromUtf8("QD");
1040                         tmpstr = tmpstr + QString::number(i) + QString::fromUtf8(":");
1041 # endif
1042                         iname = QString::fromUtf8("*Inserted*");
1043                         tmpstr = tmpstr + iname;
1044                 } else {
1045                         tmpstr = QString::fromUtf8("× QD") + QString::number(i) + QString::fromUtf8(":");
1046                         tmpstr = tmpstr + QString::fromUtf8(" ");
1047                 }
1048                 if(tmpstr != qd_text[i]) {
1049                         emit sig_change_osd_qd(i, tmpstr);
1050                         qd_text[i] = tmpstr;
1051                 }
1052         }
1053 #endif
1054
1055 #if defined(USE_FD1)
1056 # if defined(USE_ACCESS_LAMP)      
1057         access_drv = p_emu->get_access_lamp_status();
1058 # endif
1059         for(i = 0; i < MAX_FD; i++) {
1060                 if(p_emu->is_floppy_disk_inserted(i)) {
1061 # if defined(USE_ACCESS_LAMP)      
1062                         if(i == (access_drv - 1)) {
1063                                 alamp = QString::fromUtf8("<FONT COLOR=RED>●</FONT> ");
1064                         } else {
1065                                 alamp = QString::fromUtf8("○ ");
1066                         }
1067                         tmpstr = QString::fromUtf8("FD");
1068                         tmpstr = alamp + tmpstr + QString::number(i) + QString::fromUtf8(":");
1069 # else
1070                         tmpstr = QString::fromUtf8("FD");
1071                         tmpstr = tmpstr + QString::number(i) + QString::fromUtf8(":");
1072 # endif
1073                         if(emu->d88_file[i].bank_num > 0) {
1074                                 iname = QString::fromUtf8(emu->d88_file[i].disk_name[emu->d88_file[i].cur_bank]);
1075                         } else {
1076                                 iname = QString::fromUtf8("*Inserted*");
1077                         }
1078                         tmpstr = tmpstr + iname;
1079                 } else {
1080                         tmpstr = QString::fromUtf8("× FD") + QString::number(i) + QString::fromUtf8(":");
1081                         tmpstr = tmpstr + QString::fromUtf8(" ");
1082                 }
1083
1084                 if(tmpstr != fd_text[i]) {
1085                         emit sig_change_osd_fd(i, tmpstr);
1086                         fd_text[i] = tmpstr;
1087                 }
1088         }
1089 #endif
1090 #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
1091         if(p_emu->is_tape_inserted()) {
1092                 int tape_counter = p_emu->get_tape_position();
1093                 tmpstr = QString::fromUtf8("");
1094                 if(p_emu->is_tape_playing()) {
1095                         tmpstr = QString::fromUtf8("<FONT COLOR=BLUE>▶ </FONT>");
1096                 } else if(p_emu->is_tape_recording()) {
1097                         tmpstr = QString::fromUtf8("<FONT COLOR=RED>● </FONT>");
1098                 } else {
1099                         tmpstr = QString::fromUtf8("<FONT COLOR=BLACK>■ </FONT>");
1100                 }
1101                 if(tape_counter >= 100) {
1102                         tmpstr = tmpstr + QString::fromUtf8("BOTTOM");
1103                 } else if(tape_counter >= 0) {
1104                         tmpstr = tmpstr + QString::number(tape_counter) + QString::fromUtf8("%");
1105                 } else {
1106                         tmpstr = tmpstr + QString::fromUtf8("TOP");
1107                 }
1108         } else {
1109                 tmpstr = QString::fromUtf8("EMPTY");
1110         }
1111         if(tmpstr != cmt_text) {
1112                 emit sig_change_osd_cmt(tmpstr);
1113                 cmt_text = tmpstr;
1114         }
1115 #endif
1116 #if defined(USE_COMPACT_DISC)
1117         if(p_emu->is_compact_disc_inserted()) {
1118                 tmpstr = QString::fromUtf8("○");
1119         } else {
1120                 tmpstr = QString::fromUtf8("Not Inserted");
1121         }
1122         if(tmpstr != cdrom_text) {
1123                 emit sig_change_osd_cdrom(tmpstr);
1124                 cdrom_text = tmpstr;
1125         }
1126 #endif
1127 #if defined(USE_BUBBLE1)
1128         for(i = 0; i < MAX_BUBBLE ; i++) {
1129                 if(p_emu->is_bubble_casette_inserted(i)) {
1130                         //if(i == (access_drv - 1)) {
1131                         alamp = QString::fromUtf8("● ");
1132                         //} else {
1133                         //alamp = QString::fromUtf8("○ ");
1134                         //}
1135                         tmpstr = QString::fromUtf8("BUB");
1136                         tmpstr = alamp + tmpstr + QString::number(i) + QString::fromUtf8(":");
1137                 } else {
1138                         tmpstr = QString::fromUtf8("× BUB") + QString::number(i) + QString::fromUtf8(":");
1139                         tmpstr = tmpstr + QString::fromUtf8(" ");
1140                 }
1141                 if(tmpstr != bubble_text[i]) {
1142                         emit sig_change_osd_bubble(i, tmpstr);
1143                         bubble_text[i] = tmpstr;
1144                 }
1145         }
1146 #endif
1147 }
1148
1149 void EmuThreadClass::doWork(const QString &params)
1150 {
1151         int interval = 0, sleep_period = 0;
1152         int run_frames;
1153         bool now_skip;
1154         qint64 current_time;
1155         bool first = true;
1156 #ifdef USE_LED_DEVICE
1157         uint32_t led_data = 0x00000000;
1158         uint32_t led_data_old = 0x00000000;
1159 #endif
1160 #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
1161         bool tape_flag;
1162         int tpos;
1163 #endif
1164 #ifdef USE_DIG_RESOLUTION
1165         int width, height;
1166 #endif
1167         QString ctext;
1168         bool req_draw = true;
1169         bool vert_line_bak = config.opengl_scanline_vert;
1170         bool horiz_line_bak = config.opengl_scanline_horiz;
1171         bool gl_crt_filter_bak = config.use_opengl_filters;
1172         int opengl_filter_num_bak = config.opengl_filter_num;
1173         int no_draw_count = 0;  
1174         doing_debug_command = false;
1175         
1176         ctext.clear();
1177         draw_timing = false;
1178         bResetReq = false;
1179         bSpecialResetReq = false;
1180         bLoadStateReq = false;
1181         bSaveStateReq = false;
1182         bUpdateConfigReq = false;
1183         bStartRecordSoundReq = false;
1184         bStopRecordSoundReq = false;
1185         
1186         next_time = 0;
1187         mouse_flag = false;
1188         //(this->idealThreadCount());
1189         
1190 #if defined(USE_QD1)
1191         for(int i = 0; i < 2; i++) qd_text[i].clear();
1192 #endif
1193 #if defined(USE_FD1)
1194         for(int i = 0; i < MAX_FD; i++) fd_text[i].clear();
1195 #endif
1196 #if defined(USE_TAPE)
1197         cmt_text.clear();
1198 #endif
1199 #if defined(USE_COMPACT_DISC)
1200         cdrom_text.clear();
1201 #endif
1202 #if defined(USE_BUBBLE1)
1203         for(int i = 0; i < MAX_BUBBLE; i++) bubble_text[i].clear();
1204 #endif
1205         do {
1206                 //p_emu->SetHostCpus(this->idealThreadCount());
1207                 if(MainWindow == NULL) {
1208                         if(bRunThread == false){
1209                                 goto _exit;
1210                         }
1211                         msleep(10);
1212                         continue;
1213                 }
1214                 if(first) {
1215 #ifdef USE_LED_DEVICE
1216                         emit sig_send_data_led((quint32)led_data);
1217 #endif
1218                         first = false;
1219                 }
1220                 interval = 0;
1221                 sleep_period = 0;
1222                 if(p_emu) {
1223                         // drive machine
1224 #ifdef USE_STATE
1225                         if(bLoadStateReq != false) {
1226                                 p_emu->load_state();
1227                                 bLoadStateReq = false;
1228                                 req_draw = true;
1229                         }
1230 #endif                  
1231                         if(bResetReq != false) {
1232                                 p_emu->reset();
1233                                 bResetReq = false;
1234                                 req_draw = true;
1235                         }
1236 #ifdef USE_SPECIAL_RESET
1237                         if(bSpecialResetReq != false) {
1238                                 p_emu->special_reset();
1239                                 bSpecialResetReq = false;
1240                         }
1241 #endif
1242 #ifdef USE_STATE
1243                         if(bSaveStateReq != false) {
1244                                 p_emu->save_state();
1245                                 bSaveStateReq = false;
1246                         }
1247 #endif
1248 #if defined(USE_MINIMUM_RENDERING)
1249                         if((vert_line_bak != config.opengl_scanline_vert) ||
1250                            (horiz_line_bak != config.opengl_scanline_horiz) ||
1251                            (gl_crt_filter_bak != config.use_opengl_filters) ||
1252                            (opengl_filter_num_bak != config.opengl_filter_num)) req_draw = true;
1253                         vert_line_bak = config.opengl_scanline_vert;
1254                         horiz_line_bak = config.opengl_scanline_horiz;
1255                         gl_crt_filter_bak = config.use_opengl_filters;
1256                         opengl_filter_num_bak = config.opengl_filter_num;
1257 #endif
1258                         if(bStartRecordSoundReq != false) {
1259                                 p_emu->start_record_sound();
1260                                 bStartRecordSoundReq = false;
1261                                 req_draw = true;
1262                         }
1263                         if(bStopRecordSoundReq != false) {
1264                                 p_emu->stop_record_sound();
1265                                 bStopRecordSoundReq = false;
1266                                 req_draw = true;
1267                         }
1268                         if(bUpdateConfigReq != false) {
1269                                 p_emu->update_config();
1270                                 bUpdateConfigReq = false;
1271                                 req_draw = true;
1272                         }
1273 #if defined(USE_MOUSE)  // Will fix
1274                         emit sig_is_enable_mouse(p_emu->is_mouse_enabled());
1275 #endif                  
1276 #if defined(USE_SOUND_VOLUME)
1277                         for(int ii = 0; ii < USE_SOUND_VOLUME; ii++) {
1278                                 if(bUpdateVolumeReq[ii]) {
1279                                         p_emu->set_sound_device_volume(ii, config.sound_volume_l[ii], config.sound_volume_r[ii]);
1280                                         bUpdateVolumeReq[ii] = false;
1281                                 }
1282                         }
1283 #endif                  
1284                         run_frames = p_emu->run();
1285                         total_frames += run_frames;
1286 #if defined(USE_MINIMUM_RENDERING)
1287                         req_draw |= p_emu->is_screen_changed();
1288 #else
1289                         req_draw = true;
1290 #endif                  
1291 #ifdef USE_LED_DEVICE
1292                         led_data = p_emu->get_led_status();
1293                         if(led_data != led_data_old) {
1294                                 emit sig_send_data_led((quint32)led_data);
1295                                 led_data_old = led_data;
1296                         }
1297 #endif
1298                         sample_access_drv();
1299
1300                         interval += get_interval();
1301                         now_skip = p_emu->is_frame_skippable() && !p_emu->is_video_recording();
1302
1303                         if((prev_skip && !now_skip) || next_time == 0) {
1304                                 next_time = tick_timer.elapsed();
1305                         }
1306                         if(!now_skip) {
1307                                 next_time += interval;
1308                         }
1309                         prev_skip = now_skip;
1310                         //printf("p_emu::RUN Frames = %d SKIP=%d Interval = %d NextTime = %d\n", run_frames, now_skip, interval, next_time);
1311       
1312                         if(next_time > tick_timer.elapsed()) {
1313                                 //  update window if enough time
1314                                 draw_timing = false;
1315                                 if(!req_draw) {
1316                                         no_draw_count++;
1317                                         if(no_draw_count > (int)(FRAMES_PER_SEC / 4)) {
1318                                                 req_draw = true;
1319                                                 no_draw_count = 0;
1320                                         }
1321                                 } else {
1322                                         no_draw_count = 0;
1323                                 }
1324                                 emit sig_draw_thread(req_draw);
1325                                 skip_frames = 0;
1326                         
1327                                 // sleep 1 frame priod if need
1328                                 current_time = tick_timer.elapsed();
1329                                 if((int)(next_time - current_time) >= 10) {
1330                                         sleep_period = next_time - current_time;
1331                                 }
1332                         } else if(++skip_frames > MAX_SKIP_FRAMES) {
1333                                 // update window at least once per 10 frames
1334                                 draw_timing = false;
1335                                 emit sig_draw_thread(true);
1336                                 no_draw_count = 0;
1337                                 skip_frames = 0;
1338                                 qint64 tt = tick_timer.elapsed();
1339                                 next_time = tt + get_interval();
1340                                 sleep_period = next_time - tt;
1341                         }
1342                 }
1343                 req_draw = false;
1344                 if(bRunThread == false){
1345                         goto _exit;
1346                 }
1347                 if(sleep_period <= 0) sleep_period = 1;
1348                 msleep(sleep_period);
1349         } while(1);
1350 _exit:
1351         //emit quit_draw_thread();
1352         AGAR_DebugLog(AGAR_LOG_DEBUG, "EmuThread : EXIT");
1353         emit sig_finished();
1354         this->quit();
1355 }
1356
1357 void EmuThreadClass::doSetDisplaySize(int w, int h, int ww, int wh)
1358 {
1359         p_emu->suspend();
1360         //p_emu->set_vm_screen_size(w, h, -1, -1, ww, wh);
1361         p_emu->set_host_window_size(w, h, true);
1362 }
1363
1364 void EmuThreadClass::doUpdateVolumeLevel(int num, int level)
1365 {
1366 #if defined(USE_SOUND_VOLUME)
1367         if((num < USE_SOUND_VOLUME) && (num >= 0)) {
1368                 calc_volume_from_level(num, level);
1369                 bUpdateVolumeReq[num] = true;
1370         }
1371 #endif  
1372 }
1373
1374 void EmuThreadClass::doUpdateVolumeBalance(int num, int level)
1375 {
1376 #if defined(USE_SOUND_VOLUME)
1377         if((num < USE_SOUND_VOLUME) && (num >= 0)) {
1378                 calc_volume_from_balance(num, level);
1379                 bUpdateVolumeReq[num] = true;
1380         }
1381 #endif  
1382 }
1383
1384
1385 void EmuThreadClass::doUpdateConfig()
1386 {
1387         bUpdateConfigReq = true;
1388 }
1389
1390 void EmuThreadClass::doStartRecordSound()
1391 {
1392         bStartRecordSoundReq = true;
1393 }
1394
1395 void EmuThreadClass::doStopRecordSound()
1396 {
1397         bStopRecordSoundReq = true;
1398 }
1399
1400 void EmuThreadClass::doReset()
1401 {
1402         bResetReq = true;
1403 }
1404
1405 void EmuThreadClass::doSpecialReset()
1406 {
1407         bSpecialResetReq = true;
1408 }
1409
1410 void EmuThreadClass::doLoadState()
1411 {
1412         bLoadStateReq = true;
1413 }
1414
1415 void EmuThreadClass::doSaveState()
1416 {
1417         bSaveStateReq = true;
1418 }
1419 // Debugger
1420 #if defined(USE_DEBUGGER)
1421 extern int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932);
1422 #endif
1423 void EmuThreadClass::do_call_debugger_command(QString s)
1424 {
1425 #if defined(USE_DEBUGGER)
1426         _TCHAR command[MAX_COMMAND_LEN + 1];
1427
1428         if(doing_debug_command) {
1429                 emit sig_debugger_input(s);
1430                 return;
1431         }
1432         memset(command, 0x00, MAX_COMMAND_LEN + 1);
1433         if(s.isEmpty()) {
1434                 strncpy(command, dbg_prev_command, MAX_COMMAND_LEN);
1435         } else {
1436                 strncpy(command, s.toUtf8().constData(), MAX_COMMAND_LEN);
1437         }
1438         doing_debug_command = true;
1439         if(debugger_command(&(p_emu->debugger_thread_param), command, dbg_prev_command, false) < 0) {
1440                 do_close_debugger();
1441         }
1442         doing_debug_command = false;
1443 #endif
1444 }
1445
1446 void EmuThreadClass::do_close_debugger(void)
1447 {
1448 #if defined(USE_DEBUGGER)
1449         emit sig_quit_debugger();
1450 #endif
1451 }
1452
1453 bool EmuThreadClass::now_debugging() {
1454 #if defined(USE_DEBUGGER)
1455         return p_emu->now_debugging;
1456 #else
1457         return false;
1458 #endif
1459 }