OSDN Git Service

[UI][Qt] Not liking config, using_flags directly.
[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 EmuThreadClass::EmuThreadClass(META_MainWindow *rootWindow, EMU *pp_emu, USING_FLAGS *p, QObject *parent) : QThread(parent) {
30         MainWindow = rootWindow;
31         p_emu = pp_emu;
32         using_flags = p;
33         p_config = p->get_config_ptr();
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] = (using_flags->get_config_ptr()->sound_volume_l[i] +
59                                                          using_flags->get_config_ptr()->sound_volume_r[i]) / 2;
60                         volume_balance[i] = (using_flags->get_config_ptr()->sound_volume_r[i] -
61                                                                  using_flags->get_config_ptr()->sound_volume_l[i]) / 2;
62                 }
63         }
64 };
65
66 EmuThreadClass::~EmuThreadClass() {
67         delete drawCond;
68 };
69
70 void EmuThreadClass::calc_volume_from_balance(int num, int balance)
71 {
72         int level = volume_avg[num];
73         int right;
74         int left;
75         volume_balance[num] = balance;
76         right = level + balance;
77         left  = level - balance;
78         using_flags->get_config_ptr()->sound_volume_l[num] = left;      
79         using_flags->get_config_ptr()->sound_volume_r[num] = right;
80 }
81
82 void EmuThreadClass::calc_volume_from_level(int num, int level)
83 {
84         int balance = volume_balance[num];
85         int right,left;
86         volume_avg[num] = level;
87         right = level + balance;
88         left  = level - balance;
89         using_flags->get_config_ptr()->sound_volume_l[num] = left;      
90         using_flags->get_config_ptr()->sound_volume_r[num] = right;
91 }
92
93 int EmuThreadClass::get_interval(void)
94 {
95         static int accum = 0;
96         accum += p_emu->get_frame_interval();
97         int interval = accum >> 10;
98         accum -= interval << 10;
99         return interval;
100 }
101
102 void EmuThreadClass::doExit(void)
103 {
104         int status;
105         bRunThread = false;
106 }
107
108 void EmuThreadClass::moved_mouse(int x, int y)
109 {
110         mouse_x = x;
111         mouse_y = y;
112 #if defined(USE_MOUSE)   
113         p_emu->set_mouse_pointer(x, y);
114 #endif   
115 }
116
117 void EmuThreadClass::button_pressed_mouse(Qt::MouseButton button)
118 {
119         if(using_flags->is_use_mouse()) {
120 #if defined(USE_MOUSE)   
121                 int stat = p_emu->get_mouse_button();
122                 bool flag = p_emu->is_mouse_enabled();
123                 switch(button) {
124                 case Qt::LeftButton:
125                         stat |= 0x01;
126                         break;
127                 case Qt::RightButton:
128                         stat |= 0x02;
129                         break;
130                 case Qt::MiddleButton:
131                         flag = !flag;
132                         emit sig_mouse_enable(flag);
133                         break;
134                 }
135                 p_emu->set_mouse_button(stat);
136 #endif     
137         } else {                
138                 if(using_flags->get_max_button() > 0) {
139                         button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
140                         if(vm_buttons_d == NULL) return;
141                         switch(button) {
142                         case Qt::LeftButton:
143                         case Qt::RightButton:
144                                 for(int i = 0; i < using_flags->get_max_button(); i++) {
145                                         if((mouse_x >= vm_buttons_d[i].x) &&
146                                            (mouse_x < (vm_buttons_d[i].x + vm_buttons_d[i].width))) {
147                                                 if((mouse_y >= vm_buttons_d[i].y) &&
148                                                    (mouse_y < (vm_buttons_d[i].y + vm_buttons_d[i].height))) {
149                                                         if(vm_buttons_d[i].code != 0x00) {
150                                                                 //p_emu->key_down(vm_buttons_d[i].code, false);
151                                                                 key_down_code = vm_buttons_d[i].code;
152                                                                 key_repeat = false;
153                                                         } else {
154                                                                 bResetReq = true;
155                                                         }
156                                                 }
157                                         }
158                                 }
159                                 break;
160                         }
161                 }
162         }
163 }
164
165 void EmuThreadClass::button_released_mouse(Qt::MouseButton button)
166 {
167         if(using_flags->is_use_mouse()) {
168 #if defined(USE_MOUSE)   
169                 int stat = p_emu->get_mouse_button();
170                 switch(button) {
171                 case Qt::LeftButton:
172                         stat &= 0x7ffffffe;
173                         break;
174                 case Qt::RightButton:
175                         stat &= 0x7ffffffd;
176                         break;
177                 case Qt::MiddleButton:
178                         //emit sig_mouse_enable(false);
179                         break;
180                 }
181                 p_emu->set_mouse_button(stat);
182 #endif
183         } else {
184                 if(using_flags->get_max_button() > 0) {
185                         button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
186                         if(vm_buttons_d == NULL) return;
187                         
188                         switch(button) {
189                         case Qt::LeftButton:
190                         case Qt::RightButton:
191                                 for(int i = 0; i < using_flags->get_max_button(); i++) {
192                                         if((mouse_x >= vm_buttons_d[i].x) &&
193                                            (mouse_x < (vm_buttons_d[i].x + vm_buttons_d[i].width))) {
194                                                 if((mouse_y >= vm_buttons_d[i].y) &&
195                                                    (mouse_y < (vm_buttons_d[i].y + vm_buttons_d[i].height))) {
196                                                         if(vm_buttons_d[i].code != 0x00) {
197                                                                 //p_emu->key_up(vm_buttons_d[i].code);
198                                                                 key_up_code = vm_buttons_d[i].code;
199                                                         }
200                                                 }
201                                         }
202                                 }
203                                 break;
204                         }
205                 }
206         }
207 }
208
209 void EmuThreadClass::do_key_down(uint32_t vk, uint32_t mod, bool repeat)
210 {
211         key_down_code = vk;
212         key_mod_code = mod;
213         key_repeat = repeat;
214         key_changed = true;
215 }
216
217 void EmuThreadClass::do_key_up(uint32_t vk, uint32_t mod)
218 {
219         key_up_code = vk;
220         key_mod_code = mod;
221         key_changed = true;
222
223 }
224
225
226 void EmuThreadClass::set_tape_play(bool flag)
227 {
228         tape_play_flag = flag;
229 }
230
231 EmuThreadClass *EmuThreadClass::currentHandler()
232 {
233         return this;
234 }
235
236 void EmuThreadClass::resize_screen(int screen_width, int screen_height, int stretched_width, int stretched_height)
237 {
238         //emit sig_resize_uibar(stretched_width, stretched_height);
239         emit sig_resize_screen(screen_width, screen_height);
240 }
241
242 const int auto_key_table_base[][2] = {
243         // 0x100: shift
244         // 0x200: kana
245         // 0x400: alphabet
246         // 0x800: ALPHABET
247         {0x0a,  0x000 | 0x0d},  // Enter(Unix)
248         {0x0d,  0x000 | 0x0d},  // Enter
249         {0x20,  0x000 | 0x20},  // ' '
250
251         {0x21,  0x100 | 0x31},  // '!'
252         {0x22,  0x100 | 0x32},  // '"'
253         {0x23,  0x100 | 0x33},  // '#'
254         {0x24,  0x100 | 0x34},  // '$'
255         {0x25,  0x100 | 0x35},  // '%'
256         {0x26,  0x100 | 0x36},  // '&'
257         {0x27,  0x100 | 0x37},  // '''
258         {0x28,  0x100 | 0x38},  // '('
259         {0x29,  0x100 | 0x39},  // ')'
260         {0x2a,  0x100 | 0xba},  // '*'
261         {0x2b,  0x100 | 0xbb},  // '+'
262         {0x2c,  0x000 | 0xbc},  // ','
263         {0x2d,  0x000 | 0xbd},  // '-'
264         {0x2e,  0x000 | 0xbe},  // '.'
265         {0x2f,  0x000 | 0xbf},  // '/'
266
267         {0x30,  0x000 | 0x30},  // '0'
268         {0x31,  0x000 | 0x31},  // '1'
269         {0x32,  0x000 | 0x32},  // '2'
270         {0x33,  0x000 | 0x33},  // '3'
271         {0x34,  0x000 | 0x34},  // '4'
272         {0x35,  0x000 | 0x35},  // '5'
273         {0x36,  0x000 | 0x36},  // '6'
274         {0x37,  0x000 | 0x37},  // '7'
275         {0x38,  0x000 | 0x38},  // '8'
276         {0x39,  0x000 | 0x39},  // '9'
277
278         {0x3a,  0x000 | 0xba},  // ':'
279         {0x3b,  0x000 | 0xbb},  // ';'
280         {0x3c,  0x100 | 0xbc},  // '<'
281         {0x3d,  0x100 | 0xbd},  // '='
282         {0x3e,  0x100 | 0xbe},  // '>'
283         {0x3f,  0x100 | 0xbf},  // '?'
284         {0x40,  0x000 | 0xc0},  // '@'
285
286         {0x41,  0x400 | 0x41},  // 'A'
287         {0x42,  0x400 | 0x42},  // 'B'
288         {0x43,  0x400 | 0x43},  // 'C'
289         {0x44,  0x400 | 0x44},  // 'D'
290         {0x45,  0x400 | 0x45},  // 'E'
291         {0x46,  0x400 | 0x46},  // 'F'
292         {0x47,  0x400 | 0x47},  // 'G'
293         {0x48,  0x400 | 0x48},  // 'H'
294         {0x49,  0x400 | 0x49},  // 'I'
295         {0x4a,  0x400 | 0x4a},  // 'J'
296         {0x4b,  0x400 | 0x4b},  // 'K'
297         {0x4c,  0x400 | 0x4c},  // 'L'
298         {0x4d,  0x400 | 0x4d},  // 'M'
299         {0x4e,  0x400 | 0x4e},  // 'N'
300         {0x4f,  0x400 | 0x4f},  // 'O'
301         {0x50,  0x400 | 0x50},  // 'P'
302         {0x51,  0x400 | 0x51},  // 'Q'
303         {0x52,  0x400 | 0x52},  // 'R'
304         {0x53,  0x400 | 0x53},  // 'S'
305         {0x54,  0x400 | 0x54},  // 'T'
306         {0x55,  0x400 | 0x55},  // 'U'
307         {0x56,  0x400 | 0x56},  // 'V'
308         {0x57,  0x400 | 0x57},  // 'W'
309         {0x58,  0x400 | 0x58},  // 'X'
310         {0x59,  0x400 | 0x59},  // 'Y'
311         {0x5a,  0x400 | 0x5a},  // 'Z'
312
313         {0x5b,  0x000 | 0xdb},  // '['
314         {0x5c,  0x000 | 0xdc},  // '\'
315         {0x5d,  0x000 | 0xdd},  // ']'
316         {0x5e,  0x000 | 0xde},  // '^'
317         {0x5f,  0x100 | 0xe2},  // '_'
318         {0x60,  0x100 | 0xc0},  // '`'
319
320         {0x61,  0x800 | 0x41},  // 'a'
321         {0x62,  0x800 | 0x42},  // 'b'
322         {0x63,  0x800 | 0x43},  // 'c'
323         {0x64,  0x800 | 0x44},  // 'd'
324         {0x65,  0x800 | 0x45},  // 'e'
325         {0x66,  0x800 | 0x46},  // 'f'
326         {0x67,  0x800 | 0x47},  // 'g'
327         {0x68,  0x800 | 0x48},  // 'h'
328         {0x69,  0x800 | 0x49},  // 'i'
329         {0x6a,  0x800 | 0x4a},  // 'j'
330         {0x6b,  0x800 | 0x4b},  // 'k'
331         {0x6c,  0x800 | 0x4c},  // 'l'
332         {0x6d,  0x800 | 0x4d},  // 'm'
333         {0x6e,  0x800 | 0x4e},  // 'n'
334         {0x6f,  0x800 | 0x4f},  // 'o'
335         {0x70,  0x800 | 0x50},  // 'p'
336         {0x71,  0x800 | 0x51},  // 'q'
337         {0x72,  0x800 | 0x52},  // 'r'
338         {0x73,  0x800 | 0x53},  // 's'
339         {0x74,  0x800 | 0x54},  // 't'
340         {0x75,  0x800 | 0x55},  // 'u'
341         {0x76,  0x800 | 0x56},  // 'v'
342         {0x77,  0x800 | 0x57},  // 'w'
343         {0x78,  0x800 | 0x58},  // 'x'
344         {0x79,  0x800 | 0x59},  // 'y'
345         {0x7a,  0x800 | 0x5a},  // 'z'
346
347         {0x7b,  0x100 | 0xdb},  // '{'
348         {0x7c,  0x100 | 0xdc},  // '|'
349         {0x7d,  0x100 | 0xdd},  // '}'
350         {0x7e,  0x100 | 0xde},  // '~'
351
352         {0xa1,  0x300 | 0xbe},  // '
353         {0xa2,  0x300 | 0xdb},  // '
354         {0xa3,  0x300 | 0xdd},  // '
355         {0xa4,  0x300 | 0xbc},  // '
356         {0xa5,  0x300 | 0xbf},  // '・'
357         {0xa6,  0x300 | 0x30},  // 'ヲ'
358         {0xa7,  0x300 | 0x33},  // 'ァ'
359         {0xa8,  0x300 | 0x45},  // 'ィ'
360         {0xa9,  0x300 | 0x34},  // 'ゥ'
361         {0xaa,  0x300 | 0x35},  // 'ェ'
362         {0xab,  0x300 | 0x36},  // 'ォ'
363         {0xac,  0x300 | 0x37},  // 'ャ'
364         {0xad,  0x300 | 0x38},  // 'ュ'
365         {0xae,  0x300 | 0x39},  // 'ョ'
366         {0xaf,  0x300 | 0x5a},  // 'ッ'
367         {0xb0,  0x200 | 0xdc},  // 'ー'
368         {0xb1,  0x200 | 0x33},  // 'ア'
369         {0xb2,  0x200 | 0x45},  // 'イ'
370         {0xb3,  0x200 | 0x34},  // 'ウ'
371         {0xb4,  0x200 | 0x35},  // 'エ'
372         {0xb5,  0x200 | 0x36},  // 'オ'
373         {0xb6,  0x200 | 0x54},  // 'カ'
374         {0xb7,  0x200 | 0x47},  // 'キ'
375         {0xb8,  0x200 | 0x48},  // 'ク'
376         {0xb9,  0x200 | 0xba},  // 'ケ'
377         {0xba,  0x200 | 0x42},  // 'コ'
378         {0xbb,  0x200 | 0x58},  // 'サ'
379         {0xbc,  0x200 | 0x44},  // 'シ'
380         {0xbd,  0x200 | 0x52},  // 'ス'
381         {0xbe,  0x200 | 0x50},  // 'セ'
382         {0xbf,  0x200 | 0x43},  // 'ソ'
383         {0xc0,  0x200 | 0x51},  // 'タ'
384         {0xc1,  0x200 | 0x41},  // 'チ'
385         {0xc2,  0x200 | 0x5a},  // 'ツ'
386         {0xc3,  0x200 | 0x57},  // 'テ'
387         {0xc4,  0x200 | 0x53},  // 'ト'
388         {0xc5,  0x200 | 0x55},  // 'ナ'
389         {0xc6,  0x200 | 0x49},  // 'ニ'
390         {0xc7,  0x200 | 0x31},  // 'ヌ'
391         {0xc8,  0x200 | 0xbc},  // 'ネ'
392         {0xc9,  0x200 | 0x4b},  // 'ノ'
393         {0xca,  0x200 | 0x46},  // 'ハ'
394         {0xcb,  0x200 | 0x56},  // 'ヒ'
395         {0xcc,  0x200 | 0x32},  // 'フ'
396         {0xcd,  0x200 | 0xde},  // 'ヘ'
397         {0xce,  0x200 | 0xbd},  // 'ホ'
398         {0xcf,  0x200 | 0x4a},  // 'マ'
399         {0xd0,  0x200 | 0x4e},  // 'ミ'
400         {0xd1,  0x200 | 0xdd},  // 'ム'
401         {0xd2,  0x200 | 0xbf},  // 'メ'
402         {0xd3,  0x200 | 0x4d},  // 'モ'
403         {0xd4,  0x200 | 0x37},  // 'ヤ'
404         {0xd5,  0x200 | 0x38},  // 'ユ'
405         {0xd6,  0x200 | 0x39},  // 'ヨ'
406         {0xd7,  0x200 | 0x4f},  // 'ラ'
407         {0xd8,  0x200 | 0x4c},  // 'リ'
408         {0xd9,  0x200 | 0xbe},  // 'ル'
409         {0xda,  0x200 | 0xbb},  // 'レ'
410         {0xdb,  0x200 | 0xe2},  // 'ロ'
411         {0xdc,  0x200 | 0x30},  // 'ワ'
412         {0xdd,  0x200 | 0x59},  // 'ン'
413         {0xde,  0x200 | 0xc0},  // '゙'
414         {0xdf,  0x200 | 0xdb},  // '゚'
415         {-1, -1},
416 };
417
418 const int auto_key_table_base_us[][2] = {
419         // 0x100: shift
420         // 0x200: kana
421         // 0x400: alphabet
422         // 0x800: ALPHABET
423         {0x0a,  0x000 | 0x0d},  // Enter(Unix)
424         {0x0d,  0x000 | 0x0d},  // Enter
425         {0x20,  0x000 | 0x20},  // ' '
426         {0x21,  0x100 | 0x31},  // '!'
427         {0x22,  0x100 | 0xba},  // '"'
428         {0x23,  0x100 | 0x33},  // '#'
429         {0x24,  0x100 | 0x34},  // '$'
430         {0x25,  0x100 | 0x35},  // '%'
431         {0x26,  0x100 | 0x37},  // '&'
432         {0x27,  0x000 | 0xba},  // '''
433         {0x28,  0x100 | 0x39},  // '('
434         {0x29,  0x100 | 0x30},  // ')'
435         {0x2a,  0x100 | 0x38},  // '*'
436         {0x2b,  0x100 | 0xde},  // '+'
437         {0x2c,  0x000 | 0xbc},  // ','
438         {0x2d,  0x000 | 0xbd},  // '-'
439         {0x2e,  0x000 | 0xbe},  // '.'
440         {0x2f,  0x000 | 0xbf},  // '/'
441         
442         {0x30,  0x000 | 0x30},  // '0'
443         {0x31,  0x000 | 0x31},  // '1'
444         {0x32,  0x000 | 0x32},  // '2'
445         {0x33,  0x000 | 0x33},  // '3'
446         {0x34,  0x000 | 0x34},  // '4'
447         {0x35,  0x000 | 0x35},  // '5'
448         {0x36,  0x000 | 0x36},  // '6'
449         {0x37,  0x000 | 0x37},  // '7'
450         {0x38,  0x000 | 0x38},  // '8'
451         {0x39,  0x000 | 0x39},  // '9'
452         
453         {0x3a,  0x100 | 0xbb},  // ':'
454         {0x3b,  0x000 | 0xbb},  // ';'
455         {0x3c,  0x100 | 0xbc},  // '<'
456         {0x3d,  0x000 | 0xde},  // '='
457         {0x3e,  0x100 | 0xbe},  // '>'
458         {0x3f,  0x100 | 0xbf},  // '?'
459         {0x40,  0x100 | 0x32},  // '@'
460         
461         {0x41,  0x400 | 0x41},  // 'A'
462         {0x42,  0x400 | 0x42},  // 'B'
463         {0x43,  0x400 | 0x43},  // 'C'
464         {0x44,  0x400 | 0x44},  // 'D'
465         {0x45,  0x400 | 0x45},  // 'E'
466         {0x46,  0x400 | 0x46},  // 'F'
467         {0x47,  0x400 | 0x47},  // 'G'
468         {0x48,  0x400 | 0x48},  // 'H'
469         {0x49,  0x400 | 0x49},  // 'I'
470         {0x4a,  0x400 | 0x4a},  // 'J'
471         {0x4b,  0x400 | 0x4b},  // 'K'
472         {0x4c,  0x400 | 0x4c},  // 'L'
473         {0x4d,  0x400 | 0x4d},  // 'M'
474         {0x4e,  0x400 | 0x4e},  // 'N'
475         {0x4f,  0x400 | 0x4f},  // 'O'
476         {0x50,  0x400 | 0x50},  // 'P'
477         {0x51,  0x400 | 0x51},  // 'Q'
478         {0x52,  0x400 | 0x52},  // 'R'
479         {0x53,  0x400 | 0x53},  // 'S'
480         {0x54,  0x400 | 0x54},  // 'T'
481         {0x55,  0x400 | 0x55},  // 'U'
482         {0x56,  0x400 | 0x56},  // 'V'
483         {0x57,  0x400 | 0x57},  // 'W'
484         {0x58,  0x400 | 0x58},  // 'X'
485         {0x59,  0x400 | 0x59},  // 'Y'
486         {0x5a,  0x400 | 0x5a},  // 'Z'
487
488         {0x5b,  0x000 | 0xc0},  // '['
489         {0x5c,  0x000 | 0xe2},  // '\'
490         {0x5d,  0x000 | 0xdb},  // ']'
491         {0x5e,  0x100 | 0x36},  // '^'
492         {0x5f,  0x100 | 0xbd},  // '_'
493         {0x60,  0x000 | 0xdd},  // '`'
494         
495         {0x61,  0x800 | 0x41},  // 'a'
496         {0x62,  0x800 | 0x42},  // 'b'
497         {0x63,  0x800 | 0x43},  // 'c'
498         {0x64,  0x800 | 0x44},  // 'd'
499         {0x65,  0x800 | 0x45},  // 'e'
500         {0x66,  0x800 | 0x46},  // 'f'
501         {0x67,  0x800 | 0x47},  // 'g'
502         {0x68,  0x800 | 0x48},  // 'h'
503         {0x69,  0x800 | 0x49},  // 'i'
504         {0x6a,  0x800 | 0x4a},  // 'j'
505         {0x6b,  0x800 | 0x4b},  // 'k'
506         {0x6c,  0x800 | 0x4c},  // 'l'
507         {0x6d,  0x800 | 0x4d},  // 'm'
508         {0x6e,  0x800 | 0x4e},  // 'n'
509         {0x6f,  0x800 | 0x4f},  // 'o'
510         {0x70,  0x800 | 0x50},  // 'p'
511         {0x71,  0x800 | 0x51},  // 'q'
512         {0x72,  0x800 | 0x52},  // 'r'
513         {0x73,  0x800 | 0x53},  // 's'
514         {0x74,  0x800 | 0x54},  // 't'
515         {0x75,  0x800 | 0x55},  // 'u'
516         {0x76,  0x800 | 0x56},  // 'v'
517         {0x77,  0x800 | 0x57},  // 'w'
518         {0x78,  0x800 | 0x58},  // 'x'
519         {0x79,  0x800 | 0x59},  // 'y'
520         {0x7a,  0x800 | 0x5a},  // 'z'
521
522         {0x7b,  0x100 | 0xc0},  // '{'
523         {0x7c,  0x100 | 0xe2},  // '|'
524         {0x7d,  0x100 | 0xdb},  // '}'
525         {0x7e,  0x100 | 0xdd},  // '~'
526
527         {0xa1,  0x300 | 0xbe},  // '
528         {0xa2,  0x300 | 0xdb},  // '
529         {0xa3,  0x300 | 0xdd},  // '
530         {0xa4,  0x300 | 0xbc},  // '
531         {0xa5,  0x300 | 0xbf},  // '・'
532         {0xa6,  0x300 | 0x30},  // 'ヲ'
533         {0xa7,  0x300 | 0x33},  // 'ァ'
534         {0xa8,  0x300 | 0x45},  // 'ィ'
535         {0xa9,  0x300 | 0x34},  // 'ゥ'
536         {0xaa,  0x300 | 0x35},  // 'ェ'
537         {0xab,  0x300 | 0x36},  // 'ォ'
538         {0xac,  0x300 | 0x37},  // 'ャ'
539         {0xad,  0x300 | 0x38},  // 'ュ'
540         {0xae,  0x300 | 0x39},  // 'ョ'
541         {0xaf,  0x300 | 0x5a},  // 'ッ'
542         {0xb0,  0x200 | 0xdc},  // 'ー'
543         {0xb1,  0x200 | 0x33},  // 'ア'
544         {0xb2,  0x200 | 0x45},  // 'イ'
545         {0xb3,  0x200 | 0x34},  // 'ウ'
546         {0xb4,  0x200 | 0x35},  // 'エ'
547         {0xb5,  0x200 | 0x36},  // 'オ'
548         {0xb6,  0x200 | 0x54},  // 'カ'
549         {0xb7,  0x200 | 0x47},  // 'キ'
550         {0xb8,  0x200 | 0x48},  // 'ク'
551         {0xb9,  0x200 | 0xba},  // 'ケ'
552         {0xba,  0x200 | 0x42},  // 'コ'
553         {0xbb,  0x200 | 0x58},  // 'サ'
554         {0xbc,  0x200 | 0x44},  // 'シ'
555         {0xbd,  0x200 | 0x52},  // 'ス'
556         {0xbe,  0x200 | 0x50},  // 'セ'
557         {0xbf,  0x200 | 0x43},  // 'ソ'
558         {0xc0,  0x200 | 0x51},  // 'タ'
559         {0xc1,  0x200 | 0x41},  // 'チ'
560         {0xc2,  0x200 | 0x5a},  // 'ツ'
561         {0xc3,  0x200 | 0x57},  // 'テ'
562         {0xc4,  0x200 | 0x53},  // 'ト'
563         {0xc5,  0x200 | 0x55},  // 'ナ'
564         {0xc6,  0x200 | 0x49},  // 'ニ'
565         {0xc7,  0x200 | 0x31},  // 'ヌ'
566         {0xc8,  0x200 | 0xbc},  // 'ネ'
567         {0xc9,  0x200 | 0x4b},  // 'ノ'
568         {0xca,  0x200 | 0x46},  // 'ハ'
569         {0xcb,  0x200 | 0x56},  // 'ヒ'
570         {0xcc,  0x200 | 0x32},  // 'フ'
571         {0xcd,  0x200 | 0xde},  // 'ヘ'
572         {0xce,  0x200 | 0xbd},  // 'ホ'
573         {0xcf,  0x200 | 0x4a},  // 'マ'
574         {0xd0,  0x200 | 0x4e},  // 'ミ'
575         {0xd1,  0x200 | 0xdd},  // 'ム'
576         {0xd2,  0x200 | 0xbf},  // 'メ'
577         {0xd3,  0x200 | 0x4d},  // 'モ'
578         {0xd4,  0x200 | 0x37},  // 'ヤ'
579         {0xd5,  0x200 | 0x38},  // 'ユ'
580         {0xd6,  0x200 | 0x39},  // 'ヨ'
581         {0xd7,  0x200 | 0x4f},  // 'ラ'
582         {0xd8,  0x200 | 0x4c},  // 'リ'
583         {0xd9,  0x200 | 0xbe},  // 'ル'
584         {0xda,  0x200 | 0xbb},  // 'レ'
585         {0xdb,  0x200 | 0xe2},  // 'ロ'
586         {0xdc,  0x200 | 0x30},  // 'ワ'
587         {0xdd,  0x200 | 0x59},  // 'ン'
588         {0xde,  0x200 | 0xc0},  // '゙'
589         {0xdf,  0x200 | 0xdb},  // '゚'
590         {-1, -1},
591 };
592
593 void EmuThreadClass::do_start_auto_key(QString ctext)
594 {
595 #ifdef USE_AUTO_KEY
596         if(using_flags->is_use_auto_key()) {
597                 QTextCodec *codec = QTextCodec::codecForName("Shift-Jis");
598                 QByteArray array;
599                 clipBoardText = ctext;
600                 array = codec->fromUnicode(clipBoardText);
601                 if(clipBoardText.size() > 0) {
602                         static int auto_key_table[256];
603                         static bool initialized = false;
604                         if(!initialized) {
605                                 memset(auto_key_table, 0, sizeof(auto_key_table));
606                                 if(using_flags->is_use_auto_key_us()) {
607                                         for(int i = 0;; i++) {
608                                                 if(auto_key_table_base_us[i][0] == -1) {
609                                                         break;
610                                                 }
611                                                 auto_key_table[auto_key_table_base_us[i][0]] = auto_key_table_base_us[i][1];
612                                         }
613                                 } else {
614                                         for(int i = 0;; i++) {
615                                                 if(auto_key_table_base[i][0] == -1) {
616                                                         break;
617                                                 }
618                                                 auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
619                                         }
620                                 }
621                                 if(using_flags->is_use_vm_auto_key_table()) {
622                                         if(using_flags->is_use_auto_key_us()) {
623                                                 for(int i = 0;; i++) {
624                                                         if(auto_key_table_base_us[i][0] == -1) {
625                                                                 break;
626                                                         }
627                                                         auto_key_table[auto_key_table_base_us[i][0]] = auto_key_table_base_us[i][1];
628                                                 }
629                                         } else {
630                                                 for(int i = 0;; i++) {
631                                                         if(auto_key_table_base[i][0] == -1) {
632                                                                 break;
633                                                         }
634                                                         auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
635                                                 }
636                                         }
637                                 }
638                                 initialized = true;
639                         }
640                         
641                         FIFO* auto_key_buffer = emu->get_auto_key_buffer();
642                         auto_key_buffer->clear();
643                         
644                         int size = strlen(array.constData()), prev_kana = 0;
645                         const char *buf = (char *)(array.constData());
646                         
647                         for(int i = 0; i < size; i++) {
648                                 int code = buf[i] & 0xff;
649                                 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
650                                         i++;    // kanji ?
651                                         continue;
652                                 }
653                                 // Effect [Enter] even Unix etc.(0x0a should not be ignored). 
654                                 //else if(code == 0xa) { 
655                                 //continue;     // cr-lf
656                                 //}
657                                 if((code = auto_key_table[code]) != 0) {
658                                         int kana = code & 0x200;
659                                         if(prev_kana != kana) {
660                                                 auto_key_buffer->write(0xf2);
661                                         }
662                                         prev_kana = kana;
663                                         if(using_flags->is_use_auto_key_no_caps()) {
664                                                 if((code & 0x100) && !(code & (0x400 | 0x800))) {
665                                                         auto_key_buffer->write((code & 0xff) | 0x100);
666                                                 } else {
667                                                         auto_key_buffer->write(code & 0xff);
668                                                 }
669                                         } else if(using_flags->is_use_auto_key_caps()) {
670                                                 if(code & (0x100 | 0x800)) {
671                                                         auto_key_buffer->write((code & 0xff) | 0x100);
672                                                 } else {
673                                                         auto_key_buffer->write(code & 0xff);
674                                                 }
675                                         } else if(code & (0x100 | 0x400)) {
676                                                 auto_key_buffer->write((code & 0xff) | 0x100);
677                                         } else {
678                                                 auto_key_buffer->write(code & 0xff);
679                                         }
680                                 }
681                         }
682                         
683                         if(prev_kana) {
684                                 auto_key_buffer->write(0xf2);
685                         }
686                         p_emu->stop_auto_key();
687                         p_emu->start_auto_key();
688                 }
689         }
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 = using_flags->get_config_ptr()->opengl_scanline_vert;
1170         bool horiz_line_bak = using_flags->get_config_ptr()->opengl_scanline_horiz;
1171         bool gl_crt_filter_bak = using_flags->get_config_ptr()->use_opengl_filters;
1172         int opengl_filter_num_bak = using_flags->get_config_ptr()->opengl_filter_num;
1173         //uint32_t key_mod_old = 0xffffffff;
1174         int no_draw_count = 0;  
1175         bool prevRecordReq;
1176
1177         doing_debug_command = false;
1178         
1179         ctext.clear();
1180         draw_timing = false;
1181         bResetReq = false;
1182         bSpecialResetReq = false;
1183         bLoadStateReq = false;
1184         bSaveStateReq = false;
1185         bUpdateConfigReq = false;
1186         bStartRecordSoundReq = false;
1187         bStopRecordSoundReq = false;
1188         bStartRecordMovieReq = false;
1189         record_fps = -1;
1190
1191         next_time = 0;
1192         mouse_flag = false;
1193
1194         key_repeat = false;
1195         key_down_code = 0;
1196         key_up_code = 0;
1197         key_mod_code = 0;
1198         key_changed = false;
1199 #if defined(USE_QD1)
1200         for(int i = 0; i < 2; i++) qd_text[i].clear();
1201 #endif
1202 #if defined(USE_FD1)
1203         for(int i = 0; i < MAX_FD; i++) fd_text[i].clear();
1204 #endif
1205 #if defined(USE_TAPE)
1206         cmt_text.clear();
1207 #endif
1208 #if defined(USE_COMPACT_DISC)
1209         cdrom_text.clear();
1210 #endif
1211 #if defined(USE_BUBBLE1)
1212         for(int i = 0; i < MAX_BUBBLE; i++) bubble_text[i].clear();
1213 #endif
1214         
1215         do {
1216                 //p_emu->SetHostCpus(this->idealThreadCount());
1217                 if(MainWindow == NULL) {
1218                         if(bRunThread == false){
1219                                 goto _exit;
1220                         }
1221                         msleep(10);
1222                         continue;
1223                 }
1224                 if(first) {
1225 #ifdef USE_LED_DEVICE
1226                         emit sig_send_data_led((quint32)led_data);
1227 #endif
1228                         first = false;
1229                 }
1230                 interval = 0;
1231                 sleep_period = 0;
1232                 if(p_emu) {
1233                         // drive machine
1234 #ifdef USE_STATE
1235                         if(bLoadStateReq != false) {
1236                                 p_emu->load_state();
1237                                 bLoadStateReq = false;
1238                                 req_draw = true;
1239                         }
1240 #endif                  
1241                         if(bResetReq != false) {
1242                                 p_emu->reset();
1243                                 bResetReq = false;
1244                                 req_draw = true;
1245                         }
1246 #ifdef USE_SPECIAL_RESET
1247                         if(bSpecialResetReq != false) {
1248                                 p_emu->special_reset();
1249                                 bSpecialResetReq = false;
1250                         }
1251 #endif
1252 #ifdef USE_STATE
1253                         if(bSaveStateReq != false) {
1254                                 p_emu->save_state();
1255                                 bSaveStateReq = false;
1256                         }
1257 #endif
1258 #if defined(USE_MINIMUM_RENDERING)
1259                         if((vert_line_bak != p_config->opengl_scanline_vert) ||
1260                            (horiz_line_bak != p_config->opengl_scanline_horiz) ||
1261                            (gl_crt_filter_bak != p_config->use_opengl_filters) ||
1262                            (opengl_filter_num_bak != p_config->opengl_filter_num)) req_draw = true;
1263                         vert_line_bak = p_config->opengl_scanline_vert;
1264                         horiz_line_bak = p_config->opengl_scanline_horiz;
1265                         gl_crt_filter_bak = p_config->use_opengl_filters;
1266                         opengl_filter_num_bak = p_config->opengl_filter_num;
1267 #endif
1268                         if(bStartRecordSoundReq != false) {
1269                                 p_emu->start_record_sound();
1270                                 bStartRecordSoundReq = false;
1271                                 req_draw = true;
1272                         }
1273                         if(bStopRecordSoundReq != false) {
1274                                 p_emu->stop_record_sound();
1275                                 bStopRecordSoundReq = false;
1276                                 req_draw = true;
1277                         }
1278                         if(bUpdateConfigReq != false) {
1279                                 p_emu->update_config();
1280                                 bUpdateConfigReq = false;
1281                                 req_draw = true;
1282                         }
1283                         if(bStartRecordMovieReq != false) {
1284                                 if(!prevRecordReq && (record_fps > 0) && (record_fps < 75)) {           
1285                                         p_emu->start_record_video(record_fps);
1286                                         prevRecordReq = true;
1287                                 }
1288                         } else {
1289                                 if(prevRecordReq) {
1290                                         p_emu->stop_record_video();
1291                                         record_fps = -1;
1292                                         prevRecordReq = false;
1293                                 }
1294                         }
1295                    
1296                    
1297
1298 #if defined(USE_MOUSE)  // Will fix
1299                         emit sig_is_enable_mouse(p_emu->is_mouse_enabled());
1300 #endif                  
1301 #if defined(USE_SOUND_VOLUME)
1302                         for(int ii = 0; ii < USE_SOUND_VOLUME; ii++) {
1303                                 if(bUpdateVolumeReq[ii]) {
1304                                         p_emu->set_sound_device_volume(ii, p_config->sound_volume_l[ii], p_config->sound_volume_r[ii]);
1305                                         bUpdateVolumeReq[ii] = false;
1306                                 }
1307                         }
1308 #endif
1309                         if(key_changed) {
1310                                 p_emu->key_modifiers(key_mod_code);
1311                                 key_changed = false;
1312                         }
1313                         if(key_down_code != 0) {
1314                                 p_emu->key_down(key_down_code, key_repeat);
1315                                 key_down_code = 0;
1316                         }
1317                         if(key_up_code != 0) {
1318                                 p_emu->key_modifiers(key_mod_code);
1319                                 p_emu->key_up(key_up_code);
1320                                 key_up_code = 0;
1321                         }
1322                         
1323                         run_frames = p_emu->run();
1324                         total_frames += run_frames;
1325 #if defined(USE_MINIMUM_RENDERING)
1326                         req_draw |= p_emu->is_screen_changed();
1327 #else
1328                         req_draw = true;
1329 #endif                  
1330 #ifdef USE_LED_DEVICE
1331                         led_data = p_emu->get_led_status();
1332                         if(led_data != led_data_old) {
1333                                 emit sig_send_data_led((quint32)led_data);
1334                                 led_data_old = led_data;
1335                         }
1336 #endif
1337                         sample_access_drv();
1338
1339                         interval += get_interval();
1340                         now_skip = p_emu->is_frame_skippable() && !p_emu->is_video_recording();
1341
1342                         if((prev_skip && !now_skip) || next_time == 0) {
1343                                 next_time = tick_timer.elapsed();
1344                         }
1345                         if(!now_skip) {
1346                                 next_time += interval;
1347                         }
1348                         prev_skip = now_skip;
1349                         //printf("p_emu::RUN Frames = %d SKIP=%d Interval = %d NextTime = %d\n", run_frames, now_skip, interval, next_time);
1350                         if(next_time > tick_timer.elapsed()) {
1351                                 //  update window if enough time
1352                                 draw_timing = false;
1353                                 if(!req_draw) {
1354                                         no_draw_count++;
1355                                         if(no_draw_count > (int)(FRAMES_PER_SEC / 4)) {
1356                                                 req_draw = true;
1357                                                 no_draw_count = 0;
1358                                         }
1359                                 } else {
1360                                         no_draw_count = 0;
1361                                 }
1362                                 //p_emu->draw_screen();
1363                                 emit sig_draw_thread(req_draw);
1364                                 skip_frames = 0;
1365                         
1366                                 // sleep 1 frame priod if need
1367                                 current_time = tick_timer.elapsed();
1368                                 if((int)(next_time - current_time) >= 10) {
1369                                         sleep_period = next_time - current_time;
1370                                 }
1371                         } else if(++skip_frames > MAX_SKIP_FRAMES) {
1372                                 // update window at least once per 10 frames
1373                                 draw_timing = false;
1374                                 emit sig_draw_thread(true);
1375                                 no_draw_count = 0;
1376                                 skip_frames = 0;
1377                                 qint64 tt = tick_timer.elapsed();
1378                                 next_time = tt + get_interval();
1379                                 sleep_period = next_time - tt;
1380                         }
1381                 }
1382                 req_draw = false;
1383                 if(bRunThread == false){
1384                         goto _exit;
1385                 }
1386                 if(sleep_period <= 0) sleep_period = 1;
1387                 msleep(sleep_period);
1388         } while(1);
1389 _exit:
1390         //emit quit_draw_thread();
1391         AGAR_DebugLog(AGAR_LOG_DEBUG, "EmuThread : EXIT");
1392         emit sig_finished();
1393         this->quit();
1394 }
1395
1396 void EmuThreadClass::doSetDisplaySize(int w, int h, int ww, int wh)
1397 {
1398         p_emu->suspend();
1399         //p_emu->set_vm_screen_size(w, h, -1, -1, ww, wh);
1400         p_emu->set_host_window_size(w, h, true);
1401 }
1402
1403 void EmuThreadClass::doUpdateVolumeLevel(int num, int level)
1404 {
1405 #if defined(USE_SOUND_VOLUME)
1406         if((num < USE_SOUND_VOLUME) && (num >= 0)) {
1407                 calc_volume_from_level(num, level);
1408                 bUpdateVolumeReq[num] = true;
1409         }
1410 #endif  
1411 }
1412
1413 void EmuThreadClass::doUpdateVolumeBalance(int num, int level)
1414 {
1415 #if defined(USE_SOUND_VOLUME)
1416         if((num < USE_SOUND_VOLUME) && (num >= 0)) {
1417                 calc_volume_from_balance(num, level);
1418                 bUpdateVolumeReq[num] = true;
1419         }
1420 #endif  
1421 }
1422
1423
1424 void EmuThreadClass::doUpdateConfig()
1425 {
1426         bUpdateConfigReq = true;
1427 }
1428
1429 void EmuThreadClass::doStartRecordSound()
1430 {
1431         bStartRecordSoundReq = true;
1432 }
1433
1434 void EmuThreadClass::doStopRecordSound()
1435 {
1436         bStopRecordSoundReq = true;
1437 }
1438
1439 void EmuThreadClass::doReset()
1440 {
1441         bResetReq = true;
1442 }
1443
1444 void EmuThreadClass::doSpecialReset()
1445 {
1446         bSpecialResetReq = true;
1447 }
1448
1449 void EmuThreadClass::doLoadState()
1450 {
1451         bLoadStateReq = true;
1452 }
1453
1454 void EmuThreadClass::doSaveState()
1455 {
1456         bSaveStateReq = true;
1457 }
1458
1459 void EmuThreadClass::doStartRecordVideo(int fps)
1460 {
1461         record_fps = fps;
1462         bStartRecordMovieReq = true;
1463 }
1464
1465 void EmuThreadClass::doStopRecordVideo()
1466 {
1467         bStartRecordMovieReq = false;
1468 }
1469
1470
1471 // Debugger
1472 #if defined(USE_DEBUGGER)
1473 extern int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932);
1474 #endif
1475 void EmuThreadClass::do_call_debugger_command(QString s)
1476 {
1477 #if defined(USE_DEBUGGER)
1478         _TCHAR command[MAX_COMMAND_LEN + 1];
1479
1480         if(doing_debug_command) {
1481                 emit sig_debugger_input(s);
1482                 return;
1483         }
1484         memset(command, 0x00, MAX_COMMAND_LEN + 1);
1485         if(s.isEmpty()) {
1486                 strncpy(command, dbg_prev_command, MAX_COMMAND_LEN);
1487         } else {
1488                 strncpy(command, s.toUtf8().constData(), MAX_COMMAND_LEN);
1489         }
1490         doing_debug_command = true;
1491         if(debugger_command(&(p_emu->debugger_thread_param), command, dbg_prev_command, false) < 0) {
1492                 do_close_debugger();
1493         }
1494         doing_debug_command = false;
1495 #endif
1496 }
1497
1498 void EmuThreadClass::do_close_debugger(void)
1499 {
1500 #if defined(USE_DEBUGGER)
1501         emit sig_quit_debugger();
1502 #endif
1503 }
1504
1505 bool EmuThreadClass::now_debugging() {
1506 #if defined(USE_DEBUGGER)
1507         return p_emu->now_debugging;
1508 #else
1509         return false;
1510 #endif
1511 }