diff --git a/src/core.cpp b/src/core.cpp
index 25cf5c4c..93feb82b 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -30,6 +30,7 @@
#include "mkxp-polyfill.h" // std::mutex
#include "git-hash.h"
+#include "core.h"
#include "binding-sandbox.h"
#include "al-util.h"
@@ -158,6 +159,7 @@ namespace mkxp_retro {
retro_input_state_t input_state;
struct retro_perf_callback perf;
retro_hw_render_callback hw_render;
+ bool keyboard_state[RETROK_LAST];
bool input_polled;
uint64_t get_ticks_ms() noexcept {
@@ -427,6 +429,16 @@ extern "C" RETRO_API void retro_set_environment(retro_environment_t cb) {
log_printf = fallback_log;
}
+ static const struct retro_keyboard_callback keyboard = {
+ .callback = [](bool down, unsigned int keycode, uint32_t character, uint16_t key_modifiers) {
+ if (keycode < RETROK_LAST) {
+ keyboard_state[keycode] = down;
+ }
+ }
+ };
+ std::memset(keyboard_state, 0, sizeof keyboard_state);
+ cb(RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, (void *)&keyboard);
+
perf = {
.get_time_usec = nullptr,
.get_cpu_features = nullptr,
diff --git a/src/core.h b/src/core.h
index e7c6c932..a86ac428 100644
--- a/src/core.h
+++ b/src/core.h
@@ -42,6 +42,7 @@ namespace mkxp_retro {
extern retro_input_state_t input_state;
extern struct retro_perf_callback perf;
extern struct retro_hw_render_callback hw_render;
+ extern bool keyboard_state[RETROK_LAST];
extern bool input_polled;
uint64_t get_ticks_ms() noexcept;
diff --git a/src/input/input-retro.cpp b/src/input/input-retro.cpp
index b810fcfd..8c6bcf99 100644
--- a/src/input/input-retro.cpp
+++ b/src/input/input-retro.cpp
@@ -19,6 +19,7 @@
** along with mkxp. If not, see .
*/
+#include
#include "input.h"
#include "core.h"
#include "sharedstate.h"
@@ -26,11 +27,11 @@
#include "mkxp-polyfill.h" // std::lround
#define JOYPAD_BUTTON_MAX 16
-#define REPEAT_NONE 255
+#define REPEATING_NONE 255
#define REPEAT_START (rgssVer >= 2 ? 0.375 : 0.400)
#define REPEAT_DELAY 0.1
-static std::unordered_map codeToJoypadId = {
+static const std::unordered_map codeToJoypadId = {
{Input::Down, RETRO_DEVICE_ID_JOYPAD_DOWN},
{Input::Left, RETRO_DEVICE_ID_JOYPAD_LEFT},
{Input::Right, RETRO_DEVICE_ID_JOYPAD_RIGHT},
@@ -55,101 +56,691 @@ static const uint8_t otherDirs[4][3] = {
{ RETRO_DEVICE_ID_JOYPAD_DOWN, RETRO_DEVICE_ID_JOYPAD_UP, RETRO_DEVICE_ID_JOYPAD_LEFT }, /* Right */
};
+static const enum retro_key scancodeToRetrok[] = {
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_a,
+ RETROK_b,
+ RETROK_c,
+ RETROK_d,
+ RETROK_e,
+ RETROK_f,
+ RETROK_g,
+ RETROK_h,
+ RETROK_i,
+ RETROK_j,
+ RETROK_k,
+ RETROK_l,
+ RETROK_m,
+ RETROK_n,
+ RETROK_o,
+ RETROK_p,
+ RETROK_q,
+ RETROK_r,
+ RETROK_s,
+ RETROK_t,
+ RETROK_u,
+ RETROK_v,
+ RETROK_w,
+ RETROK_x,
+ RETROK_y,
+ RETROK_z,
+ RETROK_1,
+ RETROK_2,
+ RETROK_3,
+ RETROK_4,
+ RETROK_5,
+ RETROK_6,
+ RETROK_7,
+ RETROK_8,
+ RETROK_9,
+ RETROK_0,
+ RETROK_RETURN,
+ RETROK_ESCAPE,
+ RETROK_BACKSPACE,
+ RETROK_TAB,
+ RETROK_SPACE,
+ RETROK_MINUS,
+ RETROK_EQUALS,
+ RETROK_LEFTBRACKET,
+ RETROK_RIGHTBRACKET,
+ RETROK_BACKSLASH,
+ RETROK_BACKSLASH,
+ RETROK_SEMICOLON,
+ RETROK_QUOTE,
+ RETROK_BACKQUOTE,
+ RETROK_COMMA,
+ RETROK_PERIOD,
+ RETROK_SLASH,
+ RETROK_CAPSLOCK,
+ RETROK_F1,
+ RETROK_F2,
+ RETROK_F3,
+ RETROK_F4,
+ RETROK_F5,
+ RETROK_F6,
+ RETROK_F7,
+ RETROK_F8,
+ RETROK_F9,
+ RETROK_F10,
+ RETROK_F11,
+ RETROK_F12,
+ RETROK_UNKNOWN,
+ RETROK_SCROLLOCK,
+ RETROK_PAUSE,
+ RETROK_INSERT,
+ RETROK_HOME,
+ RETROK_PAGEUP,
+ RETROK_DELETE,
+ RETROK_END,
+ RETROK_PAGEDOWN,
+ RETROK_RIGHT,
+ RETROK_LEFT,
+ RETROK_DOWN,
+ RETROK_UP,
+ RETROK_NUMLOCK,
+ RETROK_KP_DIVIDE,
+ RETROK_KP_MULTIPLY,
+ RETROK_KP_MINUS,
+ RETROK_KP_PLUS,
+ RETROK_KP_ENTER,
+ RETROK_KP1,
+ RETROK_KP2,
+ RETROK_KP3,
+ RETROK_KP4,
+ RETROK_KP5,
+ RETROK_KP6,
+ RETROK_KP7,
+ RETROK_KP8,
+ RETROK_KP9,
+ RETROK_KP0,
+ RETROK_KP_PERIOD,
+ RETROK_BACKSLASH,
+ RETROK_COMPOSE,
+ RETROK_POWER,
+ RETROK_KP_EQUALS,
+ RETROK_F13,
+ RETROK_F14,
+ RETROK_F15,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_HELP,
+ RETROK_MENU,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNDO,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_VOLUME_MUTE,
+ RETROK_VOLUME_UP,
+ RETROK_VOLUME_DOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_SYSREQ,
+ RETROK_UNKNOWN,
+ RETROK_CLEAR,
+ RETROK_PAGEUP,
+ RETROK_UNKNOWN,
+ RETROK_KP_PERIOD,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_KP_PERIOD,
+ RETROK_KP_PERIOD,
+ RETROK_KP_PERIOD,
+ RETROK_KP_PERIOD,
+ RETROK_LEFTPAREN,
+ RETROK_RIGHTPAREN,
+ RETROK_LEFTBRACE,
+ RETROK_RIGHTBRACE,
+ RETROK_TAB,
+ RETROK_BACKSPACE,
+ RETROK_a,
+ RETROK_b,
+ RETROK_c,
+ RETROK_d,
+ RETROK_e,
+ RETROK_f,
+ RETROK_UNKNOWN,
+ RETROK_CARET,
+ RETROK_UNKNOWN,
+ RETROK_LESS,
+ RETROK_GREATER,
+ RETROK_AMPERSAND,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_COLON,
+ RETROK_HASH,
+ RETROK_SPACE,
+ RETROK_AT,
+ RETROK_EXCLAIM,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_LCTRL,
+ RETROK_LSHIFT,
+ RETROK_LALT,
+ RETROK_LSUPER,
+ RETROK_RCTRL,
+ RETROK_RSHIFT,
+ RETROK_RALT,
+ RETROK_RSUPER,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_MEDIA_NEXT,
+ RETROK_MEDIA_PREV,
+ RETROK_MEDIA_STOP,
+ RETROK_MEDIA_PLAY_PAUSE,
+ RETROK_VOLUME_MUTE,
+ RETROK_LAUNCH_MEDIA,
+ RETROK_UNKNOWN,
+ RETROK_LAUNCH_MAIL,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_BROWSER_SEARCH,
+ RETROK_BROWSER_HOME,
+ RETROK_BROWSER_BACK,
+ RETROK_BROWSER_FORWARD,
+ RETROK_BROWSER_STOP,
+ RETROK_BROWSER_REFRESH,
+ RETROK_BROWSER_FAVORITES,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_LAUNCH_APP1,
+ RETROK_LAUNCH_APP2,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+};
+
+#define NUM_SCANCODES (sizeof scancodeToRetrok / sizeof *scancodeToRetrok)
+
+static const enum retro_key vkeyToRetrok[] = {
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN, // left mouse button; specially handled
+ RETROK_UNKNOWN, // right mouse button; specially handled
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN, // middle mouse button; specially handled
+ RETROK_UNKNOWN, // mouse button 4; specially handled
+ RETROK_UNKNOWN, // mouse button 5; specially handled
+ RETROK_UNKNOWN,
+ RETROK_BACKSPACE,
+ RETROK_TAB,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_CLEAR,
+ RETROK_RETURN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN, // shift; specially handled to map to both RETROK_LSHIFT and RETROK_RSHIFT
+ RETROK_UNKNOWN, // ctrl; specially handled to map to both RETROK_LCTRL and RETROK_RCTRL
+ RETROK_UNKNOWN, // alt; specially handled to map to both RETROK_LALT and RETROK_RALT
+ RETROK_PAUSE,
+ RETROK_CAPSLOCK,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_ESCAPE,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_SPACE,
+ RETROK_PAGEUP,
+ RETROK_PAGEDOWN,
+ RETROK_END,
+ RETROK_HOME,
+ RETROK_LEFT,
+ RETROK_UP,
+ RETROK_RIGHT,
+ RETROK_DOWN,
+ RETROK_UNKNOWN,
+ RETROK_PRINT,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_INSERT,
+ RETROK_DELETE,
+ RETROK_HELP,
+ RETROK_0,
+ RETROK_1,
+ RETROK_2,
+ RETROK_3,
+ RETROK_4,
+ RETROK_5,
+ RETROK_6,
+ RETROK_7,
+ RETROK_8,
+ RETROK_9,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_a,
+ RETROK_b,
+ RETROK_c,
+ RETROK_d,
+ RETROK_e,
+ RETROK_f,
+ RETROK_g,
+ RETROK_h,
+ RETROK_i,
+ RETROK_j,
+ RETROK_k,
+ RETROK_l,
+ RETROK_m,
+ RETROK_n,
+ RETROK_o,
+ RETROK_p,
+ RETROK_q,
+ RETROK_r,
+ RETROK_s,
+ RETROK_t,
+ RETROK_u,
+ RETROK_v,
+ RETROK_w,
+ RETROK_x,
+ RETROK_y,
+ RETROK_z,
+ RETROK_LSUPER,
+ RETROK_RSUPER,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_KP0,
+ RETROK_KP1,
+ RETROK_KP2,
+ RETROK_KP3,
+ RETROK_KP4,
+ RETROK_KP5,
+ RETROK_KP6,
+ RETROK_KP7,
+ RETROK_KP8,
+ RETROK_KP9,
+ RETROK_KP_MULTIPLY,
+ RETROK_KP_PLUS,
+ RETROK_KP_PERIOD,
+ RETROK_KP_MINUS,
+ RETROK_KP_PERIOD,
+ RETROK_KP_DIVIDE,
+ RETROK_F1,
+ RETROK_F2,
+ RETROK_F3,
+ RETROK_F4,
+ RETROK_F5,
+ RETROK_F6,
+ RETROK_F7,
+ RETROK_F8,
+ RETROK_F9,
+ RETROK_F10,
+ RETROK_F11,
+ RETROK_F12,
+ RETROK_F13,
+ RETROK_F14,
+ RETROK_F15,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_NUMLOCK,
+ RETROK_SCROLLOCK,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_LSHIFT,
+ RETROK_RSHIFT,
+ RETROK_LCTRL,
+ RETROK_RCTRL,
+ RETROK_LALT,
+ RETROK_RALT,
+ RETROK_BROWSER_BACK,
+ RETROK_BROWSER_FORWARD,
+ RETROK_BROWSER_REFRESH,
+ RETROK_BROWSER_STOP,
+ RETROK_BROWSER_SEARCH,
+ RETROK_BROWSER_FAVORITES,
+ RETROK_BROWSER_HOME,
+ RETROK_VOLUME_MUTE,
+ RETROK_VOLUME_DOWN,
+ RETROK_VOLUME_UP,
+ RETROK_MEDIA_NEXT,
+ RETROK_MEDIA_PREV,
+ RETROK_MEDIA_STOP,
+ RETROK_MEDIA_PLAY_PAUSE,
+ RETROK_LAUNCH_MAIL,
+ RETROK_LAUNCH_MEDIA,
+ RETROK_LAUNCH_APP1,
+ RETROK_LAUNCH_APP2,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_SEMICOLON,
+ RETROK_PLUS,
+ RETROK_COMMA,
+ RETROK_MINUS,
+ RETROK_PERIOD,
+ RETROK_SLASH,
+ RETROK_BACKQUOTE,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_LEFTBRACKET,
+ RETROK_BACKSLASH,
+ RETROK_RIGHTBRACKET,
+ RETROK_QUOTE,
+ RETROK_EXCLAIM,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_OEM_102,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_COMPOSE,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+ RETROK_UNKNOWN,
+};
+
+#define NUM_VKEYS (sizeof vkeyToRetrok / sizeof *vkeyToRetrok)
+
+static const uint8_t controllerButtonToJoypadId[] = {
+ RETRO_DEVICE_ID_JOYPAD_A,
+ RETRO_DEVICE_ID_JOYPAD_B,
+ RETRO_DEVICE_ID_JOYPAD_X,
+ RETRO_DEVICE_ID_JOYPAD_Y,
+ REPEATING_NONE,
+ RETRO_DEVICE_ID_JOYPAD_SELECT,
+ RETRO_DEVICE_ID_JOYPAD_START,
+ RETRO_DEVICE_ID_JOYPAD_L3,
+ RETRO_DEVICE_ID_JOYPAD_R3,
+ RETRO_DEVICE_ID_JOYPAD_L,
+ RETRO_DEVICE_ID_JOYPAD_R,
+ RETRO_DEVICE_ID_JOYPAD_UP,
+ RETRO_DEVICE_ID_JOYPAD_DOWN,
+ RETRO_DEVICE_ID_JOYPAD_LEFT,
+ RETRO_DEVICE_ID_JOYPAD_RIGHT,
+ REPEATING_NONE,
+ REPEATING_NONE,
+ REPEATING_NONE,
+ REPEATING_NONE,
+ REPEATING_NONE,
+ REPEATING_NONE,
+};
+
+#define NUM_CONTROLLER_BUTTONS (sizeof controllerButtonToJoypadId / sizeof *controllerButtonToJoypadId)
+
struct InputPrivate
{
- uint32_t repeatCount;
- uint16_t currJoypadState;
- uint16_t prevJoypadState;
- uint8_t repeat;
- uint8_t currDir4;
- uint8_t prevDir4;
+ uint16_t joypadState;
+ uint16_t joypadStateOld;
+ uint8_t dir4;
+ uint8_t dir4Old;
uint8_t dir8;
+
+ bool keyboardStates[RETROK_LAST];
+ bool keyboardStatesOld[RETROK_LAST];
+
+ bool mouseStates[5];
+ bool mouseStatesOld[5];
int16_t mouseX;
int16_t mouseY;
uint32_t scrollV;
bool mouseInWindow;
- bool mouseLeft;
- bool mouseMiddle;
- bool mouseRight;
- bool mouseX1;
- bool mouseX2;
+
+ uint8_t rawKeyStates[NUM_SCANCODES];
+ uint8_t rawButtonStates[NUM_CONTROLLER_BUTTONS];
+
+ uint8_t repeating;
+ double repeatTime;
+ uint32_t repeatCount;
+
+ enum {
+ RAW_REPEATING_NONE,
+ RAW_REPEATING_KEYBOARD,
+ RAW_REPEATING_MOUSE,
+ } rawRepeatingType;
+ uint16_t rawRepeating;
+ uint32_t rawRepeatCount;
+ double rawRepeatTime;
+
+ double last_update;
+
bool joypadMaskSupported;
InputPrivate() :
- repeatCount(0),
- currJoypadState(0),
- prevJoypadState(0),
- repeat(-1),
- currDir4(0),
- prevDir4(0),
+ joypadState(0),
+ joypadStateOld(0),
+ dir4(0),
+ dir4Old(0),
dir8(0),
mouseX(0),
mouseY(0),
scrollV(0),
mouseInWindow(false),
- mouseLeft(false),
- mouseMiddle(false),
- mouseRight(false),
- mouseX1(false),
- mouseX2(false),
- joypadMaskSupported(mkxp_retro::environment(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
- {}
+ repeating(REPEATING_NONE),
+ repeatTime(0),
+ repeatCount(0),
+ rawRepeatingType(RAW_REPEATING_NONE),
+ rawRepeatCount(0),
+ rawRepeatTime(0),
+ last_update(0),
+ joypadMaskSupported(mkxp_retro::environment(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, nullptr))
+ {
+ std::memset(keyboardStates, 0, sizeof keyboardStates);
+ std::memset(keyboardStatesOld, 0, sizeof keyboardStates);
+ std::memset(mouseStates, 0, sizeof mouseStates);
+ std::memset(mouseStatesOld, 0, sizeof mouseStates);
+ std::memset(rawKeyStates, 0, sizeof rawKeyStates);
+ std::memset(rawButtonStates, 0, sizeof rawButtonStates);
+ }
void updateJoypad()
{
- prevJoypadState = currJoypadState;
+ joypadStateOld = joypadState;
if (joypadMaskSupported) {
- currJoypadState = (uint16_t)mkxp_retro::input_state(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
+ joypadState = (uint16_t)mkxp_retro::input_state(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
} else {
- currJoypadState = 0;
+ joypadState = 0;
for (uint8_t i = 0; i < JOYPAD_BUTTON_MAX; ++i) {
if (mkxp_retro::input_state(0, RETRO_DEVICE_JOYPAD, 0, i)) {
- currJoypadState |= (1 << i);
+ joypadState |= (1 << i);
}
}
}
-
- if (repeat == REPEAT_NONE) {
- if (currJoypadState != 0) {
- for (uint8_t i = 0; i < JOYPAD_BUTTON_MAX; ++i) {
- if (currJoypadState & (1 << i)) {
- repeat = i;
- repeatCount = 0;
- break;
- }
- }
- }
- } else if (currJoypadState & (1 << repeat)) {
- __builtin_add_overflow(repeatCount, 1, &repeatCount);
- } else {
- repeat = REPEAT_NONE;
- repeatCount = 0;
- }
}
void updateDir4()
{
/* Check for dead keys */
- if (((currJoypadState & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN)) && (currJoypadState & (1 << RETRO_DEVICE_ID_JOYPAD_UP))) || ((currJoypadState & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT)) && (currJoypadState & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))))
+ if (((joypadState & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN)) && (joypadState & (1 << RETRO_DEVICE_ID_JOYPAD_UP))) || ((joypadState & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT)) && (joypadState & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))))
{
- currDir4 = 0;
+ dir4 = 0;
return;
}
- if (prevDir4 != 0)
+ if (dir4Old != 0)
{
/* Check if prev still pressed */
- if (currJoypadState & (1 << prevDir4))
+ if (joypadState & (1 << dir4Old))
{
for (size_t i = 0; i < 3; ++i)
{
- uint8_t other = otherDirs[prevDir4 - RETRO_DEVICE_ID_JOYPAD_UP][i];
+ uint8_t other = otherDirs[dir4Old - RETRO_DEVICE_ID_JOYPAD_UP][i];
- if (!(currJoypadState & (1 << other)))
+ if (!(joypadState & (1 << other)))
continue;
- currDir4 = other;
+ dir4 = other;
return;
}
}
@@ -157,14 +748,14 @@ struct InputPrivate
for (size_t i = 0; i < 4; ++i)
{
- if (!(currJoypadState & (1 << (RETRO_DEVICE_ID_JOYPAD_UP + i))))
+ if (!(joypadState & (1 << (RETRO_DEVICE_ID_JOYPAD_UP + i))))
continue;
- currDir4 = prevDir4 = RETRO_DEVICE_ID_JOYPAD_UP + i;
+ dir4 = dir4Old = RETRO_DEVICE_ID_JOYPAD_UP + i;
return;
}
- currDir4 = prevDir4 = 0;
+ dir4 = dir4Old = 0;
}
void updateDir8()
@@ -181,14 +772,14 @@ struct InputPrivate
for (size_t i = 0; i < 4; ++i)
{
- if (!(currJoypadState & (1 << (RETRO_DEVICE_ID_JOYPAD_UP + i))))
+ if (!(joypadState & (1 << (RETRO_DEVICE_ID_JOYPAD_UP + i))))
continue;
for (int j = 0; j < 3; ++j)
{
uint8_t other = otherDirs[i][j];
- if (!(currJoypadState & (1 << other)))
+ if (!(joypadState & (1 << other)))
continue;
dir8 = combos[i][other - RETRO_DEVICE_ID_JOYPAD_UP];
@@ -200,36 +791,232 @@ struct InputPrivate
}
}
+ void updateKeyboard()
+ {
+ std::memcpy(keyboardStatesOld, keyboardStates, sizeof keyboardStates);
+ std::memcpy(keyboardStates, mkxp_retro::keyboard_state, sizeof keyboardStates);
+ }
+
void updateMouse()
{
+ std::memcpy(mouseStatesOld, mouseStates, sizeof mouseStates);
+
+ mouseStates[0] = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
+ mouseStates[1] = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT);
+ mouseStates[2] = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE);
+ mouseStates[3] = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_4);
+ mouseStates[4] = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_5);
+
mouseX = (int16_t)mkxp_retro::input_state(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
mouseY = (int16_t)mkxp_retro::input_state(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
mouseInWindow = !mkxp_retro::input_state(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_IS_OFFSCREEN);
scrollV += mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN);
scrollV -= mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_WHEELUP);
- mouseLeft = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
- mouseMiddle = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE);
- mouseRight = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT);
- mouseX1 = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_4);
- mouseX2 = mkxp_retro::input_state(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_BUTTON_5);
}
- bool getCurrJoypadState(int button)
+ void updateRawKeyStates()
{
- auto it = codeToJoypadId.find(button);
- return it != codeToJoypadId.end() && (currJoypadState & (1 << it->second));
+ for (uint16_t i = 0; i < NUM_SCANCODES; ++i)
+ {
+ rawKeyStates[i] = keyboardStates[scancodeToRetrok[i]];
+ }
}
- bool getPrevJoypadState(int button)
+ void updateRawButtonStates()
+ {
+ for (uint8_t i = 0; i < NUM_CONTROLLER_BUTTONS; ++i)
+ {
+ rawButtonStates[i] = controllerButtonToJoypadId[i] != REPEATING_NONE && joypadState & (1 << controllerButtonToJoypadId[i]);
+ }
+ }
+
+ void updateRepeat()
+ {
+ for (uint8_t i = 0; i < JOYPAD_BUTTON_MAX; ++i)
+ {
+ /* Check for new repeating joypad key */
+ if (joypadState & (1 << i) && !(joypadStateOld & (1 << i)) && i != repeating)
+ {
+ repeating = i;
+ repeatCount = 0;
+ repeatTime = shState->runTime();
+ return;
+ }
+ }
+
+ /* Check if repeating joypad key still pressed */
+ if (joypadState & (1 << repeating))
+ {
+ ++repeatCount;
+ return;
+ }
+
+ repeating = REPEATING_NONE;
+ }
+
+ void updateRawRepeat()
+ {
+ for (uint16_t i = 0; i < RETROK_LAST; ++i)
+ {
+ /* Check for new repeating keyboard key */
+ if (keyboardStates[i] && !keyboardStatesOld[i] && (rawRepeatingType != RAW_REPEATING_KEYBOARD || i != rawRepeating))
+ {
+ rawRepeatingType = RAW_REPEATING_KEYBOARD;
+ rawRepeating = i;
+ rawRepeatCount = 0;
+ rawRepeatTime = shState->runTime();
+ return;
+ }
+ }
+
+ for (uint8_t i = 0; i < 5; ++i)
+ {
+ /* Check for new repeating mouse button */
+ if (mouseStates[i] && !mouseStatesOld[i] && (rawRepeatingType != RAW_REPEATING_MOUSE || i != rawRepeating))
+ {
+ rawRepeatingType = RAW_REPEATING_MOUSE;
+ rawRepeating = i;
+ rawRepeatCount = 0;
+ rawRepeatTime = shState->runTime();
+ return;
+ }
+ }
+
+ /* Check if repeating keyboard key still pressed */
+ if (rawRepeatingType == RAW_REPEATING_KEYBOARD && keyboardStates[rawRepeating])
+ {
+ ++rawRepeatCount;
+ return;
+ }
+
+ /* Check if repeating mouse button still pressed */
+ if (rawRepeatingType == RAW_REPEATING_MOUSE && mouseStates[rawRepeating])
+ {
+ ++rawRepeatCount;
+ return;
+ }
+
+ rawRepeatingType = RAW_REPEATING_NONE;
+ }
+
+ bool getState(int button)
{
auto it = codeToJoypadId.find(button);
- return it != codeToJoypadId.end() && (prevJoypadState & (1 << it->second));
+ return it != codeToJoypadId.end() && (joypadState & (1 << it->second));
+ }
+
+ bool getStateOld(int button)
+ {
+ auto it = codeToJoypadId.find(button);
+ return it != codeToJoypadId.end() && (joypadStateOld & (1 << it->second));
}
bool isRepeat(int button)
{
auto it = codeToJoypadId.find(button);
- return it != codeToJoypadId.end() && repeat == it->second;
+ return it != codeToJoypadId.end() && repeating == it->second;
+ }
+
+ bool getRawState(int button, bool isVKey)
+ {
+ if (button < 0 || button >= (isVKey ? NUM_VKEYS : NUM_SCANCODES))
+ return false;
+ else if (!isVKey)
+ return keyboardStates[scancodeToRetrok[button]];
+ else if (button == 1)
+ return mouseStates[0];
+ else if (button == 2)
+ return mouseStates[1];
+ else if (button == 4)
+ return mouseStates[2];
+ else if (button == 5)
+ return mouseStates[3];
+ else if (button == 6)
+ return mouseStates[4];
+ else if (button == 16)
+ return keyboardStates[RETROK_LSHIFT] || keyboardStates[RETROK_RSHIFT];
+ else if (button == 17)
+ return keyboardStates[RETROK_LCTRL] || keyboardStates[RETROK_RCTRL];
+ else if (button == 18)
+ return keyboardStates[RETROK_LALT] || keyboardStates[RETROK_RALT];
+ else
+ return keyboardStates[vkeyToRetrok[button]];
+ }
+
+ bool getRawStateOld(int button, bool isVKey)
+ {
+ if (button < 0 || button >= (isVKey ? NUM_VKEYS : NUM_SCANCODES))
+ return false;
+ else if (!isVKey)
+ return keyboardStatesOld[scancodeToRetrok[button]];
+ else if (button == 1)
+ return mouseStatesOld[0];
+ else if (button == 2)
+ return mouseStatesOld[1];
+ else if (button == 4)
+ return mouseStatesOld[2];
+ else if (button == 5)
+ return mouseStatesOld[3];
+ else if (button == 6)
+ return mouseStatesOld[4];
+ else if (button == 16)
+ return keyboardStatesOld[RETROK_LSHIFT] || keyboardStatesOld[RETROK_RSHIFT];
+ else if (button == 17)
+ return keyboardStatesOld[RETROK_LCTRL] || keyboardStatesOld[RETROK_RCTRL];
+ else if (button == 18)
+ return keyboardStatesOld[RETROK_LALT] || keyboardStatesOld[RETROK_RALT];
+ else
+ return keyboardStatesOld[vkeyToRetrok[button]];
+ }
+
+ bool isRawRepeat(int button, bool isVKey)
+ {
+ if (rawRepeatingType == RAW_REPEATING_NONE || button < 0 || button >= (isVKey ? NUM_VKEYS : NUM_SCANCODES))
+ return false;
+ else if (!isVKey)
+ return rawRepeatingType == RAW_REPEATING_KEYBOARD && rawRepeating == scancodeToRetrok[button];
+ else if (button == 1)
+ return rawRepeatingType == RAW_REPEATING_MOUSE && rawRepeating == 0;
+ else if (button == 2)
+ return rawRepeatingType == RAW_REPEATING_MOUSE && rawRepeating == 1;
+ else if (button == 4)
+ return rawRepeatingType == RAW_REPEATING_MOUSE && rawRepeating == 2;
+ else if (button == 5)
+ return rawRepeatingType == RAW_REPEATING_MOUSE && rawRepeating == 3;
+ else if (button == 6)
+ return rawRepeatingType == RAW_REPEATING_MOUSE && rawRepeating == 4;
+ else if (button == 16)
+ return rawRepeatingType == RAW_REPEATING_KEYBOARD && (rawRepeating == RETROK_LSHIFT || rawRepeating == RETROK_RSHIFT);
+ else if (button == 17)
+ return rawRepeatingType == RAW_REPEATING_KEYBOARD && (rawRepeating == RETROK_LCTRL || rawRepeating == RETROK_RCTRL);
+ else if (button == 18)
+ return rawRepeatingType == RAW_REPEATING_KEYBOARD && (rawRepeating == RETROK_LALT || rawRepeating == RETROK_RALT);
+ else
+ return rawRepeatingType == RAW_REPEATING_KEYBOARD && rawRepeating == vkeyToRetrok[button];
+ }
+
+ bool getControllerState(int button)
+ {
+ if (button < 0 || button >= NUM_CONTROLLER_BUTTONS || controllerButtonToJoypadId[button] == REPEATING_NONE)
+ return false;
+ else
+ return joypadState & (1 << controllerButtonToJoypadId[button]);
+ }
+
+ bool getControllerStateOld(int button)
+ {
+ if (button < 0 || button >= NUM_CONTROLLER_BUTTONS || controllerButtonToJoypadId[button] == REPEATING_NONE)
+ return false;
+ else
+ return joypadStateOld & (1 << controllerButtonToJoypadId[button]);
+ }
+
+ bool isControllerRepeat(int button)
+ {
+ if (button < 0 || button >= NUM_CONTROLLER_BUTTONS || controllerButtonToJoypadId[button] == REPEATING_NONE)
+ return false;
+ else
+ return repeating == controllerButtonToJoypadId[button];
}
};
@@ -238,14 +1025,19 @@ Input::Input()
p = new InputPrivate();
}
+Input::~Input()
+{
+ delete p;
+}
+
void Input::recalcRepeat(unsigned int fps)
{
- // TODO
+
}
double Input::getDelta()
{
- return 0.0; // TODO
+ return shState->runTime() - p->last_update;
}
void Input::update()
@@ -255,22 +1047,28 @@ void Input::update()
p->updateJoypad();
p->updateDir4();
p->updateDir8();
+ p->updateKeyboard();
p->updateMouse();
+ p->updateRawKeyStates();
+ p->updateRawButtonStates();
+ p->updateRepeat();
+ p->updateRawRepeat();
+ p->last_update = shState->runTime();
}
bool Input::isPressed(int button)
{
- return p->getCurrJoypadState(button);
+ return p->getState(button);
}
bool Input::isTriggered(int button)
{
- return p->getCurrJoypadState(button) && !p->getPrevJoypadState(button);
+ return p->getState(button) && !p->getStateOld(button);
}
bool Input::isReleased(int button)
{
- return p->getPrevJoypadState(button) && !p->getCurrJoypadState(button);
+ return p->getStateOld(button) && !p->getState(button);
}
bool Input::isRepeated(int button)
@@ -286,87 +1084,89 @@ unsigned int Input::count(int button)
double Input::repeatTime(int button)
{
- return p->isRepeat(button) ? (double)p->repeatCount / shState->graphics().getFrameRate() : 0;
+ return p->isRepeat(button) ? shState->runTime() - p->repeatTime : 0;
}
bool Input::isPressedEx(int button, bool isVKey)
{
- return false; // TODO
+ return p->getRawState(button, isVKey);
}
bool Input::isTriggeredEx(int button, bool isVKey)
{
- return false; // TODO
+ return p->getRawState(button, isVKey) && !p->getRawStateOld(button, isVKey);
}
bool Input::isReleasedEx(int button, bool isVKey)
{
- return false; // TODO
+ return p->getRawStateOld(button, isVKey) && !p->getRawState(button, isVKey);
}
bool Input::isRepeatedEx(int button, bool isVKey)
{
- return false; // TODO
+ int frame_rate = shState->graphics().getFrameRate();
+ return p->isRawRepeat(button, isVKey) && (p->rawRepeatCount == 0 || (p->rawRepeatCount >= (size_t)std::ceil(REPEAT_START * frame_rate) && (p->rawRepeatCount + 1) % (size_t)std::ceil(REPEAT_DELAY * frame_rate) == 0));
}
unsigned int Input::repeatcount(int button, bool isVKey)
{
- return 0; // TODO
+ return p->isRawRepeat(button, isVKey) ? p->rawRepeatCount : 0;
}
double Input::repeatTimeEx(int button, bool isVKey)
{
- return 0.0; // TODO
+ return p->isRawRepeat(button, isVKey) ? shState->runTime() - p->rawRepeatTime : 0;
}
bool Input::controllerIsPressedEx(int button)
{
- return false; // TODO
+ return p->getControllerState(button);
}
bool Input::controllerIsTriggeredEx(int button)
{
- return false; // TODO
+ return p->getControllerState(button) && !p->getControllerStateOld(button);
}
bool Input::controllerIsReleasedEx(int button)
{
- return false; // TODO
-}
-
-unsigned int Input::controllerRepeatcount(int button)
-{
- return 0; // TODO
+ return p->getControllerStateOld(button) && !p->getControllerState(button);
}
bool Input::controllerIsRepeatedEx(int button)
{
- return false; // TODO
+ int frame_rate = shState->graphics().getFrameRate();
+ return p->isControllerRepeat(button) && (p->repeatCount == 0 || (p->repeatCount >= (size_t)std::ceil(REPEAT_START * frame_rate) && (p->repeatCount + 1) % (size_t)std::ceil(REPEAT_DELAY * frame_rate) == 0));
+}
+
+unsigned int Input::controllerRepeatcount(int button)
+{
+ return p->isControllerRepeat(button) ? p->repeatCount : 0;
}
double Input::controllerRepeatTimeEx(int button)
{
- return 0.0; // TODO
+ return p->isControllerRepeat(button) ? shState->runTime() - p->repeatTime : 0;
}
uint8_t *Input::rawKeyStates()
{
- return nullptr; // TODO
+ return p->rawKeyStates;
}
unsigned int Input::rawKeyStatesLength()
{
- return 0; // TODO
+ return NUM_SCANCODES;
}
uint8_t *Input::rawButtonStates()
{
- return nullptr; // TODO
+ return p->rawButtonStates;
}
unsigned int Input::rawButtonStatesLength()
{
- return 0; // TODO
+ return NUM_CONTROLLER_BUTTONS;
}
int16_t *Input::rawAxes()
@@ -386,7 +1186,7 @@ short Input::getControllerAxisValue(SDL_GameControllerAxis axis)
int Input::dir4Value()
{
- switch (p->currDir4) {
+ switch (p->dir4) {
case RETRO_DEVICE_ID_JOYPAD_DOWN:
return Input::Down;
case RETRO_DEVICE_ID_JOYPAD_LEFT:
@@ -473,8 +1273,3 @@ void Input::setClipboardText(const char *text)
{
}
-
-Input::~Input()
-{
- delete p;
-}