1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - eventloop.c * |
3 | * Mupen64Plus homepage: https://mupen64plus.org/ * |
4 | * Copyright (C) 2008-2009 Richard Goedeken * |
5 | * Copyright (C) 2008 Ebenblues Nmn Okaygo Tillin9 * |
6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * |
9 | * the Free Software Foundation; either version 2 of the License, or * |
10 | * (at your option) any later version. * |
11 | * * |
12 | * This program is distributed in the hope that it will be useful, * |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
15 | * GNU General Public License for more details. * |
16 | * * |
17 | * You should have received a copy of the GNU General Public License * |
18 | * along with this program; if not, write to the * |
19 | * Free Software Foundation, Inc., * |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
21 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
22 | |
23 | #include <SDL.h> |
24 | #include <SDL_syswm.h> |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #if ! SDL_VERSION_ATLEAST(1,3,0) |
29 | |
30 | #define SDL_SCANCODE_ESCAPE SDLK_ESCAPE |
31 | #define SDL_NUM_SCANCODES SDLK_LAST |
32 | #define SDL_SCANCODE_F5 SDLK_F5 |
33 | #define SDL_SCANCODE_F7 SDLK_F7 |
34 | #define SDL_SCANCODE_F9 SDLK_F9 |
35 | #define SDL_SCANCODE_F10 SDLK_F10 |
36 | #define SDL_SCANCODE_F11 SDLK_F11 |
37 | #define SDL_SCANCODE_F12 SDLK_F12 |
38 | #define SDL_SCANCODE_P SDLK_p |
39 | #define SDL_SCANCODE_M SDLK_m |
40 | #define SDL_SCANCODE_RIGHTBRACKET SDLK_RIGHTBRACKET |
41 | #define SDL_SCANCODE_LEFTBRACKET SDLK_LEFTBRACKET |
42 | #define SDL_SCANCODE_F SDLK_f |
43 | #define SDL_SCANCODE_SLASH SDLK_SLASH |
44 | #define SDL_SCANCODE_G SDLK_g |
45 | #define SDL_SCANCODE_RETURN SDLK_RETURN |
46 | #define SDL_SCANCODE_0 SDLK_0 |
47 | #define SDL_SCANCODE_1 SDLK_1 |
48 | #define SDL_SCANCODE_2 SDLK_2 |
49 | #define SDL_SCANCODE_3 SDLK_3 |
50 | #define SDL_SCANCODE_4 SDLK_4 |
51 | #define SDL_SCANCODE_5 SDLK_5 |
52 | #define SDL_SCANCODE_6 SDLK_6 |
53 | #define SDL_SCANCODE_7 SDLK_7 |
54 | #define SDL_SCANCODE_8 SDLK_8 |
55 | #define SDL_SCANCODE_9 SDLK_9 |
56 | #define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN |
57 | |
58 | #define SDL_SetEventFilter(func, data) SDL_SetEventFilter(func) |
59 | #define event_sdl_filter(userdata, event) event_sdl_filter(const event) |
60 | |
61 | #else |
62 | SDL_JoystickID l_iJoyInstanceID[10]; |
63 | #endif |
64 | |
65 | #define M64P_CORE_PROTOTYPES 1 |
66 | #include "api/callbacks.h" |
67 | #include "api/config.h" |
68 | #include "api/m64p_config.h" |
69 | #include "api/m64p_types.h" |
70 | #include "eventloop.h" |
71 | #include "main.h" |
72 | #include "plugin/plugin.h" |
73 | #include "sdl_key_converter.h" |
74 | #include "util.h" |
75 | |
76 | /* version number for CoreEvents config section */ |
77 | #define CONFIG_PARAM_VERSION 1.00 |
78 | |
79 | static m64p_handle l_CoreEventsConfig = NULL; |
80 | |
81 | /********************************************************************************************************* |
82 | * static variables and definitions for eventloop.c |
83 | */ |
84 | |
85 | #define kbdFullscreen "Kbd Mapping Fullscreen" |
86 | #define kbdStop "Kbd Mapping Stop" |
87 | #define kbdPause "Kbd Mapping Pause" |
88 | #define kbdSave "Kbd Mapping Save State" |
89 | #define kbdLoad "Kbd Mapping Load State" |
90 | #define kbdIncrement "Kbd Mapping Increment Slot" |
91 | #define kbdReset "Kbd Mapping Reset" |
92 | #define kbdSpeeddown "Kbd Mapping Speed Down" |
93 | #define kbdSpeedup "Kbd Mapping Speed Up" |
94 | #define kbdScreenshot "Kbd Mapping Screenshot" |
95 | #define kbdMute "Kbd Mapping Mute" |
96 | #define kbdIncrease "Kbd Mapping Increase Volume" |
97 | #define kbdDecrease "Kbd Mapping Decrease Volume" |
98 | #define kbdForward "Kbd Mapping Fast Forward" |
99 | #define kbdAdvance "Kbd Mapping Frame Advance" |
100 | #define kbdGameshark "Kbd Mapping Gameshark" |
101 | |
102 | typedef enum {joyFullscreen, |
103 | joyStop, |
104 | joyPause, |
105 | joySave, |
106 | joyLoad, |
107 | joyIncrement, |
108 | joyReset, |
109 | joySpeedDown, |
110 | joySpeedUp, |
111 | joyScreenshot, |
112 | joyMute, |
113 | joyIncrease, |
114 | joyDecrease, |
115 | joyForward, |
116 | joyAdvance, |
117 | joyGameshark |
118 | } eJoyCommand; |
119 | |
120 | static const char *JoyCmdName[] = { "Joy Mapping Fullscreen" , |
121 | "Joy Mapping Stop" , |
122 | "Joy Mapping Pause" , |
123 | "Joy Mapping Save State" , |
124 | "Joy Mapping Load State" , |
125 | "Joy Mapping Increment Slot" , |
126 | "Joy Mapping Reset" , |
127 | "Joy Mapping Speed Down" , |
128 | "Joy Mapping Speed Up" , |
129 | "Joy Mapping Screenshot" , |
130 | "Joy Mapping Mute" , |
131 | "Joy Mapping Increase Volume" , |
132 | "Joy Mapping Decrease Volume" , |
133 | "Joy Mapping Fast Forward" , |
134 | "Joy Mapping Frame Advance" , |
135 | "Joy Mapping Gameshark" }; |
136 | |
137 | static const int NumJoyCommands = sizeof(JoyCmdName) / sizeof(const char *); |
138 | |
139 | static int JoyCmdActive[16][2]; /* if extra joystick commands are added above, make sure there is enough room in this array */ |
140 | /* [i][0] is Command Active, [i][1] is Hotkey Active */ |
141 | |
142 | static int GamesharkActive = 0; |
143 | |
144 | /********************************************************************************************************* |
145 | * static functions for eventloop.c |
146 | */ |
147 | |
148 | /** MatchJoyCommand |
149 | * This function processes an SDL event and updates the JoyCmdActive array if the |
150 | * event matches with the given command. |
151 | * |
152 | * If the event activates a joystick command which was not previously active, then |
153 | * a 1 is returned. If the event de-activates an command, a -1 is returned. Otherwise |
154 | * (if the event does not match the command or active status didn't change), a 0 is returned. |
155 | */ |
156 | static int MatchJoyCommand(const SDL_Event *event, eJoyCommand cmd) |
157 | { |
158 | const char *multi_event_str = ConfigGetParamString(l_CoreEventsConfig, JoyCmdName[cmd]); |
159 | const int orig_cmd_value = (JoyCmdActive[cmd][1] << 1) | JoyCmdActive[cmd][0]; |
160 | int dev_number, input_number, input_value; |
161 | char axis_direction; |
162 | |
163 | /* Empty string or non-joystick command */ |
164 | if (multi_event_str == NULL || strlen(multi_event_str) < 4 || multi_event_str[0] != 'J') |
165 | return 0; |
166 | |
167 | /* Make copy of the event config string that we can hack it up with strtok */ |
168 | char tokenized_event_str[128]; |
169 | strncpy(tokenized_event_str, multi_event_str, 127); |
170 | tokenized_event_str[127] = '\0'; |
171 | |
172 | /* Iterate over comma-separated config phrases */ |
173 | char *phrase_str = strtok(tokenized_event_str, "," ); |
174 | while (phrase_str != NULL) |
175 | { |
176 | int iHotkey, has_hotkey = 0; |
177 | |
178 | /* Check for invalid phrase */ |
179 | if (strlen(phrase_str) < 4 || phrase_str[0] != 'J') |
180 | { |
181 | phrase_str = strtok(NULL, "," ); |
182 | continue; |
183 | } |
184 | |
185 | /* Get device (joystick) number */ |
186 | if (phrase_str[1] == '*') |
187 | { |
188 | dev_number = -1; |
189 | } |
190 | else if (phrase_str[1] >= '0' && phrase_str[1] <= '9') |
191 | { |
192 | dev_number = phrase_str[1] - '0'; |
193 | #if SDL_VERSION_ATLEAST(2,0,0) |
194 | dev_number = l_iJoyInstanceID[dev_number]; |
195 | #endif |
196 | } |
197 | else |
198 | { |
199 | phrase_str = strtok(NULL, "," ); |
200 | continue; |
201 | } |
202 | |
203 | /* Iterate over JoyAction/JoyHotkey action fields */ |
204 | for (iHotkey = 0; iHotkey < 2; iHotkey++) |
205 | { |
206 | const char *action_str = NULL; |
207 | if (iHotkey == 0) |
208 | { |
209 | action_str = phrase_str + 2; |
210 | } |
211 | else |
212 | { |
213 | char *hotkey_str = strchr(phrase_str, '/'); |
214 | if (hotkey_str == NULL || strlen(hotkey_str) < 3) |
215 | { |
216 | break; |
217 | } |
218 | action_str = hotkey_str+1; |
219 | has_hotkey = 1; |
220 | } |
221 | |
222 | /* Evaluate action based on type of joystick input expected */ |
223 | switch (action_str[0]) |
224 | { |
225 | /* Axis */ |
226 | case 'A': |
227 | if (event->type != SDL_JOYAXISMOTION) |
228 | break; |
229 | if (sscanf(action_str, "A%d%c" , &input_number, &axis_direction) != 2) |
230 | break; |
231 | if ((dev_number != 1 && dev_number != event->jaxis.which) || input_number != event->jaxis.axis) |
232 | break; |
233 | if (axis_direction == '+') |
234 | { |
235 | if (event->jaxis.value >= 15000) |
236 | JoyCmdActive[cmd][iHotkey] = 1; |
237 | else if (event->jaxis.value <= 8000) |
238 | JoyCmdActive[cmd][iHotkey] = 0; |
239 | break; |
240 | } |
241 | else if (axis_direction == '-') |
242 | { |
243 | if (event->jaxis.value <= -15000) |
244 | JoyCmdActive[cmd][iHotkey] = 1; |
245 | else if (event->jaxis.value >= -8000) |
246 | JoyCmdActive[cmd][iHotkey] = 0; |
247 | break; |
248 | } |
249 | break; |
250 | /* Hat */ |
251 | case 'H': |
252 | if (event->type != SDL_JOYHATMOTION) |
253 | break; |
254 | if (sscanf(action_str, "H%dV%d" , &input_number, &input_value) != 2) |
255 | break; |
256 | if ((dev_number != -1 && dev_number != event->jhat.which) || input_number != event->jhat.hat) |
257 | break; |
258 | if ((event->jhat.value & input_value) == input_value) |
259 | JoyCmdActive[cmd][iHotkey] = 1; |
260 | else if ((event->jhat.value & input_value) != input_value) |
261 | JoyCmdActive[cmd][iHotkey] = 0; |
262 | break; |
263 | /* Button. */ |
264 | case 'B': |
265 | if (event->type != SDL_JOYBUTTONDOWN && event->type != SDL_JOYBUTTONUP) |
266 | break; |
267 | if (sscanf(action_str, "B%d" , &input_number) != 1) |
268 | break; |
269 | if ((dev_number != -1 && dev_number != event->jbutton.which) || input_number != event->jbutton.button) |
270 | break; |
271 | if (event->type == SDL_JOYBUTTONDOWN) |
272 | JoyCmdActive[cmd][iHotkey] = 1; |
273 | else if (event->type == SDL_JOYBUTTONUP) |
274 | JoyCmdActive[cmd][iHotkey] = 0; |
275 | break; |
276 | default: |
277 | /* bad configuration parameter */ |
278 | break; |
279 | } |
280 | } /* Iterate over JoyAction/JoyHotkey action fields */ |
281 | |
282 | /* Detect changes in command activation status */ |
283 | const int new_cmd_value = (JoyCmdActive[cmd][1] << 1) | JoyCmdActive[cmd][0]; |
284 | const int active_mask = has_hotkey ? 3 : 1; |
285 | if ((orig_cmd_value & active_mask) != active_mask && (new_cmd_value & active_mask) == active_mask) |
286 | return 1; |
287 | if ((orig_cmd_value & active_mask) == active_mask && (new_cmd_value & active_mask) != active_mask) |
288 | return -1; |
289 | |
290 | /* get next comma-separated command phrase from event string */ |
291 | phrase_str = strtok(NULL, "," ); |
292 | } /* Iterate over comma-separated config phrases */ |
293 | |
294 | /* nothing found */ |
295 | return 0; |
296 | } |
297 | |
298 | /********************************************************************************************************* |
299 | * sdl event filter |
300 | */ |
301 | static int SDLCALL event_sdl_filter(void *userdata, SDL_Event *event) |
302 | { |
303 | int cmd, action; |
304 | |
305 | switch(event->type) |
306 | { |
307 | // user clicked on window close button |
308 | case SDL_QUIT: |
309 | main_stop(); |
310 | break; |
311 | |
312 | case SDL_KEYDOWN: |
313 | #if SDL_VERSION_ATLEAST(1,3,0) |
314 | if (event->key.repeat) |
315 | return 0; |
316 | |
317 | event_sdl_keydown(event->key.keysym.scancode, event->key.keysym.mod); |
318 | #else |
319 | event_sdl_keydown(event->key.keysym.sym, event->key.keysym.mod); |
320 | #endif |
321 | return 0; |
322 | case SDL_KEYUP: |
323 | #if SDL_VERSION_ATLEAST(1,3,0) |
324 | event_sdl_keyup(event->key.keysym.scancode, event->key.keysym.mod); |
325 | #else |
326 | event_sdl_keyup(event->key.keysym.sym, event->key.keysym.mod); |
327 | #endif |
328 | return 0; |
329 | |
330 | #if SDL_VERSION_ATLEAST(1,3,0) |
331 | case SDL_WINDOWEVENT: |
332 | switch (event->window.event) { |
333 | case SDL_WINDOWEVENT_RESIZED: |
334 | // call the video plugin. if the video plugin supports resizing, it will resize its viewport and call |
335 | // VidExt_ResizeWindow to update the window manager handling our opengl output window |
336 | gfx.resizeVideoOutput(event->window.data1, event->window.data2); |
337 | return 0; // consumed the event |
338 | break; |
339 | |
340 | case SDL_WINDOWEVENT_MOVED: |
341 | gfx.moveScreen(event->window.data1, event->window.data2); |
342 | return 0; // consumed the event |
343 | break; |
344 | } |
345 | break; |
346 | #else |
347 | case SDL_VIDEORESIZE: |
348 | // call the video plugin. if the video plugin supports resizing, it will resize its viewport and call |
349 | // VidExt_ResizeWindow to update the window manager handling our opengl output window |
350 | gfx.resizeVideoOutput(event->resize.w, event->resize.h); |
351 | return 0; // consumed the event |
352 | break; |
353 | |
354 | #ifdef WIN32 |
355 | case SDL_SYSWMEVENT: |
356 | if(event->syswm.msg->msg == WM_MOVE) |
357 | gfx.moveScreen(0,0); // The video plugin is responsible for getting the new window position |
358 | return 0; // consumed the event |
359 | break; |
360 | #endif |
361 | #endif |
362 | |
363 | // if joystick action is detected, check if it's mapped to a special function |
364 | case SDL_JOYAXISMOTION: |
365 | case SDL_JOYBUTTONDOWN: |
366 | case SDL_JOYBUTTONUP: |
367 | case SDL_JOYHATMOTION: |
368 | for (cmd = 0; cmd < NumJoyCommands; cmd++) |
369 | { |
370 | action = MatchJoyCommand(event, (eJoyCommand) cmd); |
371 | if (action == 1) /* command was just activated (button down, etc) */ |
372 | { |
373 | if (cmd == joyFullscreen) |
374 | gfx.changeWindow(); |
375 | else if (cmd == joyStop) |
376 | main_stop(); |
377 | else if (cmd == joyPause) |
378 | main_toggle_pause(); |
379 | else if (cmd == joySave) |
380 | main_state_save(1, NULL); /* save in mupen64plus format using current slot */ |
381 | else if (cmd == joyLoad) |
382 | main_state_load(NULL); /* load using current slot */ |
383 | else if (cmd == joyIncrement) |
384 | main_state_inc_slot(); |
385 | else if (cmd == joyReset) |
386 | main_reset(0); |
387 | else if (cmd == joySpeedDown) |
388 | main_speeddown(5); |
389 | else if (cmd == joySpeedUp) |
390 | main_speedup(5); |
391 | else if (cmd == joyScreenshot) |
392 | main_take_next_screenshot(); |
393 | else if (cmd == joyMute) |
394 | main_volume_mute(); |
395 | else if (cmd == joyDecrease) |
396 | main_volume_down(); |
397 | else if (cmd == joyIncrease) |
398 | main_volume_up(); |
399 | else if (cmd == joyForward) |
400 | main_set_fastforward(1); |
401 | else if (cmd == joyAdvance) |
402 | main_advance_one(); |
403 | else if (cmd == joyGameshark) |
404 | event_set_gameshark(1); |
405 | } |
406 | else if (action == -1) /* command was just de-activated (button up, etc) */ |
407 | { |
408 | if (cmd == joyForward) |
409 | main_set_fastforward(0); |
410 | else if (cmd == joyGameshark) |
411 | event_set_gameshark(0); |
412 | } |
413 | } |
414 | |
415 | return 0; |
416 | break; |
417 | } |
418 | |
419 | return 1; // add this event to SDL queue |
420 | } |
421 | |
422 | /********************************************************************************************************* |
423 | * global functions |
424 | */ |
425 | |
426 | void event_initialize(void) |
427 | { |
428 | int i, j; |
429 | |
430 | /* set initial state of all joystick commands to 'off' */ |
431 | for (i = 0; i < NumJoyCommands; i++) |
432 | for (j = 0; j < 2; j++) |
433 | JoyCmdActive[i][j] = 0; |
434 | |
435 | /* activate any joysticks which are referenced in the joystick event command strings */ |
436 | const int NumJoysticks = SDL_NumJoysticks(); |
437 | if (NumJoysticks > 0) |
438 | { |
439 | for (i = 0; i < NumJoyCommands; i++) |
440 | { |
441 | const char *multi_event_str = ConfigGetParamString(l_CoreEventsConfig, JoyCmdName[i]); |
442 | /* Empty string or invalid command */ |
443 | if (multi_event_str == NULL || strlen(multi_event_str) < 4 || multi_event_str[0] != 'J') |
444 | continue; |
445 | /* Make copy of the event config string that we can hack it up with strtok */ |
446 | char tokenized_event_str[128]; |
447 | strncpy(tokenized_event_str, multi_event_str, 127); |
448 | tokenized_event_str[127] = '\0'; |
449 | /* Iterate over comma-separated config phrases */ |
450 | char *phrase_str = strtok(tokenized_event_str, "," ); |
451 | while (phrase_str != NULL) |
452 | { |
453 | /* Check for invalid phrase */ |
454 | if (strlen(phrase_str) < 4 || phrase_str[0] != 'J') |
455 | { |
456 | phrase_str = strtok(NULL, "," ); |
457 | continue; |
458 | } |
459 | /* Get device (joystick) number(s) to initialize */ |
460 | int joy_min, joy_max; |
461 | if (phrase_str[1] == '*') |
462 | { |
463 | joy_min = 0; |
464 | joy_max = NumJoysticks - 1; |
465 | } |
466 | else if (phrase_str[1] >= '0' && phrase_str[1] <= '9') |
467 | { |
468 | joy_min = joy_max = phrase_str[1] - '0'; |
469 | } |
470 | else |
471 | { |
472 | phrase_str = strtok(NULL, "," ); |
473 | continue; |
474 | } |
475 | /* initialize them */ |
476 | int device; |
477 | for (device = joy_min; device <= joy_max; device++) |
478 | { |
479 | if (!SDL_WasInit(SDL_INIT_JOYSTICK)) |
480 | SDL_InitSubSystem(SDL_INIT_JOYSTICK); |
481 | #if SDL_VERSION_ATLEAST(2,0,0) |
482 | SDL_Joystick *thisJoy = SDL_JoystickOpen(device); |
483 | l_iJoyInstanceID[device] = SDL_JoystickInstanceID(thisJoy); |
484 | #else |
485 | if (!SDL_JoystickOpened(device)) |
486 | SDL_JoystickOpen(device); |
487 | #endif |
488 | } |
489 | |
490 | phrase_str = strtok(NULL, "," ); |
491 | } /* Iterate over comma-separated config phrases */ |
492 | } |
493 | } |
494 | |
495 | /* set up SDL event filter and disable key repeat */ |
496 | #if !SDL_VERSION_ATLEAST(2,0,0) |
497 | SDL_EnableKeyRepeat(0, 0); |
498 | #endif |
499 | SDL_SetEventFilter(event_sdl_filter, NULL); |
500 | |
501 | #if defined(WIN32) && !SDL_VERSION_ATLEAST(1,3,0) |
502 | SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); |
503 | |
504 | if (SDL_EventState(SDL_SYSWMEVENT, SDL_QUERY) != SDL_ENABLE) |
505 | DebugMessage(M64MSG_WARNING, "Failed to change event state: %s" , SDL_GetError()); |
506 | #endif |
507 | } |
508 | |
509 | int event_set_core_defaults(void) |
510 | { |
511 | float fConfigParamsVersion; |
512 | |
513 | if (ConfigOpenSection("CoreEvents" , &l_CoreEventsConfig) != M64ERR_SUCCESS || l_CoreEventsConfig == NULL) |
514 | { |
515 | DebugMessage(M64MSG_ERROR, "Failed to open CoreEvents config section." ); |
516 | return 0; /* fail */ |
517 | } |
518 | |
519 | if (ConfigGetParameter(l_CoreEventsConfig, "Version" , M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS) |
520 | { |
521 | DebugMessage(M64MSG_WARNING, "No version number in 'CoreEvents' config section. Setting defaults." ); |
522 | ConfigDeleteSection("CoreEvents" ); |
523 | ConfigOpenSection("CoreEvents" , &l_CoreEventsConfig); |
524 | } |
525 | else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION)) |
526 | { |
527 | DebugMessage(M64MSG_WARNING, "Incompatible version %.2f in 'CoreEvents' config section: current is %.2f. Setting defaults." , fConfigParamsVersion, (float) CONFIG_PARAM_VERSION); |
528 | ConfigDeleteSection("CoreEvents" ); |
529 | ConfigOpenSection("CoreEvents" , &l_CoreEventsConfig); |
530 | } |
531 | else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f) |
532 | { |
533 | /* handle upgrades */ |
534 | float fVersion = CONFIG_PARAM_VERSION; |
535 | ConfigSetParameter(l_CoreEventsConfig, "Version" , M64TYPE_FLOAT, &fVersion); |
536 | DebugMessage(M64MSG_INFO, "Updating parameter set version in 'CoreEvents' config section to %.2f" , fVersion); |
537 | } |
538 | |
539 | ConfigSetDefaultFloat(l_CoreEventsConfig, "Version" , CONFIG_PARAM_VERSION, "Mupen64Plus CoreEvents config parameter set version number. Please don't change this version number." ); |
540 | /* Keyboard presses mapped to core functions */ |
541 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdStop, sdl_native2keysym(SDL_SCANCODE_ESCAPE), "SDL keysym for stopping the emulator" ); |
542 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdFullscreen, sdl_native2keysym(SDL_NUM_SCANCODES), "SDL keysym for switching between fullscreen/windowed modes" ); |
543 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdSave, sdl_native2keysym(SDL_SCANCODE_F5), "SDL keysym for saving the emulator state" ); |
544 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdLoad, sdl_native2keysym(SDL_SCANCODE_F7), "SDL keysym for loading the emulator state" ); |
545 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdIncrement, sdl_native2keysym(SDL_SCANCODE_UNKNOWN), "SDL keysym for advancing the save state slot" ); |
546 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdReset, sdl_native2keysym(SDL_SCANCODE_F9), "SDL keysym for resetting the emulator" ); |
547 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdSpeeddown, sdl_native2keysym(SDL_SCANCODE_F10), "SDL keysym for slowing down the emulator" ); |
548 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdSpeedup, sdl_native2keysym(SDL_SCANCODE_F11), "SDL keysym for speeding up the emulator" ); |
549 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdScreenshot, sdl_native2keysym(SDL_SCANCODE_F12), "SDL keysym for taking a screenshot" ); |
550 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdPause, sdl_native2keysym(SDL_SCANCODE_P), "SDL keysym for pausing the emulator" ); |
551 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdMute, sdl_native2keysym(SDL_SCANCODE_M), "SDL keysym for muting/unmuting the sound" ); |
552 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdIncrease, sdl_native2keysym(SDL_SCANCODE_RIGHTBRACKET),"SDL keysym for increasing the volume" ); |
553 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdDecrease, sdl_native2keysym(SDL_SCANCODE_LEFTBRACKET), "SDL keysym for decreasing the volume" ); |
554 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdForward, sdl_native2keysym(SDL_SCANCODE_F), "SDL keysym for temporarily going really fast" ); |
555 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdAdvance, sdl_native2keysym(SDL_SCANCODE_SLASH), "SDL keysym for advancing by one frame when paused" ); |
556 | ConfigSetDefaultInt(l_CoreEventsConfig, kbdGameshark, sdl_native2keysym(SDL_SCANCODE_G), "SDL keysym for pressing the game shark button" ); |
557 | /* Joystick events mapped to core functions */ |
558 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyStop], "" , "Joystick event string for stopping the emulator" ); |
559 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyFullscreen], "" , "Joystick event string for switching between fullscreen/windowed modes" ); |
560 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joySave], "" , "Joystick event string for saving the emulator state" ); |
561 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyLoad], "" , "Joystick event string for loading the emulator state" ); |
562 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyIncrement], "" , "Joystick event string for advancing the save state slot" ); |
563 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyReset], "" , "Joystick event string for resetting the emulator" ); |
564 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joySpeedDown], "" , "Joystick event string for slowing down the emulator" ); |
565 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joySpeedUp], "" , "Joystick event string for speeding up the emulator" ); |
566 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyScreenshot], "" , "Joystick event string for taking a screenshot" ); |
567 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyPause], "" , "Joystick event string for pausing the emulator" ); |
568 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyMute], "" , "Joystick event string for muting/unmuting the sound" ); |
569 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyIncrease], "" , "Joystick event string for increasing the volume" ); |
570 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyDecrease], "" , "Joystick event string for decreasing the volume" ); |
571 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyForward], "" , "Joystick event string for fast-forward" ); |
572 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyAdvance], "" , "Joystick event string for advancing by one frame when paused" ); |
573 | ConfigSetDefaultString(l_CoreEventsConfig, JoyCmdName[joyGameshark], "" , "Joystick event string for pressing the game shark button" ); |
574 | |
575 | return 1; |
576 | } |
577 | |
578 | static int get_saveslot_from_keysym(int keysym) |
579 | { |
580 | switch (keysym) { |
581 | case SDL_SCANCODE_0: |
582 | return 0; |
583 | case SDL_SCANCODE_1: |
584 | return 1; |
585 | case SDL_SCANCODE_2: |
586 | return 2; |
587 | case SDL_SCANCODE_3: |
588 | return 3; |
589 | case SDL_SCANCODE_4: |
590 | return 4; |
591 | case SDL_SCANCODE_5: |
592 | return 5; |
593 | case SDL_SCANCODE_6: |
594 | return 6; |
595 | case SDL_SCANCODE_7: |
596 | return 7; |
597 | case SDL_SCANCODE_8: |
598 | return 8; |
599 | case SDL_SCANCODE_9: |
600 | return 9; |
601 | default: |
602 | return -1; |
603 | } |
604 | } |
605 | |
606 | /********************************************************************************************************* |
607 | * sdl keyup/keydown handlers |
608 | */ |
609 | |
610 | void event_sdl_keydown(int keysym, int keymod) |
611 | { |
612 | int slot; |
613 | |
614 | /* check for the only 2 hard-coded key commands: Alt-enter for fullscreen and 0-9 for save state slot */ |
615 | if (keysym == SDL_SCANCODE_RETURN && keymod & (KMOD_LALT | KMOD_RALT)) |
616 | gfx.changeWindow(); |
617 | else if ((slot = get_saveslot_from_keysym(keysym)) >= 0) |
618 | main_state_set_slot(slot); |
619 | /* check all of the configurable commands */ |
620 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdStop))) |
621 | main_stop(); |
622 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdFullscreen))) |
623 | gfx.changeWindow(); |
624 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdSave))) |
625 | main_state_save(0, NULL); /* save in mupen64plus format using current slot */ |
626 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdLoad))) |
627 | main_state_load(NULL); /* load using current slot */ |
628 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdIncrement))) |
629 | main_state_inc_slot(); |
630 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdReset))) |
631 | main_reset(0); |
632 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdSpeeddown))) |
633 | main_speeddown(5); |
634 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdSpeedup))) |
635 | main_speedup(5); |
636 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdScreenshot))) |
637 | main_take_next_screenshot(); /* screenshot will be taken at the end of frame rendering */ |
638 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdPause))) |
639 | main_toggle_pause(); |
640 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdMute))) |
641 | main_volume_mute(); |
642 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdIncrease))) |
643 | main_volume_up(); |
644 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdDecrease))) |
645 | main_volume_down(); |
646 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdForward))) |
647 | main_set_fastforward(1); |
648 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdAdvance))) |
649 | main_advance_one(); |
650 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdGameshark))) { |
651 | event_set_gameshark(1); |
652 | } |
653 | else |
654 | { |
655 | /* pass all other keypresses to the input plugin */ |
656 | input.keyDown(keymod, keysym); |
657 | } |
658 | |
659 | } |
660 | |
661 | void event_sdl_keyup(int keysym, int keymod) |
662 | { |
663 | if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdStop))) |
664 | { |
665 | return; |
666 | } |
667 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdForward))) |
668 | { |
669 | main_set_fastforward(0); |
670 | } |
671 | else if (keysym == sdl_keysym2native(ConfigGetParamInt(l_CoreEventsConfig, kbdGameshark))) |
672 | { |
673 | event_set_gameshark(0); |
674 | } |
675 | else input.keyUp(keymod, keysym); |
676 | |
677 | } |
678 | |
679 | int event_gameshark_active(void) |
680 | { |
681 | return GamesharkActive; |
682 | } |
683 | |
684 | void event_set_gameshark(int active) |
685 | { |
686 | // if boolean value doesn't change then just return |
687 | if (!active == !GamesharkActive) |
688 | return; |
689 | |
690 | // set the button state |
691 | GamesharkActive = (active ? 1 : 0); |
692 | |
693 | // notify front-end application that gameshark button state has changed |
694 | StateChanged(M64CORE_INPUT_GAMESHARK, GamesharkActive); |
695 | } |
696 | |
697 | |