Stub out the rest of the input bindings in libretro builds

This commit is contained in:
刘皓 2025-05-01 22:49:18 -04:00
parent df559241a2
commit c9e7c4d02d
No known key found for this signature in database
GPG key ID: 7901753DB465B711
6 changed files with 460 additions and 16 deletions

View file

@ -25,6 +25,7 @@
using namespace mkxp_sandbox;
VALUE mkxp_sandbox::input_module;
VALUE mkxp_sandbox::input_controller_module;
static VALUE symhash;
@ -335,9 +336,296 @@ static VALUE mouse_in_window(VALUE self) {
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->mouseInWindow());
}
static VALUE raw_key_states(VALUE self) {
struct coro : boost::asio::coroutine {
VALUE ary;
uint32_t i;
uint32_t len;
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
len = mkxp_retro::input->rawKeyStatesLength();
SANDBOX_AWAIT_AND_SET(ary, rb_ary_new_capa, len);
for (i = 0; i < len; ++i) {
SANDBOX_AWAIT(rb_ary_push, ary, SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->rawKeyStates()[i]));
}
}
return ary;
}
};
return sb()->bind<struct coro>()()(self);
}
static VALUE controller_connected(VALUE self) {
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->getControllerConnected());
}
static VALUE controller_name(VALUE self) {
return sb()->bind<struct rb_str_new_cstr>()()(mkxp_retro::input->getControllerName());
}
#define POWERCASE(power) \
if (level == (int32_t)SDL_JOYSTICK_POWER_##power) { \
SANDBOX_AWAIT_AND_SET(id, rb_intern, #power); \
SANDBOX_AWAIT_AND_SET(value, rb_id2sym, id); \
return value; \
}
static VALUE controller_power_level(VALUE self) {
struct coro : boost::asio::coroutine {
VALUE value;
ID id;
int32_t level;
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
level = mkxp_retro::input->getControllerPowerLevel();
POWERCASE(UNKNOWN);
POWERCASE(EMPTY);
POWERCASE(LOW);
POWERCASE(MEDIUM);
POWERCASE(FULL);
POWERCASE(WIRED);
value = SANDBOX_NIL;
}
return value;
}
};
return sb()->bind<struct coro>()()(self);
}
#define DEF_AXES(enum1, enum2, name) \
static VALUE controller_axes_##name(VALUE self) { \
struct coro : boost::asio::coroutine { \
VALUE ary; \
VALUE value; \
VALUE operator()(VALUE self) { \
BOOST_ASIO_CORO_REENTER (this) { \
SANDBOX_AWAIT_AND_SET(ary, rb_ary_new_capa, 2); \
SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, mkxp_retro::input->getControllerAxisValue(SDL_CONTROLLER_AXIS_##enum1)); \
SANDBOX_AWAIT(rb_ary_push, ary, value); \
SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, mkxp_retro::input->getControllerAxisValue(SDL_CONTROLLER_AXIS_##enum2)); \
SANDBOX_AWAIT(rb_ary_push, ary, value); \
} \
return ary; \
} \
}; \
return sb()->bind<struct coro>()()(self); \
}
DEF_AXES(LEFTX, LEFTY, left);
DEF_AXES(RIGHTX, RIGHTY, right);
DEF_AXES(TRIGGERLEFT, TRIGGERRIGHT, trigger);
static VALUE controller_raw_button_states(VALUE self) {
struct coro : boost::asio::coroutine {
VALUE ary;
uint32_t i;
uint32_t len;
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
len = mkxp_retro::input->rawButtonStatesLength();
SANDBOX_AWAIT_AND_SET(ary, rb_ary_new_capa, len);
for (i = 0; i < len; ++i) {
SANDBOX_AWAIT(rb_ary_push, ary, SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->rawButtonStates()[i]));
}
}
return ary;
}
};
return sb()->bind<struct coro>()()(self);
}
static VALUE controller_raw_axes(VALUE self) {
struct coro : boost::asio::coroutine {
VALUE ary;
VALUE value;
uint32_t i;
uint32_t len;
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
len = mkxp_retro::input->rawAxesLength();
SANDBOX_AWAIT_AND_SET(ary, rb_ary_new_capa, len);
for (i = 0; i < len; ++i) {
SANDBOX_AWAIT_AND_SET(value, rb_float_new, mkxp_retro::input->rawAxes()[i] / 32767.0);
SANDBOX_AWAIT(rb_ary_push, ary, value);
}
}
return ary;
}
};
return sb()->bind<struct coro>()()(self);
}
static VALUE controller_pressex(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->controllerIsPressedEx(button));
}
return SANDBOX_UNDEF;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE controller_triggerex(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->controllerIsTriggeredEx(button));
}
return SANDBOX_UNDEF;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE controller_repeatex(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->controllerIsRepeatedEx(button));
}
return SANDBOX_UNDEF;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE controller_releaseex(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->controllerIsReleasedEx(button));
}
return SANDBOX_UNDEF;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE controller_repeatcount(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
int32_t count;
VALUE value;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
count = mkxp_retro::input->controllerRepeatcount(button);
SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, count);
}
return value;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE controller_timeex(VALUE self, VALUE code) {
struct coro : boost::asio::coroutine {
int32_t button;
double time;
VALUE value;
VALUE operator()(VALUE self, VALUE code) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(button, get_button_arg, code);
time = mkxp_retro::input->controllerRepeatTimeEx(button);
SANDBOX_AWAIT_AND_SET(value, rb_float_new, time);
}
return value;
}
};
return sb()->bind<struct coro>()()(self, code);
}
static VALUE get_text_input(VALUE self) {
return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->getTextInputMode());
}
static VALUE set_text_input(VALUE self, VALUE value) {
mkxp_retro::input->setTextInputMode(value);
return value;
}
static VALUE gets_(VALUE self) {
struct coro : boost::asio::coroutine {
VALUE value;
VALUE operator()(VALUE self) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(value, rb_str_new_cstr, mkxp_retro::input->getText());
mkxp_retro::input->clearText();
}
return value;
}
};
return sb()->bind<struct coro>()()(self);
}
static VALUE get_clipboard(VALUE self) {
return sb()->bind<struct rb_str_new_cstr>()()(mkxp_retro::input->getClipboardText());
}
static VALUE set_clipboard(VALUE self, VALUE value) {
struct coro : boost::asio::coroutine {
wasm_ptr_t ptr;
VALUE operator()(VALUE self, VALUE value) {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(ptr, rb_string_value_cstr, &value);
mkxp_retro::input->setClipboardText((const char *)(**sb() + ptr));
}
return value;
}
};
return sb()->bind<struct coro>()()(self, value);
}
void input_binding_init::operator()() {
BOOST_ASIO_CORO_REENTER (this) {
SANDBOX_AWAIT_AND_SET(input_module, rb_define_module, "Input");
SANDBOX_AWAIT(rb_define_module_function, input_module, "delta", (VALUE (*)(ANYARGS))delta, 0);
SANDBOX_AWAIT(rb_define_module_function, input_module, "update", (VALUE (*)(ANYARGS))update, 0);
SANDBOX_AWAIT(rb_define_module_function, input_module, "press?", (VALUE (*)(ANYARGS))press, 1);
@ -361,6 +649,29 @@ void input_binding_init::operator()() {
SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_in_window", (VALUE (*)(ANYARGS))mouse_in_window, 0);
SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_in_window?", (VALUE (*)(ANYARGS))mouse_in_window, 0);
SANDBOX_AWAIT(rb_define_module_function, input_module, "raw_key_states", (VALUE (*)(ANYARGS))raw_key_states, 0);
SANDBOX_AWAIT_AND_SET(input_controller_module, rb_define_module_under, input_module, "Controller");
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "connected?", (VALUE (*)(ANYARGS))controller_connected, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "name", (VALUE (*)(ANYARGS))controller_name, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "power_level", (VALUE (*)(ANYARGS))controller_power_level, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "axes_left", (VALUE (*)(ANYARGS))controller_axes_left, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "axes_right", (VALUE (*)(ANYARGS))controller_axes_right, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "axes_trigger", (VALUE (*)(ANYARGS))controller_axes_trigger, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "raw_button_states", (VALUE (*)(ANYARGS))controller_raw_button_states, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "raw_axes", (VALUE (*)(ANYARGS))controller_raw_axes, 0);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "pressex?", (VALUE (*)(ANYARGS))controller_pressex, 1);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "triggerex?", (VALUE (*)(ANYARGS))controller_triggerex, 1);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "repeatex?", (VALUE (*)(ANYARGS))controller_repeatex, 1);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "releaseex?", (VALUE (*)(ANYARGS))controller_releaseex, 1);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "repeatcount", (VALUE (*)(ANYARGS))controller_repeatcount, 1);
SANDBOX_AWAIT(rb_define_module_function, input_controller_module, "timeex?", (VALUE (*)(ANYARGS))controller_timeex, 1);
SANDBOX_INIT_MODULE_PROP_BIND(input_module, text_input);
SANDBOX_AWAIT(rb_define_module_function, input_module, "gets", (VALUE (*)(ANYARGS))gets_, 0);
SANDBOX_INIT_MODULE_PROP_BIND(input_module, clipboard);
if (rgssVer >= 3) {
SANDBOX_AWAIT_AND_SET(symhash, rb_hash_new);

View file

@ -26,6 +26,7 @@
namespace mkxp_sandbox {
extern VALUE input_module;
extern VALUE input_controller_module;
struct input_binding_init : boost::asio::coroutine {
void operator()();

View file

@ -1245,14 +1245,17 @@ bool Graphics::update(bool checkForShutdown) {
p->threadData->rqWindowAdjust.wait();
p->last_update = shState->runTime();
#ifndef MKXPZ_RETRO
// update Input.repeat timing, rounding the framerate to the nearest 2
{
static const double mult = 2.0;
double afr = std::abs(averageFrameRate()); // abs shouldn't be necessary but that's ok
afr += mult / 2;
afr -= std::fmod(afr, mult);
#ifdef MKXPZ_RETRO // TODO: merge into shState
mkxp_retro::input->recalcRepeat(std::floor(afr));
#else
shState->input().recalcRepeat(std::floor(afr));
#endif // MKXPZ_RETRO
}
if (checkForShutdown)
@ -1261,11 +1264,10 @@ bool Graphics::update(bool checkForShutdown) {
p->checkSyncLock();
# ifdef MKXPZ_STEAM
#ifdef MKXPZ_STEAM
if (STEAMSHIM_alive())
STEAMSHIM_pump();
# endif // MKXPZ_STEAM
#endif // MKXPZ_RETRO
#endif // MKXPZ_STEAM
if (p->frozen)
return false;

View file

@ -238,6 +238,11 @@ Input::Input()
p = new InputPrivate();
}
void Input::recalcRepeat(unsigned int fps)
{
// TODO
}
double Input::getDelta()
{
return 0.0; // TODO
@ -329,6 +334,11 @@ bool Input::controllerIsReleasedEx(int button)
return false; // TODO
}
unsigned int Input::controllerRepeatcount(int button)
{
return 0; // TODO
}
bool Input::controllerIsRepeatedEx(int button)
{
return false; // TODO
@ -339,6 +349,41 @@ double Input::controllerRepeatTimeEx(int button)
return 0.0; // TODO
}
uint8_t *Input::rawKeyStates()
{
return nullptr; // TODO
}
unsigned int Input::rawKeyStatesLength()
{
return 0; // TODO
}
uint8_t *Input::rawButtonStates()
{
return nullptr; // TODO
}
unsigned int Input::rawButtonStatesLength()
{
return 0; // TODO
}
int16_t *Input::rawAxes()
{
return nullptr; // TODO
}
unsigned int Input::rawAxesLength()
{
return 0; // TODO
}
short Input::getControllerAxisValue(SDL_GameControllerAxis axis)
{
return 0; // TODO
}
int Input::dir4Value()
{
switch (p->currDir4) {
@ -384,6 +429,51 @@ bool Input::mouseInWindow()
return p->mouseInWindow;
}
bool Input::getControllerConnected()
{
return true;
}
const char *Input::getControllerName()
{
return "RetroPad";
}
int Input::getControllerPowerLevel()
{
return (int)SDL_JOYSTICK_POWER_UNKNOWN;
}
bool Input::getTextInputMode()
{
return false;
}
void Input::setTextInputMode(bool mode)
{
}
const char *Input::getText()
{
return "";
}
void Input::clearText()
{
}
const char *Input::getClipboardText()
{
return "";
}
void Input::setClipboardText(const char *text)
{
}
Input::~Input()
{
delete p;

View file

@ -1491,15 +1491,16 @@ void Input::clearText()
shState->eThread().textInputBuffer.clear();
}
char *Input::getClipboardText()
const char *Input::getClipboardText()
{
char *tx = SDL_GetClipboardText();
// FIXME: this doesn't appear to be freed anywhere
const char *tx = SDL_GetClipboardText();
if (!tx)
throw Exception(Exception::SDLError, "Failed to get clipboard text: %s", SDL_GetError());
return tx;
}
void Input::setClipboardText(char *text)
void Input::setClipboardText(const char *text)
{
if (SDL_SetClipboardText(text) < 0)
throw Exception(Exception::SDLError, "Failed to set clipboard text: %s", SDL_GetError());

View file

@ -27,7 +27,52 @@
#include <string>
#include <vector>
#ifndef MKXPZ_RETRO
#ifdef MKXPZ_RETRO
enum SDL_GameControllerAxis
{
SDL_CONTROLLER_AXIS_LEFTX = 0,
SDL_CONTROLLER_AXIS_LEFTY = 1,
SDL_CONTROLLER_AXIS_RIGHTX = 2,
SDL_CONTROLLER_AXIS_RIGHTY = 3,
SDL_CONTROLLER_AXIS_TRIGGERLEFT = 4,
SDL_CONTROLLER_AXIS_TRIGGERRIGHT = 5,
};
enum SDL_GameControllerButton
{
SDL_CONTROLLER_BUTTON_A = 0,
SDL_CONTROLLER_BUTTON_B = 1,
SDL_CONTROLLER_BUTTON_X = 2,
SDL_CONTROLLER_BUTTON_Y = 3,
SDL_CONTROLLER_BUTTON_BACK = 4,
SDL_CONTROLLER_BUTTON_GUIDE = 5,
SDL_CONTROLLER_BUTTON_START = 6,
SDL_CONTROLLER_BUTTON_LEFTSTICK = 7,
SDL_CONTROLLER_BUTTON_RIGHTSTICK = 8,
SDL_CONTROLLER_BUTTON_LEFTSHOULDER = 9,
SDL_CONTROLLER_BUTTON_RIGHTSHOULDER = 10,
SDL_CONTROLLER_BUTTON_DPAD_UP = 11,
SDL_CONTROLLER_BUTTON_DPAD_DOWN = 12,
SDL_CONTROLLER_BUTTON_DPAD_LEFT = 13,
SDL_CONTROLLER_BUTTON_DPAD_RIGHT = 14,
SDL_CONTROLLER_BUTTON_MISC1 = 15,
SDL_CONTROLLER_BUTTON_PADDLE1 = 16,
SDL_CONTROLLER_BUTTON_PADDLE2 = 17,
SDL_CONTROLLER_BUTTON_PADDLE3 = 18,
SDL_CONTROLLER_BUTTON_PADDLE4 = 19,
SDL_CONTROLLER_BUTTON_TOUCHPAD = 20,
};
enum SDL_JoystickPowerLevel
{
SDL_JOYSTICK_POWER_UNKNOWN = 0,
SDL_JOYSTICK_POWER_EMPTY = 1,
SDL_JOYSTICK_POWER_LOW = 2,
SDL_JOYSTICK_POWER_MEDIUM = 3,
SDL_JOYSTICK_POWER_FULL = 4,
SDL_JOYSTICK_POWER_WIRED = 5,
};
#else
#include <SDL_gamecontroller.h>
extern std::unordered_map<int, int> vKeyToScancode;
extern std::unordered_map<std::string, int> strToScancode;
@ -59,9 +104,7 @@ public:
MouseX1 = 41, MouseX2 = 42
};
#ifndef MKXPZ_RETRO
void recalcRepeat(unsigned int fps);
#endif // MKXPZ_RETRO
double getDelta();
void update();
@ -87,7 +130,6 @@ public:
unsigned int controllerRepeatcount(int button);
double controllerRepeatTimeEx(int button);
#ifndef MKXPZ_RETRO
uint8_t *rawKeyStates();
unsigned int rawKeyStatesLength();
uint8_t *rawButtonStates();
@ -96,7 +138,6 @@ public:
unsigned int rawAxesLength();
short getControllerAxisValue(SDL_GameControllerAxis axis);
#endif // MKXPZ_RETRO
int dir4Value();
int dir8Value();
@ -106,7 +147,6 @@ public:
int scrollV();
bool mouseInWindow();
#ifndef MKXPZ_RETRO
bool getControllerConnected();
const char *getControllerName();
int getControllerPowerLevel();
@ -116,12 +156,11 @@ public:
const char *getText();
void clearText();
char *getClipboardText();
void setClipboardText(char *text);
const char *getClipboardText();
void setClipboardText(const char *text);
const char *getAxisName(SDL_GameControllerAxis axis);
const char *getButtonName(SDL_GameControllerButton button);
#endif // MKXPZ_RETRO
#ifdef MKXPZ_RETRO
Input();