OSDN Git Service

[Thread][Qt] Fix segfault on quiting.
[csp-qt/common_source_project-fm7.git] / source / src / qt / common / emu_input.cpp
1 /*
2  *      Skelton for retropc emulator
3  *
4  *      Author : Takeda.Toshiya
5  *      Date   : 2006.08.18 -
6  *      Converted to QT by (C) 2015 K.Ohta
7  *         History:
8  *            Jan 12, 2015 (maybe) : Initial
9  *      [ SDL input -> Keyboard]
10 */
11
12 #include <Qt>
13 #include <SDL2/SDL.h>
14 #include "emu.h"
15 #include "vm/vm.h"
16 #include "fifo.h"
17 #include "fileio.h"
18 #include "qt_input.h"
19 #include "qt_gldraw.h"
20 #include "qt_main.h"
21 #include "menuclasses.h"
22 #include "agar_logger.h"
23
24 #ifndef Ulong
25 #define Ulong unsigned long
26 #endif
27
28 #define KEY_KEEP_FRAMES 3
29
30 extern EMU* emu;
31
32 struct SDLKeyTable  SDLKeyMappings[] = {
33         { '0',                  SDL_SCANCODE_0 },
34         { '1',                  SDL_SCANCODE_1 },
35         { '2',                  SDL_SCANCODE_2 },
36         { '3',                  SDL_SCANCODE_3 },
37         { '4',                  SDL_SCANCODE_4 },
38         { '5',                  SDL_SCANCODE_5 },
39         { '6',                  SDL_SCANCODE_6 },
40         { '7',                  SDL_SCANCODE_7 },
41         { '8',                  SDL_SCANCODE_8 },
42         { '9',                  SDL_SCANCODE_9 },
43         { 'A',                  SDL_SCANCODE_A },
44         { 'B',                  SDL_SCANCODE_B },
45         { 'C',                  SDL_SCANCODE_C },
46         { 'D',                  SDL_SCANCODE_D },
47         { 'E',                  SDL_SCANCODE_E },
48         { 'F',                  SDL_SCANCODE_F },
49         { 'G',                  SDL_SCANCODE_G },
50         { 'H',                  SDL_SCANCODE_H },
51         { 'I',                  SDL_SCANCODE_I },
52         { 'J',                  SDL_SCANCODE_J },
53         { 'K',                  SDL_SCANCODE_K },
54         { 'L',                  SDL_SCANCODE_L },
55         { 'M',                  SDL_SCANCODE_M },
56         { 'N',                  SDL_SCANCODE_N },
57         { 'O',                  SDL_SCANCODE_O },
58         { 'P',                  SDL_SCANCODE_P },
59         { 'Q',                  SDL_SCANCODE_Q },
60         { 'R',                  SDL_SCANCODE_R },
61         { 'S',                  SDL_SCANCODE_S },
62         { 'T',                  SDL_SCANCODE_T },
63         { 'U',                  SDL_SCANCODE_U },
64         { 'V',                  SDL_SCANCODE_V },
65         { 'W',                  SDL_SCANCODE_W },
66         { 'X',                  SDL_SCANCODE_X },
67         { 'Y',                  SDL_SCANCODE_Y },
68         { 'Z',                  SDL_SCANCODE_Z },
69         // Start Qt's workaround: Qt returns character directry when keyin/out.
70         // Excepts(maybe) 'a' to 'z'?
71         // So, you should change keycode, using other than 109 / 106 Keyboard.
72 //        {0xBA,                        SDL_SCANCODE_ASTERISK}, // $2a
73 //        {0xBB,                        SDL_SCANCODE_PLUS}, // $2b
74 //        {0xBC,                  SDL_SCANCODE_LESS}, // ,
75 //        {0xBD,                  SDL_SCANCODE_CARET}, // ^~
76 //        {0xBE,                  SDL_SCANCODE_GREATER}, //$2e
77 //        {0xBF,                  SDL_SCANCODE_QUSETION}, //$2f
78         //{0xC0,                  SDL_SCANCODE_BACKQUOTE}, //`
79 //        {0xE2,                        SDL_SCANCODE_UNDERSCORE},//_\
80         {0xE2,                  SDL_SCANCODE_INTERNATIONAL3},//_\
81         // End.
82         { VK_F1,                SDL_SCANCODE_F1 },
83         { VK_F2,                SDL_SCANCODE_F2 },
84         { VK_F3,                SDL_SCANCODE_F3 },
85         { VK_F4,                SDL_SCANCODE_F4 },
86         { VK_F5,                SDL_SCANCODE_F5 },
87         { VK_F6,                SDL_SCANCODE_F6 },
88         { VK_F7,                SDL_SCANCODE_F7 },
89         { VK_F8,                SDL_SCANCODE_F8 },
90         { VK_F9,                SDL_SCANCODE_F9 },
91         { VK_F10,               SDL_SCANCODE_F10 },
92         { VK_F11,               SDL_SCANCODE_F11 },
93         { VK_F12,               SDL_SCANCODE_F12 },
94         { VK_F13,               SDL_SCANCODE_F13 },
95         { VK_F14,               SDL_SCANCODE_F14 },
96         { VK_F15,               SDL_SCANCODE_F15 },
97         { VK_BACK,              SDL_SCANCODE_BACKSPACE },
98         { VK_TAB,               SDL_SCANCODE_TAB },
99         { VK_CLEAR,             SDL_SCANCODE_CLEAR },
100         { VK_RETURN,            SDL_SCANCODE_RETURN },
101         { VK_PAUSE,             SDL_SCANCODE_PAUSE },
102         { VK_ESCAPE,            SDL_SCANCODE_ESCAPE },
103         { VK_SPACE,             SDL_SCANCODE_SPACE },
104         { VK_DELETE,            SDL_SCANCODE_DELETE },
105         { VK_UP,                SDL_SCANCODE_UP },
106         { VK_DOWN,              SDL_SCANCODE_DOWN},
107         { VK_RIGHT,             SDL_SCANCODE_RIGHT },
108         { VK_LEFT,              SDL_SCANCODE_LEFT },
109         { VK_INSERT,            SDL_SCANCODE_INSERT },
110         { VK_HOME,              SDL_SCANCODE_HOME },
111         { VK_END,               SDL_SCANCODE_END },
112         { VK_PRIOR,             SDL_SCANCODE_PAGEUP },
113         { VK_NEXT,              SDL_SCANCODE_PAGEDOWN },
114
115         { VK_NUMPAD0,           SDL_SCANCODE_KP_0 },
116         { VK_NUMPAD1,           SDL_SCANCODE_KP_1 },
117         { VK_NUMPAD2,           SDL_SCANCODE_KP_2 },
118         { VK_NUMPAD3,           SDL_SCANCODE_KP_3 },
119         { VK_NUMPAD4,           SDL_SCANCODE_KP_4 },
120         { VK_NUMPAD5,           SDL_SCANCODE_KP_5 },
121         { VK_NUMPAD6,           SDL_SCANCODE_KP_6 },
122         { VK_NUMPAD7,           SDL_SCANCODE_KP_7 },
123         { VK_NUMPAD8,           SDL_SCANCODE_KP_8 },
124         { VK_NUMPAD9,           SDL_SCANCODE_KP_9 },
125
126         { VK_DECIMAL,           SDL_SCANCODE_KP_PERIOD },
127         { VK_DIVIDE,            SDL_SCANCODE_KP_DIVIDE},
128         { VK_MULTIPLY,          SDL_SCANCODE_KP_MULTIPLY },
129         { VK_SUBTRACT,          SDL_SCANCODE_KP_MINUS },
130         { VK_ADD,               SDL_SCANCODE_KP_PLUS },
131
132         { VK_NUMLOCK,           SDL_SCANCODE_NUMLOCKCLEAR },
133 //      { VK_CAPITAL,           SDL_SCANCODE_Henkan }, // Need check
134         { VK_CAPITAL,           SDL_SCANCODE_CAPSLOCK}, // Need check
135         { VK_SCROLL,            SDL_SCANCODE_SCROLLLOCK },
136 //      { VK_SHIFT,             SDL_SCANCODE_LSHIFT }, // Left
137         { VK_RSHIFT,            SDL_SCANCODE_RSHIFT }, // Right
138         { VK_LSHIFT,            SDL_SCANCODE_LSHIFT }, // Right
139 //      { VK_CONTROL,           SDL_SCANCODE_CTRL }, // Right
140         { VK_RCONTROL,          SDL_SCANCODE_RCTRL }, // Right
141         { VK_LCONTROL,          SDL_SCANCODE_LCTRL }, // Left
142         { VK_RMENU,             SDL_SCANCODE_RALT },  // Right
143         { VK_LMENU,             SDL_SCANCODE_LALT },  // Left
144         { VK_MENU,              SDL_SCANCODE_MENU },  // Right
145         { VK_RWIN,              SDL_SCANCODE_RGUI },
146         { VK_LWIN,              SDL_SCANCODE_LGUI },
147         { VK_HELP,              SDL_SCANCODE_HELP }, // Right?
148 #ifdef VK_PRINT
149         { VK_PRINT,             SDL_SCANCODE_PRINTSCREEN },
150 #endif
151         { VK_SNAPSHOT,          SDL_SCANCODE_PRINTSCREEN },
152         { VK_CANCEL,            SDL_SCANCODE_PAUSE },
153         { VK_APPS,              SDL_SCANCODE_APPLICATION },
154         { 0xBA,                 SDL_SCANCODE_KP_COLON },
155         { 0xBB,                 SDL_SCANCODE_SEMICOLON },
156 //        { 0xBB,                       SDL_SCANCODE_KP_SEMICOLON },
157         { 0xBC,                 SDL_SCANCODE_COMMA },
158         { 0xBD,                 SDL_SCANCODE_MINUS },//
159         { 0xBE,                 SDL_SCANCODE_PERIOD },//
160         { 0xBF,                 SDL_SCANCODE_SLASH },//
161         { 0xBB,                 SDL_SCANCODE_EQUALS },//
162         { 0xC0,                 SDL_SCANCODE_KP_AT },
163         { 0xDB,                 SDL_SCANCODE_LEFTBRACKET },//]
164         { 0xDC,                 SDL_SCANCODE_BACKSLASH },  // Okay?
165         { 0xDD,                 SDL_SCANCODE_RIGHTBRACKET }, //[
166         { 0xDE,                 SDL_SCANCODE_NONUSBACKSLASH }, // ^
167 //      { 0xDF,                 SDL_SCANCODE_QuoteLeft },
168
169         // VK_CAPITAL 
170         { 0xF0,                 SDL_SCANCODE_CAPSLOCK },
171         // VK_KANA 
172         { 0xF2,                 SDL_SCANCODE_LANG3 },
173         { 0xF2,                 SDL_SCANCODE_LANG4 },
174         // VK_KANJI 
175         { 0xF3,                 SDL_SCANCODE_LANG5 },
176 //      { 0xF4,                 SDL_SCANCODE_Hankaku },
177    
178         { 0xffffffff, 0xffffffff}
179 };
180
181
182
183
184 uint32_t convert_SDLKey2VK(uint32_t sym)
185 {
186    uint32 n = 0;
187    int i = 0;
188    do {
189       if(SDLKeyMappings[i].sdlkey == sym) {
190            n = SDLKeyMappings[i].vk;
191            break;
192       }
193       
194       i++;
195    } while(QtKeyMappings[i].vk != 0xffffffff);
196    //if((n == VK_LSHIFT) || (n == VK_RSHIFT)) n = VK_SHIFT;
197    //if((n == VK_LCTRL) || (n == VK_RCTRL)) n = VK_CONTROL;
198    //if((n == VL_RMENU) || (n == VK_RMENU)) n = VK_MENU;
199    return n;
200 }
201
202 void EMU::initialize_input()
203 {
204         // initialize status
205         memset(key_status, 0, sizeof(key_status));
206         memset(joy_status, 0, sizeof(joy_status));
207         memset(mouse_status, 0, sizeof(mouse_status));
208         
209         // initialize joysticks
210         // mouse emulation is disenabled
211         mouse_enabled = false;
212         joy_num = SDL_NumJoysticks();
213         for(int i = 0; i < joy_num && i < 2; i++) {
214            //SDL_Joystick *joycaps = SDL_JoystickOpen(i);
215            //if(joycaps != NULL) {
216            //   joy_mask[i] = (1 << SDL_JoystickNumButtons(joycaps)) - 1;
217            //   SDL_JoystickClose(joycaps);
218            //} else {
219               joy_mask[i] = 0x0f; // 4buttons
220            //}
221   
222         }
223
224         
225         // initialize keycode convert table
226         FILEIO* fio = new FILEIO();
227         if(fio->Fopen(bios_path(_T("keycode.cfg")), FILEIO_READ_BINARY)) {
228                 fio->Fread(keycode_conv, sizeof(keycode_conv), 1);
229                 fio->Fclose();
230         } else {
231                 for(int i = 0; i < 256; i++) {
232                         keycode_conv[i] = i;
233                 }
234         }
235         delete fio;
236         
237 #ifdef USE_SHIFT_NUMPAD_KEY
238         // initialize shift+numpad conversion
239         memset(key_converted, 0, sizeof(key_converted));
240         key_shift_pressed = key_shift_released = false;
241 #endif
242 #ifdef USE_AUTO_KEY
243         // initialize autokey
244         autokey_buffer = new FIFO(65536);
245         autokey_buffer->clear();
246         autokey_phase = autokey_shift = 0;
247 #endif
248         lost_focus = false;
249 }
250
251 void EMU::release_input()
252 {
253         // release mouse
254         if(mouse_enabled) {
255                 disenable_mouse();
256         }
257         
258 #ifdef USE_AUTO_KEY
259         // release autokey buffer
260         if(autokey_buffer) {
261                 autokey_buffer->release();
262                 delete autokey_buffer;
263         }
264 #endif
265 }
266
267
268 void EMU::update_input()
269 {
270
271     int *keystat;
272     int i_c = 0;;
273    
274         // release keys
275 #ifdef USE_AUTO_KEY
276         if(lost_focus && autokey_phase == 0) {
277 #else
278         if(lost_focus) {
279 #endif
280                 // we lost key focus so release all pressed keys
281                 for(int i = 0; i < 256; i++) {
282                         if(key_status[i] & 0x80) {
283                                 key_status[i] &= 0x7f;
284 #ifdef NOTIFY_KEY_DOWN
285                                 if(!key_status[i]) {
286                                         vm->key_up(i);
287                                 }
288 #endif
289                         }
290                 }
291         } else {
292                 for(int i = 0; i < 256; i++) {
293                         if(key_status[i] & 0x7f) {
294                                 key_status[i] = (key_status[i] & 0x80) | ((key_status[i] & 0x7f) - 1);
295 #ifdef NOTIFY_KEY_DOWN
296                                 if(!key_status[i]) {
297                                         vm->key_up(i);
298                                 }
299 #endif
300                         }
301                 }
302         }
303         lost_focus = false;
304 #if 1   
305         // update joystick status
306 #ifdef USE_KEY_TO_JOY
307         // emulate joystick #1 with keyboard
308         if(key_status[0x26]) joy_status[0] |= 0x01;     // up
309         if(key_status[0x28]) joy_status[0] |= 0x02;     // down
310         if(key_status[0x25]) joy_status[0] |= 0x04;     // left
311         if(key_status[0x27]) joy_status[0] |= 0x08;     // right
312 #ifdef KEY_TO_JOY_BUTTON_U
313         if(key_status[KEY_TO_JOY_BUTTON_U]) joy_status[0] |= 0x01;
314 #endif
315 #ifdef KEY_TO_JOY_BUTTON_D
316         if(key_status[KEY_TO_JOY_BUTTON_D]) joy_status[0] |= 0x02;
317 #endif
318 #ifdef KEY_TO_JOY_BUTTON_L
319         if(key_status[KEY_TO_JOY_BUTTON_L]) joy_status[0] |= 0x04;
320 #endif
321 #ifdef KEY_TO_JOY_BUTTON_R
322         if(key_status[KEY_TO_JOY_BUTTON_R]) joy_status[0] |= 0x08;
323 #endif
324 #ifdef KEY_TO_JOY_BUTTON_1
325         if(key_status[KEY_TO_JOY_BUTTON_1]) joy_status[0] |= 0x10;
326 #endif
327 #ifdef KEY_TO_JOY_BUTTON_2
328         if(key_status[KEY_TO_JOY_BUTTON_2]) joy_status[0] |= 0x20;
329 #endif
330 #ifdef KEY_TO_JOY_BUTTON_3
331         if(key_status[KEY_TO_JOY_BUTTON_3]) joy_status[0] |= 0x40;
332 #endif
333 #ifdef KEY_TO_JOY_BUTTON_4
334         if(key_status[KEY_TO_JOY_BUTTON_4]) joy_status[0] |= 0x80;
335 #endif
336 #endif
337
338 #endif
339         // update mouse status
340         memset(mouse_status, 0, sizeof(mouse_status));
341 #if 0
342            if(mouse_enabled) {
343                 // get current status
344                 POINT pt;
345                 GetCursorPos(&pt);
346                 ScreenToClient(main_window_handle, &pt);
347                 mouse_status[0]  = pt.x - display_width / 2;
348                 mouse_status[1]  = pt.y - display_height / 2;
349                 mouse_status[2]  = (GetAsyncKeyState(VK_LBUTTON, modkey_status) & 0x8000) ? 1 : 0;
350                 mouse_status[2] |= (GetAsyncKeyState(VK_RBUTTON, modkey_status) & 0x8000) ? 2 : 0;
351                 mouse_status[2] |= (GetAsyncKeyState(VK_MBUTTON, modkey_status) & 0x8000) ? 4 : 0;
352                  move mouse cursor to the center of window
353                 if(!(mouse_status[0] == 0 && mouse_status[1] == 0)) {
354                         pt.x = display_width / 2;
355                         pt.y = display_height / 2;
356                 //      ClientToScreen(main_window_handle, &pt);
357                 //      SetCursorPos(pt.x, pt.y);
358                 }
359         }
360 #endif
361
362 #if 0
363 #ifdef USE_AUTO_KEY
364         // auto key
365         switch(autokey_phase) {
366         case 1:
367                 if(autokey_buffer && !autokey_buffer->empty()) {
368                         // update shift key status
369                         int shift = autokey_buffer->read_not_remove(0) & 0x100;
370                         if(shift && !autokey_shift) {
371                                 key_down(VK_SHIFT, false);
372                         } else if(!shift && autokey_shift) {
373                                 key_up(VK_SHIFT);
374                         }
375                         autokey_shift = shift;
376                         autokey_phase++;
377                         break;
378                 }
379         case 3:
380                 if(autokey_buffer && !autokey_buffer->empty()) {
381                         key_down(autokey_buffer->read_not_remove(0) & 0xff, false);
382                 }
383                 autokey_phase++;
384                 break;
385         case USE_AUTO_KEY:
386                 if(autokey_buffer && !autokey_buffer->empty()) {
387                         key_up(autokey_buffer->read_not_remove(0) & 0xff);
388                 }
389                 autokey_phase++;
390                 break;
391         case USE_AUTO_KEY_RELEASE:
392                 if(autokey_buffer && !autokey_buffer->empty()) {
393                         // wait enough while vm analyzes one line
394                         if(autokey_buffer->read() == 0xd) {
395                                 autokey_phase++;
396                                 break;
397                         }
398                 }
399         case 30:
400                 if(autokey_buffer && !autokey_buffer->empty()) {
401                         autokey_phase = 1;
402                 } else {
403                         stop_auto_key();
404                 }
405                 break;
406         default:
407                 if(autokey_phase) {
408                         autokey_phase++;
409                 }
410         }
411 #endif
412 #endif
413         }
414
415
416
417 #ifdef USE_SHIFT_NUMPAD_KEY
418 static const int numpad_table[256] = {
419         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
420         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 //      0x00, 0x69, 0x63, 0x61, 0x67, 0x64, 0x68, 0x66, 0x62, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0x00,
422         0x00, 0x69, 0x63, 0x61, 0x67, 0x64, 0x68, 0x66, 0x62, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, // remove shift + period
423         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
436 };
437 #endif
438
439 void EMU::key_down(int sym, bool repeat)
440 {
441         bool keep_frames = false;
442         uint8 code = sym;
443 //        code = convert_AGKey2VK(sym);
444
445          //printf("Key down %08x\n", sym);
446
447 #if 1  // No needed with SDL?
448        if(code == VK_SHIFT) {
449 #ifndef USE_SHIFT_NUMPAD_KEY
450 //              if(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000) key_status[VK_LSHIFT] = 0x80;
451 //              if(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000) key_status[VK_RSHIFT] = 0x80;
452 //              if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
453 #endif
454         } else if(code == VK_CONTROL) {
455                 if(GetAsyncKeyState(VK_LCONTROL, modkey_status) & 0x8000) key_status[VK_LCONTROL] = 0x80;
456                 if(GetAsyncKeyState(VK_RCONTROL, modkey_status) & 0x8000) key_status[VK_RCONTROL] = 0x80;
457                 if(!(key_status[VK_LCONTROL] || key_status[VK_RCONTROL])) key_status[VK_LCONTROL] = 0x80;
458         } else if(code == VK_MENU) {
459                 if(GetAsyncKeyState(VK_LMENU, modkey_status) & 0x8000) key_status[VK_LMENU] = 0x80;
460                 if(GetAsyncKeyState(VK_RMENU, modkey_status) & 0x8000) key_status[VK_RMENU] = 0x80;
461                 if(!(key_status[VK_LMENU] || key_status[VK_RMENU])) key_status[VK_LMENU] = 0x80;
462         } else if(code == 0xf0) {
463                 code = VK_CAPITAL;
464                 keep_frames = true;
465         } else if(code == 0xf2) {
466                 code = VK_KANA;
467                 keep_frames = true;
468         } else if(code == 0xf3 || code == 0xf4) {
469                 code = VK_KANJI;
470                 keep_frames = true;
471         }
472 #else  //SDL
473        if(code == 0xf0) {
474                 code = VK_CAPITAL;
475                 keep_frames = true;
476         } else if(code == 0xf2) {
477                 code = VK_KANA;
478                 keep_frames = true;
479         } else if(code == 0xf3 || code == 0xf4) {
480                 code = VK_KANJI;
481                 keep_frames = true;
482         }
483 #endif
484    
485 # ifdef USE_SHIFT_NUMPAD_KEY
486         if(code == VK_SHIFT) {
487                 key_shift_pressed = true;
488                 return;
489         } else if(numpad_table[code] != 0) {
490                 if(key_shift_pressed || key_shift_released) {
491                         key_converted[code] = 1;
492                         key_shift_pressed = true;
493                         code = numpad_table[code];
494                 }
495         }
496 #endif
497
498        if(!(code == VK_CONTROL || code == VK_MENU)) {
499                 code = keycode_conv[code];
500         }
501         
502 #ifdef DONT_KEEEP_KEY_PRESSED
503         if(!(code == VK_CONTROL || code == VK_MENU)) {
504                 key_status[code] = KEY_KEEP_FRAMES;
505         } else
506 #endif
507      
508         key_status[code] = keep_frames ? KEY_KEEP_FRAMES : 0x80;
509 #ifdef NOTIFY_KEY_DOWN
510         if(keep_frames) {
511                 repeat = false;
512         }
513         vm->key_down(code, repeat);
514 #endif
515
516 }
517
518         
519 void EMU::key_up(int sym)
520 {
521         uint8 code = sym;
522 //        code = convert_AGKey2VK(sym);
523    //printf("Key up %03x %03x\n", sym, code);
524 #if 1
525    if(code == VK_SHIFT) {
526 #ifndef USE_SHIFT_NUMPAD_KEY
527 //              if(!(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000)) key_status[VK_LSHIFT] &= 0x7f;
528 //              if(!(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000)) key_status[VK_RSHIFT] &= 0x7f;
529 #endif
530         } else if(code == VK_CONTROL) {
531                 if(!(GetAsyncKeyState(VK_LCONTROL, modkey_status) & 0x8000)) key_status[VK_LCONTROL] &= 0x7f;
532                 if(!(GetAsyncKeyState(VK_RCONTROL, modkey_status) & 0x8000)) key_status[VK_RCONTROL] &= 0x7f;
533         } else if(code == VK_MENU) {
534                 if(!(GetAsyncKeyState(VK_LMENU, modkey_status) & 0x8000)) key_status[VK_LMENU] &= 0x7f;
535                 if(!(GetAsyncKeyState(VK_RMENU, modkey_status) & 0x8000)) key_status[VK_RMENU] &= 0x7f;
536         } else
537 #endif
538      {
539            key_status[code] &= 0x7f;
540 #ifdef NOTIFY_KEY_DOWN
541            vm->key_up(code);
542 #endif
543         }
544
545
546 #ifdef USE_SHIFT_NUMPAD_KEY
547         if(code == VK_SHIFT) {
548                 key_shift_pressed = false;
549                 key_shift_released = true;
550                 return;
551         } else if(key_converted[code] != 0) {
552                 key_converted[code] = 0;
553                 code = numpad_table[code];
554         }
555    
556 #endif
557         if(!(code == VK_SHIFT || code == VK_CONTROL || code == VK_MENU)) {
558                 code = keycode_conv[code];
559         }
560         if(key_status[code]) {
561                 key_status[code] &= 0x7f;
562 #ifdef NOTIFY_KEY_DOWN
563                 if(!key_status[code]) {
564                         vm->key_up(code);
565                 }
566 #endif
567         }
568
569 }
570
571 #ifdef USE_BUTTON
572 void EMU::press_button(int num)
573 {
574 #if 1
575         int code = buttons[num].code;
576         
577         if(code) {
578                 key_down(code, false);
579                 key_status[code] = KEY_KEEP_FRAMES;
580         } else {
581                 // code=0: reset virtual machine
582                 vm->reset();
583         }
584 #endif
585 }
586 #endif
587
588 void EMU::enable_mouse()
589 {
590         // enable mouse emulation
591         if(!mouse_enabled) {
592 #if 0
593                 // hide mouse cursor
594                 ShowCursor(FALSE);
595                 // move mouse cursor to the center of window
596                 POINT pt;
597                 pt.x = display_width / 2;
598                 pt.y = display_height / 2;
599                 ClientToScreen(main_window_handle, &pt);
600                 SetCursorPos(pt.x, pt.y);
601 #endif
602         }
603         mouse_enabled = true;
604
605 }
606
607
608
609 void EMU::disenable_mouse()
610 {
611 #if 0
612         // disenable mouse emulation
613         if(mouse_enabled) {
614                 ShowCursor(TRUE);
615         }
616 #endif
617       mouse_enabled = false;
618 }
619
620 void EMU::toggle_mouse()
621 {
622         // toggle mouse enable / disenable
623         if(mouse_enabled) {
624                 disenable_mouse();
625         } else {
626                 enable_mouse();
627         }
628 }
629
630 #ifdef USE_AUTO_KEY
631 static const int autokey_table[256] = {
632         // 0x100: shift
633         // 0x200: kana
634         // 0x400: alphabet
635         // 0x800: ALPHABET
636         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x00d,0x000,0x000,0x00d,0x000,0x000,
637         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
638         0x020,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x138,0x139,0x1ba,0x1bb,0x0bc,0x0bd,0x0be,0x0bf,
639         0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x038,0x039,0x0ba,0x0bb,0x1bc,0x1bd,0x1be,0x1bf,
640         0x0c0,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44a,0x44b,0x44c,0x44d,0x44e,0x44f,
641         0x450,0x451,0x452,0x453,0x454,0x455,0x456,0x457,0x458,0x459,0x45a,0x0db,0x0dc,0x0dd,0x0de,0x1e2,
642         0x1c0,0x841,0x842,0x843,0x844,0x845,0x846,0x847,0x848,0x849,0x84a,0x84b,0x84c,0x84d,0x84e,0x84f,
643         0x850,0x851,0x852,0x853,0x854,0x855,0x856,0x857,0x858,0x859,0x85a,0x1db,0x1dc,0x1dd,0x1de,0x000,
644         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
645         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
646         // kana -->
647         0x000,0x3be,0x3db,0x3dd,0x3bc,0x3bf,0x330,0x333,0x345,0x334,0x335,0x336,0x337,0x338,0x339,0x35a,
648         0x2dc,0x233,0x245,0x234,0x235,0x236,0x254,0x247,0x248,0x2ba,0x242,0x258,0x244,0x252,0x250,0x243,
649         0x251,0x241,0x25a,0x257,0x253,0x255,0x249,0x231,0x2bc,0x24b,0x246,0x256,0x232,0x2de,0x2bd,0x24a,
650         0x24e,0x2dd,0x2bf,0x24d,0x237,0x238,0x239,0x24f,0x24c,0x2be,0x2bb,0x2e2,0x230,0x259,0x2c0,0x2db,
651         // <--- kana
652         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
653         0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000
654 };
655
656 void EMU::start_auto_key()
657 {
658 #if 0
659         stop_auto_key();
660         
661         if(OpenClipboard(NULL)) {
662                 HANDLE hClip = GetClipboardData(CF_TEXT);
663                 if(hClip) {
664                         autokey_buffer->clear();
665                         char* buf = (char*)GlobalLock(hClip);
666                         int size = strlen(buf), prev_kana = 0;
667                         for(int i = 0; i < size; i++) {
668                                 int code = buf[i] & 0xff;
669                                 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
670                                         i++;    // kanji ?
671                                         continue;
672                                 } else if(code == 0xa) {
673                                         continue;       // cr-lf
674                                 }
675                                 if((code = autokey_table[code]) != 0) {
676                                         int kana = code & 0x200;
677                                         if(prev_kana != kana) {
678                                                 autokey_buffer->write(0xf2);
679                                         }
680                                         prev_kana = kana;
681 #if defined(USE_AUTO_KEY_NO_CAPS)
682                                         if((code & 0x100) && !(code & (0x400 | 0x800))) {
683 #elif defined(USE_AUTO_KEY_CAPS)
684                                         if(code & (0x100 | 0x800)) {
685 #else
686                                         if(code & (0x100 | 0x400)) {
687 #endif
688                                                 autokey_buffer->write((code & 0xff) | 0x100);
689                                         } else {
690                                                 autokey_buffer->write(code & 0xff);
691                                         }
692                                 }
693                         }
694                         if(prev_kana) {
695                                 autokey_buffer->write(0xf2);
696                         }
697                         GlobalUnlock(hClip);
698                         
699                         autokey_phase = 1;
700                         autokey_shift = 0;
701                 }
702                 CloseClipboard();
703         }
704 #endif
705 }
706
707 void EMU::stop_auto_key()
708 {
709 #if 1
710         if(autokey_shift) {
711                 key_up(VK_SHIFT);
712         }
713         autokey_phase = autokey_shift = 0;
714 #endif
715 }
716 #endif
717
718            
719 void JoyThreadClass::x_axis_changed(int index, int value)
720 {
721    if(p_emu == NULL) return;
722    p_emu->LockVM();
723    uint32_t *joy_status = p_emu->getJoyStatPtr();
724    
725    if(joy_status != NULL) {
726       if(value < -8192) { // left
727          joy_status[index] |= 0x04; joy_status[index] &= ~0x08;
728       } else if(value > 8192)  { // right
729          joy_status[index] |= 0x08; joy_status[index] &= ~0x04;
730       }  else { // center
731          joy_status[index] &= ~0x0c;
732       }
733    }
734    
735    p_emu->UnlockVM();
736 }
737            
738 void JoyThreadClass::y_axis_changed(int index, int value)
739 {
740    if(p_emu == NULL) return;
741    p_emu->LockVM();
742    uint32_t *joy_status = p_emu->getJoyStatPtr();
743    
744    if(joy_status != NULL) {
745       if(value < -8192) {// up
746          joy_status[index] |= 0x01; joy_status[index] &= ~0x02;
747       } else if(value > 8192)  {// down 
748          joy_status[index] |= 0x02; joy_status[index] &= ~0x01;
749       } else {
750          joy_status[index] &= ~0x03;
751       }
752    }
753    
754    p_emu->UnlockVM();
755 }
756
757 void JoyThreadClass::button_down(int index, unsigned int button)
758 {
759       if(p_emu == NULL) return;
760       p_emu->LockVM();
761       uint32_t *joy_status = p_emu->getJoyStatPtr();
762       if(joy_status != NULL) {
763          joy_status[index] |= (1 << (button + 4));
764       }
765       p_emu->UnlockVM();
766 }
767
768 void JoyThreadClass::button_up(int index, unsigned int button)
769 {
770    if(p_emu == NULL) return;
771    
772    p_emu->LockVM();
773    uint32_t *joy_status = p_emu->getJoyStatPtr();
774       if(joy_status != NULL) {
775          joy_status[index] &= ~(1 << (button + 4));
776       }
777    p_emu->UnlockVM();
778 }
779            
780 // SDL Event Handler
781 bool  JoyThreadClass::EventSDL(SDL_Event *eventQueue)
782 {
783    //   SDL_Surface *p;
784    Sint16 value;
785    unsigned int button;
786    int vk;
787    uint32_t sym;
788    int i;
789    if(eventQueue == NULL) return;
790         /*
791          * JoyStickなどはSDLが管理する
792          */
793    switch (eventQueue->type){
794     case SDL_JOYAXISMOTION:
795       value = eventQueue->jaxis.value;
796       i = eventQueue->jaxis.which;
797       if((i < 0) || (i > 1)) break;
798
799       if(eventQueue->jaxis.axis == 0) { // X
800          x_axis_changed(i, value);
801       } else if(eventQueue->jaxis.axis == 1) { // Y
802          y_axis_changed(i, value);
803       }
804       break;
805     case SDL_JOYBUTTONDOWN:
806       button = eventQueue->jbutton.button;
807       i = eventQueue->jbutton.which;
808       if((i < 0) || (i > 1)) break;
809       button_down(i, button);
810       break;
811     case SDL_JOYBUTTONUP:
812       button = eventQueue->jbutton.button;
813       i = eventQueue->jbutton.which;
814       if((i < 0) || (i > 1)) break;
815       button_up(i, button);
816       break;
817     default:
818       break;
819    }
820    return TRUE;
821 }
822
823
824 void JoyThreadClass::doWork(EMU *e)
825 {
826   int joy_num;
827   int i;
828   SDL_Joystick *joyhandle[2] = {NULL, NULL};
829   SDL_Event event;
830   p_emu = e;
831   for(i = 0; i < 2; i++) joyhandle[i] = SDL_JoystickOpen(i);
832   joy_num = SDL_NumJoysticks();
833   do {
834        if(rMainWindow->GetJoyThreadEnabled() != true) {
835           for(i = 0; i < 2; i++) {
836              if(joyhandle[i] != NULL) SDL_JoystickClose(joyhandle[i]);
837           }
838           printf("EXIT\n");
839           exit(0);
840        }
841      if(SDL_WaitEventTimeout(&event, 15) == 1) {
842         EventSDL(&event);
843      } 
844   } while(1);
845 }
846
847
848
849 void Ui_MainWindow::LaunchJoyThread(void)
850 {
851     //    bRunEmuThread = true;
852     //hRunEmuThread = SDL_CreateThread(fn, "CSP_EmuThread", (void *)this);
853     bRunJoyThread = true;
854     hRunJoy = new JoyThreadClass();
855     hRunJoyThread = new JoyThreadCore();
856     hRunJoy->moveToThread(hRunJoyThread);
857     
858     connect(this, SIGNAL(call_joy_thread(EMU *)), hRunJoy, SLOT(doWork(EMU *)));
859     connect(this, SIGNAL(quit_joy_thread()), hRunJoy, SLOT(quit()));
860 //    connect(hRunJoy, SIGNAL(x_axis_changed(int, int)),  hRunEmu, SLOT(x_axis_changed(int, int)));
861 //    connect(hRunJoy, SIGNAL(y_axis_changed(int, int)),  hRunEmu, SLOT(y_axis_changed(int, int)));
862 //    connect(hRunJoy, SIGNAL(button_down(int, unsigned int)), hRunEmu, SLOT(button_down(int, unsigned int)));
863 //    connect(hRunJoy, SIGNAL(button_up(int, unsigned int)),   hRunEmu, SLOT(button_up(int, unsigned int)));
864     hRunJoyThread->start();
865     emit call_joy_thread(emu);
866 }
867 void Ui_MainWindow::StopJoyThread(void) {
868     bRunJoyThread = false;
869     emit quit_joy_thread();
870     hRunJoyThread->wait();
871     delete hRunJoyThread;
872     delete hRunJoy;
873 }