6#if defined(SDL_LIBRETRO_IMPLEMENTATION) && !defined(SDL_LIBRETRO_INPUT_IMPL_ONCE)
7#define SDL_LIBRETRO_INPUT_IMPL_ONCE
14static const SDL_GamepadButton SDL_Libretro_DefaultGamepadButtons[SDL_LIBRETRO_MAX_JOYPAD_BUTTONS] = {
15 SDL_GAMEPAD_BUTTON_SOUTH,
16 SDL_GAMEPAD_BUTTON_WEST,
17 SDL_GAMEPAD_BUTTON_BACK,
18 SDL_GAMEPAD_BUTTON_START,
19 SDL_GAMEPAD_BUTTON_DPAD_UP,
20 SDL_GAMEPAD_BUTTON_DPAD_DOWN,
21 SDL_GAMEPAD_BUTTON_DPAD_LEFT,
22 SDL_GAMEPAD_BUTTON_DPAD_RIGHT,
23 SDL_GAMEPAD_BUTTON_EAST,
24 SDL_GAMEPAD_BUTTON_NORTH,
25 SDL_GAMEPAD_BUTTON_LEFT_SHOULDER,
26 SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER,
27 SDL_GAMEPAD_BUTTON_LEFT_PADDLE1,
28 SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1,
29 SDL_GAMEPAD_BUTTON_LEFT_STICK,
30 SDL_GAMEPAD_BUTTON_RIGHT_STICK,
40static SDL_GamepadButton SDL_Libretro_RetroJoypadToGamepadButton(
const SDL_Libretro* lr,
unsigned port,
unsigned button) {
42 ? lr->gamepadButtons[port][button]
43 : SDL_GAMEPAD_BUTTON_INVALID;
53static bool SDL_Libretro_AnalogToDigitalPressed(
const SDL_Libretro* lr,
unsigned port,
unsigned id) {
59 SDL_GamepadAxis axisX = right ? SDL_GAMEPAD_AXIS_RIGHTX : SDL_GAMEPAD_AXIS_LEFTX;
60 SDL_GamepadAxis axisY = right ? SDL_GAMEPAD_AXIS_RIGHTY : SDL_GAMEPAD_AXIS_LEFTY;
62 case RETRO_DEVICE_ID_JOYPAD_UP:
return SDL_GetGamepadAxis(lr->gamepads[port], axisY) < -8192;
63 case RETRO_DEVICE_ID_JOYPAD_DOWN:
return SDL_GetGamepadAxis(lr->gamepads[port], axisY) > 8192;
64 case RETRO_DEVICE_ID_JOYPAD_LEFT:
return SDL_GetGamepadAxis(lr->gamepads[port], axisX) < -8192;
65 case RETRO_DEVICE_ID_JOYPAD_RIGHT:
return SDL_GetGamepadAxis(lr->gamepads[port], axisX) > 8192;
66 default:
return false;
78static SDL_Scancode SDL_Libretro_RetroKeyToScancode(
unsigned key) {
80 case RETROK_BACKSPACE:
return SDL_SCANCODE_BACKSPACE;
81 case RETROK_TAB:
return SDL_SCANCODE_TAB;
82 case RETROK_RETURN:
return SDL_SCANCODE_RETURN;
83 case RETROK_ESCAPE:
return SDL_SCANCODE_ESCAPE;
84 case RETROK_SPACE:
return SDL_SCANCODE_SPACE;
85 case RETROK_EXCLAIM:
return SDL_SCANCODE_1;
86 case RETROK_QUOTEDBL:
return SDL_SCANCODE_APOSTROPHE;
87 case RETROK_HASH:
return SDL_SCANCODE_3;
88 case RETROK_DOLLAR:
return SDL_SCANCODE_4;
89 case RETROK_AMPERSAND:
return SDL_SCANCODE_7;
90 case RETROK_QUOTE:
return SDL_SCANCODE_APOSTROPHE;
91 case RETROK_LEFTPAREN:
return SDL_SCANCODE_9;
92 case RETROK_RIGHTPAREN:
return SDL_SCANCODE_0;
93 case RETROK_ASTERISK:
return SDL_SCANCODE_8;
94 case RETROK_PLUS:
return SDL_SCANCODE_EQUALS;
95 case RETROK_COMMA:
return SDL_SCANCODE_COMMA;
96 case RETROK_MINUS:
return SDL_SCANCODE_MINUS;
97 case RETROK_PERIOD:
return SDL_SCANCODE_PERIOD;
98 case RETROK_SLASH:
return SDL_SCANCODE_SLASH;
99 case RETROK_0:
return SDL_SCANCODE_0;
100 case RETROK_1:
return SDL_SCANCODE_1;
101 case RETROK_2:
return SDL_SCANCODE_2;
102 case RETROK_3:
return SDL_SCANCODE_3;
103 case RETROK_4:
return SDL_SCANCODE_4;
104 case RETROK_5:
return SDL_SCANCODE_5;
105 case RETROK_6:
return SDL_SCANCODE_6;
106 case RETROK_7:
return SDL_SCANCODE_7;
107 case RETROK_8:
return SDL_SCANCODE_8;
108 case RETROK_9:
return SDL_SCANCODE_9;
109 case RETROK_SEMICOLON:
return SDL_SCANCODE_SEMICOLON;
110 case RETROK_EQUALS:
return SDL_SCANCODE_EQUALS;
111 case RETROK_LEFTBRACKET:
return SDL_SCANCODE_LEFTBRACKET;
112 case RETROK_BACKSLASH:
return SDL_SCANCODE_BACKSLASH;
113 case RETROK_RIGHTBRACKET:
return SDL_SCANCODE_RIGHTBRACKET;
114 case RETROK_BACKQUOTE:
return SDL_SCANCODE_GRAVE;
115 case RETROK_a:
return SDL_SCANCODE_A;
116 case RETROK_b:
return SDL_SCANCODE_B;
117 case RETROK_c:
return SDL_SCANCODE_C;
118 case RETROK_d:
return SDL_SCANCODE_D;
119 case RETROK_e:
return SDL_SCANCODE_E;
120 case RETROK_f:
return SDL_SCANCODE_F;
121 case RETROK_g:
return SDL_SCANCODE_G;
122 case RETROK_h:
return SDL_SCANCODE_H;
123 case RETROK_i:
return SDL_SCANCODE_I;
124 case RETROK_j:
return SDL_SCANCODE_J;
125 case RETROK_k:
return SDL_SCANCODE_K;
126 case RETROK_l:
return SDL_SCANCODE_L;
127 case RETROK_m:
return SDL_SCANCODE_M;
128 case RETROK_n:
return SDL_SCANCODE_N;
129 case RETROK_o:
return SDL_SCANCODE_O;
130 case RETROK_p:
return SDL_SCANCODE_P;
131 case RETROK_q:
return SDL_SCANCODE_Q;
132 case RETROK_r:
return SDL_SCANCODE_R;
133 case RETROK_s:
return SDL_SCANCODE_S;
134 case RETROK_t:
return SDL_SCANCODE_T;
135 case RETROK_u:
return SDL_SCANCODE_U;
136 case RETROK_v:
return SDL_SCANCODE_V;
137 case RETROK_w:
return SDL_SCANCODE_W;
138 case RETROK_x:
return SDL_SCANCODE_X;
139 case RETROK_y:
return SDL_SCANCODE_Y;
140 case RETROK_z:
return SDL_SCANCODE_Z;
141 case RETROK_DELETE:
return SDL_SCANCODE_DELETE;
142 case RETROK_KP0:
return SDL_SCANCODE_KP_0;
143 case RETROK_KP1:
return SDL_SCANCODE_KP_1;
144 case RETROK_KP2:
return SDL_SCANCODE_KP_2;
145 case RETROK_KP3:
return SDL_SCANCODE_KP_3;
146 case RETROK_KP4:
return SDL_SCANCODE_KP_4;
147 case RETROK_KP5:
return SDL_SCANCODE_KP_5;
148 case RETROK_KP6:
return SDL_SCANCODE_KP_6;
149 case RETROK_KP7:
return SDL_SCANCODE_KP_7;
150 case RETROK_KP8:
return SDL_SCANCODE_KP_8;
151 case RETROK_KP9:
return SDL_SCANCODE_KP_9;
152 case RETROK_KP_PERIOD:
return SDL_SCANCODE_KP_PERIOD;
153 case RETROK_KP_DIVIDE:
return SDL_SCANCODE_KP_DIVIDE;
154 case RETROK_KP_MULTIPLY:
return SDL_SCANCODE_KP_MULTIPLY;
155 case RETROK_KP_MINUS:
return SDL_SCANCODE_KP_MINUS;
156 case RETROK_KP_PLUS:
return SDL_SCANCODE_KP_PLUS;
157 case RETROK_KP_ENTER:
return SDL_SCANCODE_KP_ENTER;
158 case RETROK_KP_EQUALS:
return SDL_SCANCODE_KP_EQUALS;
159 case RETROK_UP:
return SDL_SCANCODE_UP;
160 case RETROK_DOWN:
return SDL_SCANCODE_DOWN;
161 case RETROK_RIGHT:
return SDL_SCANCODE_RIGHT;
162 case RETROK_LEFT:
return SDL_SCANCODE_LEFT;
163 case RETROK_INSERT:
return SDL_SCANCODE_INSERT;
164 case RETROK_HOME:
return SDL_SCANCODE_HOME;
165 case RETROK_END:
return SDL_SCANCODE_END;
166 case RETROK_PAGEUP:
return SDL_SCANCODE_PAGEUP;
167 case RETROK_PAGEDOWN:
return SDL_SCANCODE_PAGEDOWN;
168 case RETROK_F1:
return SDL_SCANCODE_F1;
169 case RETROK_F2:
return SDL_SCANCODE_F2;
170 case RETROK_F3:
return SDL_SCANCODE_F3;
171 case RETROK_F4:
return SDL_SCANCODE_F4;
172 case RETROK_F5:
return SDL_SCANCODE_F5;
173 case RETROK_F6:
return SDL_SCANCODE_F6;
174 case RETROK_F7:
return SDL_SCANCODE_F7;
175 case RETROK_F8:
return SDL_SCANCODE_F8;
176 case RETROK_F9:
return SDL_SCANCODE_F9;
177 case RETROK_F10:
return SDL_SCANCODE_F10;
178 case RETROK_F11:
return SDL_SCANCODE_F11;
179 case RETROK_F12:
return SDL_SCANCODE_F12;
180 case RETROK_F13:
return SDL_SCANCODE_F13;
181 case RETROK_F14:
return SDL_SCANCODE_F14;
182 case RETROK_F15:
return SDL_SCANCODE_F15;
183 case RETROK_NUMLOCK:
return SDL_SCANCODE_NUMLOCKCLEAR;
184 case RETROK_CAPSLOCK:
return SDL_SCANCODE_CAPSLOCK;
185 case RETROK_SCROLLOCK:
return SDL_SCANCODE_SCROLLLOCK;
186 case RETROK_RSHIFT:
return SDL_SCANCODE_RSHIFT;
187 case RETROK_LSHIFT:
return SDL_SCANCODE_LSHIFT;
188 case RETROK_RCTRL:
return SDL_SCANCODE_RCTRL;
189 case RETROK_LCTRL:
return SDL_SCANCODE_LCTRL;
190 case RETROK_RALT:
return SDL_SCANCODE_RALT;
191 case RETROK_LALT:
return SDL_SCANCODE_LALT;
192 case RETROK_RMETA:
return SDL_SCANCODE_RGUI;
193 case RETROK_LMETA:
return SDL_SCANCODE_LGUI;
194 case RETROK_RSUPER:
return SDL_SCANCODE_RGUI;
195 case RETROK_LSUPER:
return SDL_SCANCODE_LGUI;
196 case RETROK_MENU:
return SDL_SCANCODE_MENU;
197 default:
return SDL_SCANCODE_UNKNOWN;
209static unsigned SDL_Libretro_ScancodeToRetroKey(SDL_Scancode scancode) {
211 case SDL_SCANCODE_BACKSPACE:
return RETROK_BACKSPACE;
212 case SDL_SCANCODE_TAB:
return RETROK_TAB;
213 case SDL_SCANCODE_RETURN:
return RETROK_RETURN;
214 case SDL_SCANCODE_ESCAPE:
return RETROK_ESCAPE;
215 case SDL_SCANCODE_SPACE:
return RETROK_SPACE;
216 case SDL_SCANCODE_APOSTROPHE:
return RETROK_QUOTE;
217 case SDL_SCANCODE_COMMA:
return RETROK_COMMA;
218 case SDL_SCANCODE_MINUS:
return RETROK_MINUS;
219 case SDL_SCANCODE_PERIOD:
return RETROK_PERIOD;
220 case SDL_SCANCODE_SLASH:
return RETROK_SLASH;
221 case SDL_SCANCODE_0:
return RETROK_0;
222 case SDL_SCANCODE_1:
return RETROK_1;
223 case SDL_SCANCODE_2:
return RETROK_2;
224 case SDL_SCANCODE_3:
return RETROK_3;
225 case SDL_SCANCODE_4:
return RETROK_4;
226 case SDL_SCANCODE_5:
return RETROK_5;
227 case SDL_SCANCODE_6:
return RETROK_6;
228 case SDL_SCANCODE_7:
return RETROK_7;
229 case SDL_SCANCODE_8:
return RETROK_8;
230 case SDL_SCANCODE_9:
return RETROK_9;
231 case SDL_SCANCODE_SEMICOLON:
return RETROK_SEMICOLON;
232 case SDL_SCANCODE_EQUALS:
return RETROK_EQUALS;
233 case SDL_SCANCODE_LEFTBRACKET:
return RETROK_LEFTBRACKET;
234 case SDL_SCANCODE_BACKSLASH:
return RETROK_BACKSLASH;
235 case SDL_SCANCODE_RIGHTBRACKET:
return RETROK_RIGHTBRACKET;
236 case SDL_SCANCODE_GRAVE:
return RETROK_BACKQUOTE;
237 case SDL_SCANCODE_A:
return RETROK_a;
238 case SDL_SCANCODE_B:
return RETROK_b;
239 case SDL_SCANCODE_C:
return RETROK_c;
240 case SDL_SCANCODE_D:
return RETROK_d;
241 case SDL_SCANCODE_E:
return RETROK_e;
242 case SDL_SCANCODE_F:
return RETROK_f;
243 case SDL_SCANCODE_G:
return RETROK_g;
244 case SDL_SCANCODE_H:
return RETROK_h;
245 case SDL_SCANCODE_I:
return RETROK_i;
246 case SDL_SCANCODE_J:
return RETROK_j;
247 case SDL_SCANCODE_K:
return RETROK_k;
248 case SDL_SCANCODE_L:
return RETROK_l;
249 case SDL_SCANCODE_M:
return RETROK_m;
250 case SDL_SCANCODE_N:
return RETROK_n;
251 case SDL_SCANCODE_O:
return RETROK_o;
252 case SDL_SCANCODE_P:
return RETROK_p;
253 case SDL_SCANCODE_Q:
return RETROK_q;
254 case SDL_SCANCODE_R:
return RETROK_r;
255 case SDL_SCANCODE_S:
return RETROK_s;
256 case SDL_SCANCODE_T:
return RETROK_t;
257 case SDL_SCANCODE_U:
return RETROK_u;
258 case SDL_SCANCODE_V:
return RETROK_v;
259 case SDL_SCANCODE_W:
return RETROK_w;
260 case SDL_SCANCODE_X:
return RETROK_x;
261 case SDL_SCANCODE_Y:
return RETROK_y;
262 case SDL_SCANCODE_Z:
return RETROK_z;
263 case SDL_SCANCODE_DELETE:
return RETROK_DELETE;
264 case SDL_SCANCODE_KP_0:
return RETROK_KP0;
265 case SDL_SCANCODE_KP_1:
return RETROK_KP1;
266 case SDL_SCANCODE_KP_2:
return RETROK_KP2;
267 case SDL_SCANCODE_KP_3:
return RETROK_KP3;
268 case SDL_SCANCODE_KP_4:
return RETROK_KP4;
269 case SDL_SCANCODE_KP_5:
return RETROK_KP5;
270 case SDL_SCANCODE_KP_6:
return RETROK_KP6;
271 case SDL_SCANCODE_KP_7:
return RETROK_KP7;
272 case SDL_SCANCODE_KP_8:
return RETROK_KP8;
273 case SDL_SCANCODE_KP_9:
return RETROK_KP9;
274 case SDL_SCANCODE_KP_PERIOD:
return RETROK_KP_PERIOD;
275 case SDL_SCANCODE_KP_DIVIDE:
return RETROK_KP_DIVIDE;
276 case SDL_SCANCODE_KP_MULTIPLY:
return RETROK_KP_MULTIPLY;
277 case SDL_SCANCODE_KP_MINUS:
return RETROK_KP_MINUS;
278 case SDL_SCANCODE_KP_PLUS:
return RETROK_KP_PLUS;
279 case SDL_SCANCODE_KP_ENTER:
return RETROK_KP_ENTER;
280 case SDL_SCANCODE_KP_EQUALS:
return RETROK_KP_EQUALS;
281 case SDL_SCANCODE_UP:
return RETROK_UP;
282 case SDL_SCANCODE_DOWN:
return RETROK_DOWN;
283 case SDL_SCANCODE_RIGHT:
return RETROK_RIGHT;
284 case SDL_SCANCODE_LEFT:
return RETROK_LEFT;
285 case SDL_SCANCODE_INSERT:
return RETROK_INSERT;
286 case SDL_SCANCODE_HOME:
return RETROK_HOME;
287 case SDL_SCANCODE_END:
return RETROK_END;
288 case SDL_SCANCODE_PAGEUP:
return RETROK_PAGEUP;
289 case SDL_SCANCODE_PAGEDOWN:
return RETROK_PAGEDOWN;
290 case SDL_SCANCODE_F1:
return RETROK_F1;
291 case SDL_SCANCODE_F2:
return RETROK_F2;
292 case SDL_SCANCODE_F3:
return RETROK_F3;
293 case SDL_SCANCODE_F4:
return RETROK_F4;
294 case SDL_SCANCODE_F5:
return RETROK_F5;
295 case SDL_SCANCODE_F6:
return RETROK_F6;
296 case SDL_SCANCODE_F7:
return RETROK_F7;
297 case SDL_SCANCODE_F8:
return RETROK_F8;
298 case SDL_SCANCODE_F9:
return RETROK_F9;
299 case SDL_SCANCODE_F10:
return RETROK_F10;
300 case SDL_SCANCODE_F11:
return RETROK_F11;
301 case SDL_SCANCODE_F12:
return RETROK_F12;
302 case SDL_SCANCODE_F13:
return RETROK_F13;
303 case SDL_SCANCODE_F14:
return RETROK_F14;
304 case SDL_SCANCODE_F15:
return RETROK_F15;
305 case SDL_SCANCODE_NUMLOCKCLEAR:
return RETROK_NUMLOCK;
306 case SDL_SCANCODE_CAPSLOCK:
return RETROK_CAPSLOCK;
307 case SDL_SCANCODE_SCROLLLOCK:
return RETROK_SCROLLOCK;
308 case SDL_SCANCODE_RSHIFT:
return RETROK_RSHIFT;
309 case SDL_SCANCODE_LSHIFT:
return RETROK_LSHIFT;
310 case SDL_SCANCODE_RCTRL:
return RETROK_RCTRL;
311 case SDL_SCANCODE_LCTRL:
return RETROK_LCTRL;
312 case SDL_SCANCODE_RALT:
return RETROK_RALT;
313 case SDL_SCANCODE_LALT:
return RETROK_LALT;
314 case SDL_SCANCODE_RGUI:
return RETROK_RMETA;
315 case SDL_SCANCODE_LGUI:
return RETROK_LMETA;
316 case SDL_SCANCODE_MENU:
return RETROK_MENU;
317 default:
return RETROK_UNKNOWN;
325static uint16_t SDL_Libretro_KeymodToRetroMod(SDL_Keymod mod) {
326 uint16_t retromod = RETROKMOD_NONE;
327 if (mod & SDL_KMOD_SHIFT) retromod |= RETROKMOD_SHIFT;
328 if (mod & SDL_KMOD_CTRL) retromod |= RETROKMOD_CTRL;
329 if (mod & SDL_KMOD_ALT) retromod |= RETROKMOD_ALT;
330 if (mod & SDL_KMOD_GUI) retromod |= RETROKMOD_META;
331 if (mod & SDL_KMOD_NUM) retromod |= RETROKMOD_NUMLOCK;
332 if (mod & SDL_KMOD_CAPS) retromod |= RETROKMOD_CAPSLOCK;
333 if (mod & SDL_KMOD_SCROLL) retromod |= RETROKMOD_SCROLLOCK;
337static void SDL_Libretro_InputPoll(
void) {
342 SDL_GetMouseState(&lr->core.inputMouseX, &lr->core.inputMouseY);
346 lr->core.inputMotionX = SDL_truncf(lr->core.inputMotionAccumX);
347 lr->core.inputMotionY = SDL_truncf(lr->core.inputMotionAccumY);
348 lr->core.inputMotionAccumX -= lr->core.inputMotionX;
349 lr->core.inputMotionAccumY -= lr->core.inputMotionY;
352 lr->core.inputWheelX = lr->core.inputWheelAccumX;
353 lr->core.inputWheelY = lr->core.inputWheelAccumY;
354 lr->core.inputWheelAccumX = 0.0f;
355 lr->core.inputWheelAccumY = 0.0f;
358static bool SDL_Libretro_IsKeyDown(SDL_Scancode scancode) {
361 const bool* state = SDL_GetKeyboardState(&numKeys);
362 return scancode > SDL_SCANCODE_UNKNOWN && (int)scancode < numKeys && state[scancode];
376static bool SDL_Libretro_PointerCoords(
const SDL_Libretro* lr, int16_t* outX, int16_t* outY) {
377 float mx = lr->core.inputMouseX;
378 float my = lr->core.inputMouseY;
383 SDL_RenderCoordinatesFromWindow(lr->renderer, mx, my, &mx, &my);
386 SDL_FRect r = lr->core.renderDstRect;
387 bool inside = r.w > 0.0f && r.h > 0.0f &&
388 mx >= r.x && mx < r.x + r.w &&
389 my >= r.y && my < r.y + r.h;
391 if (r.w <= 0.0f || r.h <= 0.0f) {
398 float sx = (mx - r.x) / r.w;
399 float sy = (my - r.y) / r.h;
403 switch (lr->core.rotation & 3) {
422 if (outX) *outX = (int16_t)(SDL_clamp(u * 2.0f - 1.0f, -1.0f, 1.0f) * 0x7FFF);
423 if (outY) *outY = (int16_t)(SDL_clamp(v * 2.0f - 1.0f, -1.0f, 1.0f) * 0x7FFF);
427static int16_t SDL_Libretro_InputState(
unsigned port,
unsigned device,
unsigned index,
unsigned id) {
433 if (lr->rewindActive)
return 0;
435 unsigned baseDevice = device & RETRO_DEVICE_MASK;
437 switch (baseDevice) {
438 case RETRO_DEVICE_JOYPAD: {
439 if (
id == RETRO_DEVICE_ID_JOYPAD_MASK) {
441 for (
unsigned b = 0; b <= RETRO_DEVICE_ID_JOYPAD_R3; b++) {
442 if (SDL_Libretro_InputState(port, device, index, b)) {
451 lr->core.virtualJoypadState[port][
id]) {
456 if (port == 0 &&
id <= RETRO_DEVICE_ID_JOYPAD_R3) {
457 if (SDL_Libretro_IsKeyDown(lr->keyboardPlayer1[
id])) {
463 if (port < SDL_LIBRETRO_MAX_USERS && lr->gamepads[port]) {
465 if (
id == RETRO_DEVICE_ID_JOYPAD_L2 &&
466 SDL_GetGamepadAxis(lr->gamepads[port], SDL_GAMEPAD_AXIS_LEFT_TRIGGER) > 8192) {
469 if (
id == RETRO_DEVICE_ID_JOYPAD_R2 &&
470 SDL_GetGamepadAxis(lr->gamepads[port], SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) > 8192) {
475 if (SDL_Libretro_AnalogToDigitalPressed(lr, port,
id)) {
479 SDL_GamepadButton btn = SDL_Libretro_RetroJoypadToGamepadButton(lr, port,
id);
480 if (btn != SDL_GAMEPAD_BUTTON_INVALID) {
481 return SDL_GetGamepadButton(lr->gamepads[port], btn) ? 1 : 0;
487 case RETRO_DEVICE_ANALOG: {
488 if (port < SDL_LIBRETRO_MAX_USERS && lr->gamepads[port]) {
489 SDL_Gamepad* gp = lr->gamepads[port];
490 if (index == RETRO_DEVICE_INDEX_ANALOG_LEFT ||
491 index == RETRO_DEVICE_INDEX_ANALOG_RIGHT) {
492 SDL_GamepadAxis axis = SDL_GAMEPAD_AXIS_INVALID;
493 if (index == RETRO_DEVICE_INDEX_ANALOG_LEFT) {
494 axis = (
id == RETRO_DEVICE_ID_ANALOG_X) ? SDL_GAMEPAD_AXIS_LEFTX : SDL_GAMEPAD_AXIS_LEFTY;
497 axis = (
id == RETRO_DEVICE_ID_ANALOG_X) ? SDL_GAMEPAD_AXIS_RIGHTX : SDL_GAMEPAD_AXIS_RIGHTY;
499 return SDL_GetGamepadAxis(gp, axis);
501 if (index == RETRO_DEVICE_INDEX_ANALOG_BUTTON) {
504 if (
id == RETRO_DEVICE_ID_JOYPAD_L2) {
505 return SDL_GetGamepadAxis(gp, SDL_GAMEPAD_AXIS_LEFT_TRIGGER);
507 if (
id == RETRO_DEVICE_ID_JOYPAD_R2) {
508 return SDL_GetGamepadAxis(gp, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
510 SDL_GamepadButton btn = SDL_Libretro_RetroJoypadToGamepadButton(lr, port,
id);
511 if (btn != SDL_GAMEPAD_BUTTON_INVALID && SDL_GetGamepadButton(gp, btn)) {
519 case RETRO_DEVICE_KEYBOARD: {
520 SDL_Scancode sc = SDL_Libretro_RetroKeyToScancode(
id);
521 return SDL_Libretro_IsKeyDown(sc) ? 1 : 0;
524 case RETRO_DEVICE_MOUSE: {
525 if (port != lr->mousePort)
return 0;
527 case RETRO_DEVICE_ID_MOUSE_X:
528 return (int16_t)SDL_clamp(lr->core.inputMotionX, -32768.0f, 32767.0f);
529 case RETRO_DEVICE_ID_MOUSE_Y:
530 return (int16_t)SDL_clamp(lr->core.inputMotionY, -32768.0f, 32767.0f);
531 case RETRO_DEVICE_ID_MOUSE_LEFT: {
532 Uint32 state = SDL_GetMouseState(NULL, NULL);
533 return (state & SDL_BUTTON_LMASK) ? 1 : 0;
535 case RETRO_DEVICE_ID_MOUSE_RIGHT: {
536 Uint32 state = SDL_GetMouseState(NULL, NULL);
537 return (state & SDL_BUTTON_RMASK) ? 1 : 0;
539 case RETRO_DEVICE_ID_MOUSE_MIDDLE: {
540 Uint32 state = SDL_GetMouseState(NULL, NULL);
541 return (state & SDL_BUTTON_MMASK) ? 1 : 0;
543 case RETRO_DEVICE_ID_MOUSE_BUTTON_4: {
544 Uint32 state = SDL_GetMouseState(NULL, NULL);
545 return (state & SDL_BUTTON_X1MASK) ? 1 : 0;
547 case RETRO_DEVICE_ID_MOUSE_BUTTON_5: {
548 Uint32 state = SDL_GetMouseState(NULL, NULL);
549 return (state & SDL_BUTTON_X2MASK) ? 1 : 0;
551 case RETRO_DEVICE_ID_MOUSE_WHEELUP:
552 return lr->core.inputWheelY > 0.0f ? 1 : 0;
553 case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
554 return lr->core.inputWheelY < 0.0f ? 1 : 0;
555 case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
556 return lr->core.inputWheelX > 0.0f ? 1 : 0;
557 case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
558 return lr->core.inputWheelX < 0.0f ? 1 : 0;
563 case RETRO_DEVICE_POINTER: {
564 if (port != lr->mousePort || index > 0)
return 0;
567 case RETRO_DEVICE_ID_POINTER_X: {
569 SDL_Libretro_PointerCoords(lr, &x, NULL);
572 case RETRO_DEVICE_ID_POINTER_Y: {
574 SDL_Libretro_PointerCoords(lr, NULL, &y);
577 case RETRO_DEVICE_ID_POINTER_PRESSED:
578 case RETRO_DEVICE_ID_POINTER_COUNT: {
579 Uint32 state = SDL_GetMouseState(NULL, NULL);
580 return (state & SDL_BUTTON_LMASK) ? 1 : 0;
582 case RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN:
583 return SDL_Libretro_PointerCoords(lr, NULL, NULL) ? 0 : 1;
588 case RETRO_DEVICE_LIGHTGUN: {
589 if (port != lr->mousePort)
return 0;
592 case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X:
593 case RETRO_DEVICE_ID_LIGHTGUN_X: {
595 SDL_Libretro_PointerCoords(lr, &x, NULL);
598 case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y:
599 case RETRO_DEVICE_ID_LIGHTGUN_Y: {
601 SDL_Libretro_PointerCoords(lr, NULL, &y);
604 case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN:
605 return SDL_Libretro_PointerCoords(lr, NULL, NULL) ? 0 : 1;
609 case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: {
610 Uint32 state = SDL_GetMouseState(NULL, NULL);
611 return (state & SDL_BUTTON_LMASK) ? 1 : 0;
613 case RETRO_DEVICE_ID_LIGHTGUN_RELOAD: {
616 Uint32 state = SDL_GetMouseState(NULL, NULL);
617 if (state & SDL_BUTTON_RMASK)
return 1;
618 if ((state & SDL_BUTTON_LMASK) && !SDL_Libretro_PointerCoords(lr, NULL, NULL))
return 1;
621 case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: {
622 Uint32 state = SDL_GetMouseState(NULL, NULL);
623 return (state & SDL_BUTTON_MMASK) ? 1 : 0;
625 case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: {
626 Uint32 state = SDL_GetMouseState(NULL, NULL);
627 return (state & SDL_BUTTON_X1MASK) ? 1 : 0;
629 case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: {
630 Uint32 state = SDL_GetMouseState(NULL, NULL);
631 return (state & SDL_BUTTON_X2MASK) ? 1 : 0;
633 case RETRO_DEVICE_ID_LIGHTGUN_START:
634 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_RETURN) ? 1 : 0;
635 case RETRO_DEVICE_ID_LIGHTGUN_SELECT:
636 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_RSHIFT) ? 1 : 0;
637 case RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP:
638 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_UP) ? 1 : 0;
639 case RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN:
640 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_DOWN) ? 1 : 0;
641 case RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT:
642 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_LEFT) ? 1 : 0;
643 case RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT:
644 return SDL_Libretro_IsKeyDown(SDL_SCANCODE_RIGHT) ? 1 : 0;
664 if (!lr || !event)
return;
666 switch (event->type) {
667 case SDL_EVENT_MOUSE_WHEEL: {
670 lr->core.inputWheelAccumX +=
event->wheel.x;
671 lr->core.inputWheelAccumY +=
event->wheel.y;
674 case SDL_EVENT_MOUSE_MOTION: {
677 lr->core.inputMotionAccumX +=
event->motion.xrel;
678 lr->core.inputMotionAccumY +=
event->motion.yrel;
681 case SDL_EVENT_GAMEPAD_ADDED: {
682 SDL_JoystickID jid =
event->gdevice.which;
683 SDL_Gamepad* gp = SDL_OpenGamepad(jid);
687 if (!lr->gamepads[i]) {
688 lr->gamepads[i] = gp;
689 const char* name = SDL_GetGamepadName(gp);
690 if (i + 1 > lr->gamepadCount) lr->gamepadCount = i + 1;
691 SDL_Log(
"[SDL_Libretro] Gamepad added: #%u %s", i + 1, name ? name :
"");
698 const char* name = SDL_GetGamepadName(gp);
699 SDL_Log(
"[SDL_Libretro] Gamepad ignored, no free port: %s", name ? name :
"");
700 SDL_CloseGamepad(gp);
705 case SDL_EVENT_GAMEPAD_REMOVED: {
706 SDL_JoystickID jid =
event->gdevice.which;
708 if (lr->gamepads[i] && SDL_GetGamepadID(lr->gamepads[i]) == jid) {
709 const char* name = SDL_GetGamepadName(lr->gamepads[i]);
710 SDL_Log(
"[SDL_Libretro] Gamepad removed: #%u %s", i + 1, name ? name :
"");
711 SDL_CloseGamepad(lr->gamepads[i]);
712 lr->gamepads[i] = NULL;
714 lr->gamepadCount = 0;
716 if (lr->gamepads[j]) lr->gamepadCount = j + 1;
723 case SDL_EVENT_KEY_DOWN:
724 case SDL_EVENT_KEY_UP: {
725 if (lr->core.keyboard_event) {
726 bool down = (
event->type == SDL_EVENT_KEY_DOWN);
727 unsigned retrokey = SDL_Libretro_ScancodeToRetroKey(event->key.scancode);
728 uint16_t modmask = SDL_Libretro_KeymodToRetroMod(event->key.mod);
732 uint32_t character = 0;
733 SDL_Keycode key = SDL_GetKeyFromScancode(event->key.scancode, event->key.mod,
false);
734 if (key >= 0x20 && key < 0x110000 &&
735 !(key & SDLK_SCANCODE_MASK)) {
736 character = (uint32_t)key;
739 lr->core.keyboard_event(down, retrokey, character, modmask);
764 lr->core.portDeviceMap[port] = device;
766 lr->core.symbols.retro_set_controller_port_device(port, device);
786 return lr->core.portDeviceMap[port];
802 if (!lr || retroButton < 0 || retroButton > RETRO_DEVICE_ID_JOYPAD_R3)
return;
803 lr->keyboardPlayer1[retroButton] = scancode;
818 retroButton < 0 || retroButton > RETRO_DEVICE_ID_JOYPAD_R3) {
821 lr->gamepadButtons[port][retroButton] = button;
840 lr->analogToDigital[port] = stick;
855 return lr->analogToDigital[port];
870 lr->mousePort = port;
882 return lr ? lr->mousePort : 0;
900 button < 0 || button >= SDL_LIBRETRO_MAX_JOYPAD_BUTTONS) {
903 lr->core.virtualJoypadState[port][button] = pressed;
943 const struct retro_input_descriptor* d = &lr->core.inputDescriptors[index];
944 if (port) *port = d->port;
945 if (device) *device = d->device;
947 if (description) *description = d->description;
953static SDL_Sensor* SDL_Libretro_OpenSensorByType(SDL_SensorType type) {
955 SDL_SensorID* sensors = SDL_GetSensors(&count);
956 if (!sensors)
return NULL;
957 SDL_Sensor* result = NULL;
958 for (
int i = 0; i < count; i++) {
959 if (SDL_GetSensorTypeForID(sensors[i]) == type) {
960 result = SDL_OpenSensor(sensors[i]);
968static bool SDL_Libretro_SetSensorState(
unsigned port,
enum retro_sensor_action action,
unsigned rate) {
974 case RETRO_SENSOR_ACCELEROMETER_ENABLE:
975 if (!lr->core.sensorAccel[port]) {
976 lr->core.sensorAccel[port] = SDL_Libretro_OpenSensorByType(SDL_SENSOR_ACCEL);
978 return lr->core.sensorAccel[port] != NULL;
979 case RETRO_SENSOR_ACCELEROMETER_DISABLE:
980 if (lr->core.sensorAccel[port]) {
981 SDL_CloseSensor(lr->core.sensorAccel[port]);
982 lr->core.sensorAccel[port] = NULL;
984 SDL_memset(lr->core.sensorAccelData[port], 0,
sizeof(lr->core.sensorAccelData[port]));
986 case RETRO_SENSOR_GYROSCOPE_ENABLE:
987 if (!lr->core.sensorGyro[port]) {
988 lr->core.sensorGyro[port] = SDL_Libretro_OpenSensorByType(SDL_SENSOR_GYRO);
990 return lr->core.sensorGyro[port] != NULL;
991 case RETRO_SENSOR_GYROSCOPE_DISABLE:
992 if (lr->core.sensorGyro[port]) {
993 SDL_CloseSensor(lr->core.sensorGyro[port]);
994 lr->core.sensorGyro[port] = NULL;
996 SDL_memset(lr->core.sensorGyroData[port], 0,
sizeof(lr->core.sensorGyroData[port]));
1006static float SDL_Libretro_GetSensorInput(
unsigned port,
unsigned id) {
1011 if (id <= RETRO_SENSOR_ACCELEROMETER_Z && lr->core.sensorAccel[port]) {
1013 if (SDL_GetSensorData(lr->core.sensorAccel[port], data, 3)) {
1014 lr->core.sensorAccelData[port][0] = data[0] / SDL_STANDARD_GRAVITY;
1015 lr->core.sensorAccelData[port][1] = data[1] / SDL_STANDARD_GRAVITY;
1016 lr->core.sensorAccelData[port][2] = data[2] / SDL_STANDARD_GRAVITY;
1018 return lr->core.sensorAccelData[port][
id - RETRO_SENSOR_ACCELEROMETER_X];
1022 if (
id >= RETRO_SENSOR_GYROSCOPE_X && id <= RETRO_SENSOR_GYROSCOPE_Z && lr->core.sensorGyro[port]) {
1024 if (SDL_GetSensorData(lr->core.sensorGyro[port], data, 3)) {
1025 lr->core.sensorGyroData[port][0] = data[0];
1026 lr->core.sensorGyroData[port][1] = data[1];
1027 lr->core.sensorGyroData[port][2] = data[2];
1029 return lr->core.sensorGyroData[port][
id - RETRO_SENSOR_GYROSCOPE_X];
1037static void SDL_Libretro_CloseSensors(SDL_Libretro* lr) {
1042 if (lr->core.sensorAccel[i]) {
1043 SDL_CloseSensor(lr->core.sensorAccel[i]);
1044 lr->core.sensorAccel[i] = NULL;
1046 lr->core.sensorAccelData[i][0] = 0.0f;
1047 lr->core.sensorAccelData[i][1] = 0.0f;
1048 lr->core.sensorAccelData[i][2] = 0.0f;
1051 if (lr->core.sensorGyro[i]) {
1052 SDL_CloseSensor(lr->core.sensorGyro[i]);
1053 lr->core.sensorGyro[i] = NULL;
1055 lr->core.sensorGyroData[i][0] = 0.0f;
1056 lr->core.sensorGyroData[i][1] = 0.0f;
1057 lr->core.sensorGyroData[i][2] = 0.0f;
#define SDL_LIBRETRO_MAX_USERS
The number of controller ports (gamepads) the frontend tracks.
bool SDL_Libretro_IsCoreReady(const SDL_Libretro *lr)
Indicates whether a core is loaded.
unsigned SDL_Libretro_GetInputDescriptorCount(const SDL_Libretro *lr)
Retrieve the number of input descriptors provided by a Libretro core.
bool SDL_Libretro_SetPortDevice(SDL_Libretro *lr, unsigned port, unsigned device)
Assign a device type to a controller port.
unsigned SDL_Libretro_GetPortDevice(const SDL_Libretro *lr, unsigned port)
Get the device type assigned to a controller port.
bool SDL_Libretro_GetInputDescriptor(const SDL_Libretro *lr, unsigned index, unsigned *port, unsigned *device, unsigned *id, const char **description)
Retrieve an input descriptor by index.
struct SDL_Libretro SDL_Libretro
A libretro frontend context: one loaded core, its game, and the settings that carry across cores.
void SDL_Libretro_SetGamepadMapping(SDL_Libretro *lr, unsigned port, int retroButton, SDL_GamepadButton button)
Maps an SDL gamepad button to a RETRO_DEVICE_ID_JOYPAD_* button on the given controller port.
void SDL_Libretro_SetMousePort(SDL_Libretro *lr, unsigned port)
Selects the one controller port that the mouse drives.
SDL_LibretroAnalogToDigital SDL_Libretro_GetAnalogToDigital(const SDL_Libretro *lr, unsigned port)
Get the analog stick that also registers D-Pad presses on a controller port.
void SDL_Libretro_SetVirtualButton(SDL_Libretro *lr, unsigned port, int button, bool pressed)
Press or release a joypad button from code, such as from an on-screen touch control.
void SDL_Libretro_HandleEvent(SDL_Libretro *lr, const SDL_Event *event)
Call this function within the SDL_PollEvent() loop to ensure libretro knows of important events.
void SDL_Libretro_SetAnalogToDigital(SDL_Libretro *lr, unsigned port, SDL_LibretroAnalogToDigital stick)
Selects which analog stick, if any, also registers D-Pad presses on the given controller port,...
SDL_LibretroAnalogToDigital
Which analog stick, if any, also registers D-Pad presses for a controller port.
unsigned SDL_Libretro_GetMousePort(const SDL_Libretro *lr)
Get the controller port that the mouse drives.
void SDL_Libretro_SetKeyboardMapping(SDL_Libretro *lr, int retroButton, SDL_Scancode scancode)
Maps a keyboard key to a RETRO_DEVICE_ID_JOYPAD_* button for Player 1 (controller port 0).
@ SDL_LIBRETRO_ANALOG_TO_DIGITAL_NONE
Only the D-Pad drives the retro joypad's directions.
@ SDL_LIBRETRO_ANALOG_TO_DIGITAL_RIGHT
The right analog stick also registers D-Pad presses.
@ SDL_LIBRETRO_ANALOG_TO_DIGITAL_COUNT
The number of possible modes.