2 * Skelton for retropc emulator
4 * Author : Takeda.Toshiya
6 * Converted to QT by (C) 2015 K.Ohta
8 * Jan 12, 2015 (maybe) : Initial
9 * [ SDL input -> Keyboard]
19 #include "qt_gldraw.h"
21 #include "menuclasses.h"
22 #include "agar_logger.h"
25 #define Ulong unsigned long
28 #define KEY_KEEP_FRAMES 3
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},//_\
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 },
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 },
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 },
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?
149 { VK_PRINT, SDL_SCANCODE_PRINTSCREEN },
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 },
170 { 0xF0, SDL_SCANCODE_CAPSLOCK },
172 { 0xF2, SDL_SCANCODE_LANG3 },
173 { 0xF2, SDL_SCANCODE_LANG4 },
175 { 0xF3, SDL_SCANCODE_LANG5 },
176 // { 0xF4, SDL_SCANCODE_Hankaku },
178 { 0xffffffff, 0xffffffff}
184 uint32_t convert_SDLKey2VK(uint32_t sym)
189 if(SDLKeyMappings[i].sdlkey == sym) {
190 n = SDLKeyMappings[i].vk;
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;
202 void EMU::initialize_input()
205 memset(key_status, 0, sizeof(key_status));
206 memset(joy_status, 0, sizeof(joy_status));
207 memset(mouse_status, 0, sizeof(mouse_status));
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);
219 joy_mask[i] = 0x0f; // 4buttons
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);
231 for(int i = 0; i < 256; i++) {
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;
243 // initialize autokey
244 autokey_buffer = new FIFO(65536);
245 autokey_buffer->clear();
246 autokey_phase = autokey_shift = 0;
251 void EMU::release_input()
259 // release autokey buffer
261 autokey_buffer->release();
262 delete autokey_buffer;
268 void EMU::update_input()
273 #ifdef USE_SHIFT_NUMPAD_KEY
274 //update numpad key status
275 if(key_shift_pressed && !key_shift_released) {
276 if(key_status[VK_SHIFT] == 0) {
277 // shift key is newly pressed
278 key_status[VK_SHIFT] = 0x80;
279 # ifdef NOTIFY_KEY_DOWN
280 vm->key_down(VK_SHIFT, false);
283 } else if(!key_shift_pressed && key_shift_released) {
284 if(key_status[VK_SHIFT] != 0) {
285 // shift key is newly released
286 key_status[VK_SHIFT] = 0;
287 # ifdef NOTIFY_KEY_DOWN
288 vm->key_up(VK_SHIFT);
291 if(!(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000)) key_status[VK_LSHIFT] &= 0x7f;
292 if(!(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000)) key_status[VK_RSHIFT] &= 0x7f;
295 key_shift_pressed = key_shift_released = false;
300 if(lost_focus && autokey_phase == 0) {
304 // we lost key focus so release all pressed keys
305 for(int i = 0; i < 256; i++) {
306 if(key_status[i] & 0x80) {
307 key_status[i] &= 0x7f;
308 #ifdef NOTIFY_KEY_DOWN
316 for(int i = 0; i < 256; i++) {
317 if(key_status[i] & 0x7f) {
318 key_status[i] = (key_status[i] & 0x80) | ((key_status[i] & 0x7f) - 1);
319 #ifdef NOTIFY_KEY_DOWN
329 // update joystick status
330 #ifdef USE_KEY_TO_JOY
331 // emulate joystick #1 with keyboard
332 if(key_status[0x26]) joy_status[0] |= 0x01; // up
333 if(key_status[0x28]) joy_status[0] |= 0x02; // down
334 if(key_status[0x25]) joy_status[0] |= 0x04; // left
335 if(key_status[0x27]) joy_status[0] |= 0x08; // right
336 #ifdef KEY_TO_JOY_BUTTON_U
337 if(key_status[KEY_TO_JOY_BUTTON_U]) joy_status[0] |= 0x01;
339 #ifdef KEY_TO_JOY_BUTTON_D
340 if(key_status[KEY_TO_JOY_BUTTON_D]) joy_status[0] |= 0x02;
342 #ifdef KEY_TO_JOY_BUTTON_L
343 if(key_status[KEY_TO_JOY_BUTTON_L]) joy_status[0] |= 0x04;
345 #ifdef KEY_TO_JOY_BUTTON_R
346 if(key_status[KEY_TO_JOY_BUTTON_R]) joy_status[0] |= 0x08;
348 #ifdef KEY_TO_JOY_BUTTON_1
349 if(key_status[KEY_TO_JOY_BUTTON_1]) joy_status[0] |= 0x10;
351 #ifdef KEY_TO_JOY_BUTTON_2
352 if(key_status[KEY_TO_JOY_BUTTON_2]) joy_status[0] |= 0x20;
354 #ifdef KEY_TO_JOY_BUTTON_3
355 if(key_status[KEY_TO_JOY_BUTTON_3]) joy_status[0] |= 0x40;
357 #ifdef KEY_TO_JOY_BUTTON_4
358 if(key_status[KEY_TO_JOY_BUTTON_4]) joy_status[0] |= 0x80;
363 // update mouse status
364 memset(mouse_status, 0, sizeof(mouse_status));
367 // get current status
370 ScreenToClient(main_window_handle, &pt);
371 mouse_status[0] = pt.x - display_width / 2;
372 mouse_status[1] = pt.y - display_height / 2;
373 mouse_status[2] = (GetAsyncKeyState(VK_LBUTTON, modkey_status) & 0x8000) ? 1 : 0;
374 mouse_status[2] |= (GetAsyncKeyState(VK_RBUTTON, modkey_status) & 0x8000) ? 2 : 0;
375 mouse_status[2] |= (GetAsyncKeyState(VK_MBUTTON, modkey_status) & 0x8000) ? 4 : 0;
376 move mouse cursor to the center of window
377 if(!(mouse_status[0] == 0 && mouse_status[1] == 0)) {
378 pt.x = display_width / 2;
379 pt.y = display_height / 2;
380 // ClientToScreen(main_window_handle, &pt);
381 // SetCursorPos(pt.x, pt.y);
389 switch(autokey_phase) {
391 if(autokey_buffer && !autokey_buffer->empty()) {
392 // update shift key status
393 int shift = autokey_buffer->read_not_remove(0) & 0x100;
394 if(shift && !autokey_shift) {
395 key_down(VK_SHIFT, false);
396 } else if(!shift && autokey_shift) {
399 autokey_shift = shift;
404 if(autokey_buffer && !autokey_buffer->empty()) {
405 key_down(autokey_buffer->read_not_remove(0) & 0xff, false);
410 if(autokey_buffer && !autokey_buffer->empty()) {
411 key_up(autokey_buffer->read_not_remove(0) & 0xff);
415 case USE_AUTO_KEY_RELEASE:
416 if(autokey_buffer && !autokey_buffer->empty()) {
417 // wait enough while vm analyzes one line
418 if(autokey_buffer->read() == 0xd) {
424 if(autokey_buffer && !autokey_buffer->empty()) {
441 #ifdef USE_SHIFT_NUMPAD_KEY
442 static const int numpad_table[256] = {
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00,
444 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 // 0x00, 0x69, 0x63, 0x61, 0x67, 0x64, 0x68, 0x66, 0x62, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0x00,
446 0x00, 0x69, 0x63, 0x61, 0x67, 0x64, 0x68, 0x66, 0x62, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, // remove shift + period
447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
463 void EMU::key_down(int sym, bool repeat)
465 bool keep_frames = false;
467 // code = convert_AGKey2VK(sym);
469 //printf("Key down %08x\n", sym);
471 #if 1 // No needed with SDL?
472 if(code == VK_SHIFT){
473 #ifndef USE_SHIFT_NUMPAD_KEY
474 // if(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000) key_status[VK_LSHIFT] = 0x80;
475 // if(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000) key_status[VK_RSHIFT] = 0x80;
476 if(GetAsyncKeyState(VK_SHIFT, modkey_status) & 0x8000) key_status[VK_LSHIFT] = 0x80;
477 if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
479 } else if(code == VK_LSHIFT){
480 #ifndef USE_SHIFT_NUMPAD_KEY
481 if(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000) key_status[VK_LSHIFT] = 0x80;
482 // if(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000) key_status[VK_RSHIFT] = 0x80;
483 if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
485 } else if(code == VK_RSHIFT){
486 #ifndef USE_SHIFT_NUMPAD_KEY
487 // if(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000) key_status[VK_LSHIFT] = 0x80;
488 if(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000) key_status[VK_RSHIFT] = 0x80;
489 if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
491 } else if(code == VK_CONTROL) {
492 if(GetAsyncKeyState(VK_LCONTROL, modkey_status) & 0x8000) key_status[VK_LCONTROL] = 0x80;
493 if(GetAsyncKeyState(VK_RCONTROL, modkey_status) & 0x8000) key_status[VK_RCONTROL] = 0x80;
494 if(!(key_status[VK_LCONTROL] || key_status[VK_RCONTROL])) key_status[VK_LCONTROL] = 0x80;
495 } else if(code == VK_MENU) {
496 if(GetAsyncKeyState(VK_LMENU, modkey_status) & 0x8000) key_status[VK_LMENU] = 0x80;
497 if(GetAsyncKeyState(VK_RMENU, modkey_status) & 0x8000) key_status[VK_RMENU] = 0x80;
498 if(!(key_status[VK_LMENU] || key_status[VK_RMENU])) key_status[VK_LMENU] = 0x80;
499 } else if(code == 0xf0) {
502 } else if(code == 0xf2) {
505 } else if(code == 0xf3 || code == 0xf4) {
510 if((code == VK_LSHIFT) || (code == VK_RSHIFT)) {
511 key_status[code] = 0x80;
512 if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
513 } else if(code == VK_SHIFT) {
514 key_status[code] = 0x80;
515 if(!(key_status[VK_LSHIFT] || key_status[VK_RSHIFT])) key_status[VK_LSHIFT] = 0x80;
516 } else if((code == VK_LCONTROL) || (code == VK_RCONTROL)) {
517 key_status[code] = 0x80;
518 } else if(code == VK_CONTROL) {
519 key_status[code] = 0x80;
520 key_status[VK_LCONTROL] = 0x80;
521 } else if((code == VK_LMENU) || (code == VK_RMENU)) {
522 key_status[code] = 0x80;
523 } else if(code == VK_MENU) {
524 key_status[code] = 0x80;
525 key_status[VK_LMENU] = 0x80;
526 } else if(code == 0xf0) {
529 } else if(code == 0xf2) {
532 } else if(code == 0xf3 || code == 0xf4) {
538 # ifdef USE_SHIFT_NUMPAD_KEY
539 if(code == VK_SHIFT) {
540 key_shift_pressed = true;
541 key_shift_released = false;
543 } else if(numpad_table[code] != 0) {
544 if(key_shift_pressed || key_shift_released) {
545 key_converted[code] = 1;
546 key_shift_pressed = true;
547 key_shift_released = false;
548 code = numpad_table[code];
553 if(!(code == VK_CONTROL || code == VK_MENU || code == VK_SHIFT)) {
554 code = keycode_conv[code];
557 #ifdef DONT_KEEEP_KEY_PRESSED
558 if(!(code == VK_CONTROL || code == VK_MENU || code == VK_SHIFT)) {
559 key_status[code] = KEY_KEEP_FRAMES;
563 key_status[code] = keep_frames ? KEY_KEEP_FRAMES : 0x80;
564 #ifdef NOTIFY_KEY_DOWN
568 vm->key_down(code, repeat);
574 void EMU::key_up(int sym)
577 // code = convert_AGKey2VK(sym);
578 //printf("Key up %03x %03x\n", sym, code);
580 if(code == VK_SHIFT) {
581 #ifndef USE_SHIFT_NUMPAD_KEY
582 if(!(GetAsyncKeyState(VK_SHIFT, modkey_status) & 0x8000)) key_status[VK_LSHIFT] &= 0x7f;
583 // if(!(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000)) key_status[VK_RSHIFT] &= 0x7f;
585 } else if(code == VK_LSHIFT) {
586 #ifndef USE_SHIFT_NUMPAD_KEY
587 if(!(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000)) key_status[VK_LSHIFT] &= 0x7f;
588 // if(!(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000)) key_status[VK_RSHIFT] &= 0x7f;
590 } else if(code == VK_RSHIFT) {
591 #ifndef USE_SHIFT_NUMPAD_KEY
592 // if(!(GetAsyncKeyState(VK_LSHIFT, modkey_status) & 0x8000)) key_status[VK_LSHIFT] &= 0x7f;
593 if(!(GetAsyncKeyState(VK_RSHIFT, modkey_status) & 0x8000)) key_status[VK_RSHIFT] &= 0x7f;
595 } else if(code == VK_CONTROL) {
596 if(!(GetAsyncKeyState(VK_LCONTROL, modkey_status) & 0x8000)) key_status[VK_LCONTROL] &= 0x7f;
597 if(!(GetAsyncKeyState(VK_RCONTROL, modkey_status) & 0x8000)) key_status[VK_RCONTROL] &= 0x7f;
598 } else if(code == VK_MENU) {
599 if(!(GetAsyncKeyState(VK_LMENU, modkey_status) & 0x8000)) key_status[VK_LMENU] &= 0x7f;
600 if(!(GetAsyncKeyState(VK_RMENU, modkey_status) & 0x8000)) key_status[VK_RMENU] &= 0x7f;
603 if((code == VK_LSHIFT) || (code == VK_RSHIFT)) {
604 key_status[code] &= 0x7f;
605 } else if(code == VK_SHIFT) {
606 key_status[code] &= 0x7f;
607 key_status[VK_LSHIFT] &= 0x7f;
608 } else if((code == VK_LCONTROL) || (code == VK_RCONTROL)) {
609 key_status[code] &= 0x7f;
610 } else if(code == VK_CONTROL) {
611 key_status[code] &= 0x7f;
612 key_status[VK_LCONTROL] &= 0x7f;
613 } else if((code == VK_LMENU) || (code == VK_RMENU)) {
614 key_status[code] &= 0x7f;
615 } else if(code == VK_MENU) {
616 key_status[code] &= 0x7f;
617 key_status[VK_LMENU] &= 0x7f;
621 key_status[code] &= 0x7f;
622 #ifdef NOTIFY_KEY_DOWN
628 #ifdef USE_SHIFT_NUMPAD_KEY
629 if((code == VK_SHIFT) || (code == VK_RSHIFT) || (code == VK_LSHIFT)) {
630 key_shift_pressed = false;
631 key_shift_released = true;
633 } else if(key_converted[code] != 0) {
634 key_converted[code] = 0;
635 code = numpad_table[code];
639 if(!(code == VK_SHIFT || code == VK_CONTROL || code == VK_MENU)) {
640 code = keycode_conv[code];
642 if(key_status[code]) {
643 key_status[code] &= 0x7f;
644 #ifdef NOTIFY_KEY_DOWN
645 if(!key_status[code]) {
654 void EMU::press_button(int num)
657 int code = buttons[num].code;
660 key_down(code, false);
661 key_status[code] = KEY_KEEP_FRAMES;
663 // code=0: reset virtual machine
670 void EMU::enable_mouse()
672 // enable mouse emulation
677 // move mouse cursor to the center of window
679 pt.x = display_width / 2;
680 pt.y = display_height / 2;
681 ClientToScreen(main_window_handle, &pt);
682 SetCursorPos(pt.x, pt.y);
685 mouse_enabled = true;
691 void EMU::disenable_mouse()
694 // disenable mouse emulation
699 mouse_enabled = false;
702 void EMU::toggle_mouse()
704 // toggle mouse enable / disenable
713 static const int autokey_table[256] = {
718 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x00d,0x000,0x000,0x00d,0x000,0x000,
719 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
720 0x020,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x138,0x139,0x1ba,0x1bb,0x0bc,0x0bd,0x0be,0x0bf,
721 0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x038,0x039,0x0ba,0x0bb,0x1bc,0x1bd,0x1be,0x1bf,
722 0x0c0,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44a,0x44b,0x44c,0x44d,0x44e,0x44f,
723 0x450,0x451,0x452,0x453,0x454,0x455,0x456,0x457,0x458,0x459,0x45a,0x0db,0x0dc,0x0dd,0x0de,0x1e2,
724 0x1c0,0x841,0x842,0x843,0x844,0x845,0x846,0x847,0x848,0x849,0x84a,0x84b,0x84c,0x84d,0x84e,0x84f,
725 0x850,0x851,0x852,0x853,0x854,0x855,0x856,0x857,0x858,0x859,0x85a,0x1db,0x1dc,0x1dd,0x1de,0x000,
726 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
727 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
729 0x000,0x3be,0x3db,0x3dd,0x3bc,0x3bf,0x330,0x333,0x345,0x334,0x335,0x336,0x337,0x338,0x339,0x35a,
730 0x2dc,0x233,0x245,0x234,0x235,0x236,0x254,0x247,0x248,0x2ba,0x242,0x258,0x244,0x252,0x250,0x243,
731 0x251,0x241,0x25a,0x257,0x253,0x255,0x249,0x231,0x2bc,0x24b,0x246,0x256,0x232,0x2de,0x2bd,0x24a,
732 0x24e,0x2dd,0x2bf,0x24d,0x237,0x238,0x239,0x24f,0x24c,0x2be,0x2bb,0x2e2,0x230,0x259,0x2c0,0x2db,
734 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,
735 0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000
738 void EMU::start_auto_key()
743 if(OpenClipboard(NULL)) {
744 HANDLE hClip = GetClipboardData(CF_TEXT);
746 autokey_buffer->clear();
747 char* buf = (char*)GlobalLock(hClip);
748 int size = strlen(buf), prev_kana = 0;
749 for(int i = 0; i < size; i++) {
750 int code = buf[i] & 0xff;
751 if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
754 } else if(code == 0xa) {
757 if((code = autokey_table[code]) != 0) {
758 int kana = code & 0x200;
759 if(prev_kana != kana) {
760 autokey_buffer->write(0xf2);
763 #if defined(USE_AUTO_KEY_NO_CAPS)
764 if((code & 0x100) && !(code & (0x400 | 0x800))) {
765 #elif defined(USE_AUTO_KEY_CAPS)
766 if(code & (0x100 | 0x800)) {
768 if(code & (0x100 | 0x400)) {
770 autokey_buffer->write((code & 0xff) | 0x100);
772 autokey_buffer->write(code & 0xff);
777 autokey_buffer->write(0xf2);
789 void EMU::stop_auto_key()
795 autokey_phase = autokey_shift = 0;
800 void Ui_MainWindow::msleep_joy(unsigned long int ticks)
802 hRunJoyThread->msleep(ticks);
805 JoyThreadClass::JoyThreadClass(QObject *parent) : QObject(parent)
808 for(i = 0; i < 2; i++) joyhandle[i] = SDL_JoystickOpen(i);
809 joy_num = SDL_NumJoysticks();
810 AGAR_DebugLog(AGAR_LOG_DEBUG, "JoyThread : Start.");
814 JoyThreadClass::~JoyThreadClass()
817 for(i = 0; i < 2; i++) {
818 if(joyhandle[i] != NULL) SDL_JoystickClose(joyhandle[i]);
820 AGAR_DebugLog(AGAR_LOG_DEBUG, "JoyThread : EXIT");
823 void JoyThreadClass::x_axis_changed(int index, int value)
825 if(p_emu == NULL) return;
827 uint32_t *joy_status = p_emu->getJoyStatPtr();
829 if(joy_status != NULL) {
830 if(value < -8192) { // left
831 joy_status[index] |= 0x04; joy_status[index] &= ~0x08;
832 } else if(value > 8192) { // right
833 joy_status[index] |= 0x08; joy_status[index] &= ~0x04;
835 joy_status[index] &= ~0x0c;
842 void JoyThreadClass::y_axis_changed(int index, int value)
844 if(p_emu == NULL) return;
846 uint32_t *joy_status = p_emu->getJoyStatPtr();
848 if(joy_status != NULL) {
849 if(value < -8192) {// up
850 joy_status[index] |= 0x01; joy_status[index] &= ~0x02;
851 } else if(value > 8192) {// down
852 joy_status[index] |= 0x02; joy_status[index] &= ~0x01;
854 joy_status[index] &= ~0x03;
861 void JoyThreadClass::button_down(int index, unsigned int button)
863 if(p_emu == NULL) return;
865 uint32_t *joy_status = p_emu->getJoyStatPtr();
866 if(joy_status != NULL) {
867 joy_status[index] |= (1 << (button + 4));
872 void JoyThreadClass::button_up(int index, unsigned int button)
874 if(p_emu == NULL) return;
877 uint32_t *joy_status = p_emu->getJoyStatPtr();
878 if(joy_status != NULL) {
879 joy_status[index] &= ~(1 << (button + 4));
885 bool JoyThreadClass::EventSDL(SDL_Event *eventQueue)
893 if(eventQueue == NULL) return;
895 * JoyStickなどはSDLが管理する
897 switch (eventQueue->type){
898 case SDL_JOYAXISMOTION:
899 value = eventQueue->jaxis.value;
900 i = eventQueue->jaxis.which;
901 if((i < 0) || (i > 1)) break;
903 if(eventQueue->jaxis.axis == 0) { // X
904 x_axis_changed(i, value);
905 } else if(eventQueue->jaxis.axis == 1) { // Y
906 y_axis_changed(i, value);
909 case SDL_JOYBUTTONDOWN:
910 button = eventQueue->jbutton.button;
911 i = eventQueue->jbutton.which;
912 if((i < 0) || (i > 1)) break;
913 button_down(i, button);
915 case SDL_JOYBUTTONUP:
916 button = eventQueue->jbutton.button;
917 i = eventQueue->jbutton.which;
918 if((i < 0) || (i > 1)) break;
919 button_up(i, button);
928 void JoyThreadClass::doWork(void)
930 if(bRunThread == false) {
933 while(SDL_PollEvent(&event) == 1) {
936 timer.setInterval(5);
940 void JoyThreadClass::doExit(void)
947 void Ui_MainWindow::LaunchJoyThread(void)
949 hRunJoy = new JoyThreadClass();
950 hRunJoy->p_emu = emu;
951 connect(&(hRunJoy->timer), SIGNAL(timeout()), hRunJoy, SLOT(doWork()));
952 connect(this, SIGNAL(quit_joy_thread()), hRunJoy, SLOT(doExit()));
954 hRunJoy->timer.setInterval(5);
955 hRunJoy->timer.setSingleShot(false);
956 hRunJoy->timer.start(5);
959 void Ui_MainWindow::StopJoyThread(void) {
960 emit quit_joy_thread();
963 void Ui_MainWindow::delete_joy_thread(void)
965 // delete hRunJoyThread;