diff --git a/src/Application.cpp b/src/Application.cpp index f7ace7e..34c6689 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -371,8 +371,8 @@ void Application::processEvents() void Application::runSmoothed() { - const int TARGET_FRAMES = (int)round(_core.getSystemAVInfo()->timing.fps); - const int SMOOTHING_FRAMES = 32; + const unsigned int TARGET_FRAMES = (int)round(_core.getSystemAVInfo()->timing.fps); + const unsigned int SMOOTHING_FRAMES = 32; uint32_t frameMicroseconds[SMOOTHING_FRAMES]; uint32_t totalMicroseconds; int frameIndex = 0; @@ -393,7 +393,7 @@ void Application::runSmoothed() const auto tFirstFrameEnd = std::chrono::steady_clock::now(); const auto tFirstFrameElapsed = std::chrono::duration_cast(tFirstFrameEnd - tFirstFrameStart); - for (int i = 0; i < SMOOTHING_FRAMES; ++i) + for (unsigned int i = 0; i < SMOOTHING_FRAMES; ++i) frameMicroseconds[i] = (uint32_t)tFirstFrameElapsed.count(); totalMicroseconds = frameMicroseconds[0] * SMOOTHING_FRAMES; @@ -685,6 +685,8 @@ bool Application::loadCore(const std::string& coreName) }); free(data); + + _config.initializeInput(_input); } _coreName = coreName; @@ -2125,7 +2127,7 @@ void Application::handle(const SDL_SysWMEvent* syswm) break; case IDM_CORE_CONFIG: - _config.showDialog(_core.getSystemInfo()->library_name); + _config.showDialog(_core.getSystemInfo()->library_name, _input); break; case IDM_INPUT_CONFIG: @@ -2236,6 +2238,12 @@ void Application::handle(const KeyBinds::Action action, unsigned extra) case KeyBinds::Action::kButtonSelect: _input.buttonEvent(extra >> 8, Input::Button::kSelect, (extra & 0xFF) != 0); break; case KeyBinds::Action::kButtonStart: _input.buttonEvent(extra >> 8, Input::Button::kStart, (extra & 0xFF) != 0); break; + // Joypad analog sticks + case KeyBinds::Action::kAxisLeftX: _input.axisEvent(extra >> 16, Input::Axis::kLeftAxisX, (int16_t)(extra & 0xFFFF)); break; + case KeyBinds::Action::kAxisLeftY: _input.axisEvent(extra >> 16, Input::Axis::kLeftAxisY, (int16_t)(extra & 0xFFFF)); break; + case KeyBinds::Action::kAxisRightX: _input.axisEvent(extra >> 16, Input::Axis::kRightAxisX, (int16_t)(extra & 0xFFFF)); break; + case KeyBinds::Action::kAxisRightY: _input.axisEvent(extra >> 16, Input::Axis::kRightAxisY, (int16_t)(extra & 0xFFFF)); break; + // State management case KeyBinds::Action::kSaveState: saveState(extra); break; case KeyBinds::Action::kLoadState: loadState(extra); break; diff --git a/src/Application.h b/src/Application.h index 2d13302..6eb8a97 100644 --- a/src/Application.h +++ b/src/Application.h @@ -54,7 +54,6 @@ class Application void unloadCore(); void resetGame(); bool hardcore(); - void setTurbo(bool turbo); bool unloadGame(); void pauseGame(bool pause); diff --git a/src/Emulator.cpp b/src/Emulator.cpp index 1639a1c..c0f0a7e 100644 --- a/src/Emulator.cpp +++ b/src/Emulator.cpp @@ -170,6 +170,9 @@ bool loadCores(Config* config, Logger* logger) ud->core->systems.insert(static_cast(std::stoi(system))); } break; + + default: + break; } return 0; @@ -290,30 +293,6 @@ const char* getSystemName(System system) return "?"; } -static bool romLoadedWithPadding(void* rom, size_t size, size_t max_size, int fill) -{ - uint8_t* data = (uint8_t*)malloc(max_size); - - if (data != NULL) - { - if (size < max_size) - { - memcpy(data, rom, size); - memset(data + size, fill, max_size - size); - } - else - { - memcpy(data, rom, max_size); - } - - RA_OnLoadNewRom(data, max_size); - free(data); - return true; - } - - return false; -} - static bool romLoadSnes(void* rom, size_t size) { // if the file contains a header, ignore it @@ -542,7 +521,7 @@ class CoreDialog : public Dialog continue; if (core.systems.find(system) != core.systems.end()) - systemCores.insert_or_assign(core.name, &core); + systemCores.emplace(core.name, &core); } char buffer[64]; @@ -819,7 +798,7 @@ bool showCoresDialog(Config* config, Logger* logger) for (auto system : core.systems) { - allSystems.insert_or_assign(getSystemName(system), system); + allSystems.emplace(getSystemName(system), system); if (++systemCoreCounts[(int)system] > maxSystemCoreCount) maxSystemCoreCount = systemCoreCounts[(int)system]; } diff --git a/src/KeyBinds.cpp b/src/KeyBinds.cpp index cc8da69..c2f9a43 100644 --- a/src/KeyBinds.cpp +++ b/src/KeyBinds.cpp @@ -50,6 +50,10 @@ enum kJoy0R3, kJoy0Select, kJoy0Start, + kJoy0LeftAnalogX, + kJoy0LeftAnalogY, + kJoy0RightAnalogX, + kJoy0RightAnalogY, kJoy1Up, kJoy1Down, @@ -67,6 +71,10 @@ enum kJoy1R3, kJoy1Select, kJoy1Start, + kJoy1LeftAnalogX, + kJoy1LeftAnalogY, + kJoy1RightAnalogX, + kJoy1RightAnalogY, // State management kSaveState1, @@ -127,9 +135,11 @@ enum static const char* bindingNames[] = { "J0_UP", "J0_DOWN", "J0_LEFT", "J0_RIGHT", "J0_X", "J0_Y", "J0_A", "J0_B", "J0_L", "J0_R", "J0_L2", "J0_R2", "J0_L3", "J0_R3", "J0_SELECT", "J0_START", + "J0_LSTICK_X", "J0_LSTICK_Y", "J0_RSTICK_X", "J0_RSTICK_Y", "J1_UP", "J1_DOWN", "J1_LEFT", "J1_RIGHT", "J1_X", "J1_Y", "J1_A", "J1_B", "J1_L", "J1_R", "J1_L2", "J1_R2", "J1_L3", "J1_R3", "J1_SELECT", "J1_START", + "J1_LSTICK_X", "J1_LSTICK_Y", "J1_RSTICK_X", "J1_RSTICK_Y", "SAVE1", "SAVE2", "SAVE3", "SAVE4", "SAVE5", "SAVE6", "SAVE7", "SAVE8", "SAVE9", "SAVE0", "LOAD1", "LOAD2", "LOAD3", "LOAD4", "LOAD5", "LOAD6", "LOAD7", "LOAD8", "LOAD9", "LOAD0", @@ -170,6 +180,10 @@ bool KeyBinds::init(libretro::LoggerComponent* logger) _bindings[kJoy0R2] = { 0, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, Binding::Type::Axis, 0 }; _bindings[kJoy0L3] = { 0, SDL_CONTROLLER_BUTTON_LEFTSTICK, Binding::Type::Button, 0 }; _bindings[kJoy0R3] = { 0, SDL_CONTROLLER_BUTTON_RIGHTSTICK, Binding::Type::Button, 0 }; + _bindings[kJoy0LeftAnalogX] = { 0, SDL_CONTROLLER_AXIS_LEFTX, Binding::Type::Axis, 0 }; + _bindings[kJoy0LeftAnalogY] = { 0, SDL_CONTROLLER_AXIS_LEFTY, Binding::Type::Axis, 0 }; + _bindings[kJoy0RightAnalogX] = { 0, SDL_CONTROLLER_AXIS_RIGHTX, Binding::Type::Axis, 0 }; + _bindings[kJoy0RightAnalogY] = { 0, SDL_CONTROLLER_AXIS_RIGHTY, Binding::Type::Axis, 0 }; _bindings[kJoy0Select] = { 0, SDL_CONTROLLER_BUTTON_BACK, Binding::Type::Button, 0 }; _bindings[kJoy0Start] = { 0, SDL_CONTROLLER_BUTTON_START, Binding::Type::Button, 0 }; } @@ -391,6 +405,34 @@ KeyBinds::Action KeyBinds::translateButtonReleased(int button, unsigned* extra) } } +KeyBinds::Action KeyBinds::translateAnalog(int button, Sint16 value, unsigned* extra) +{ + KeyBinds::Action action; + unsigned controller; + + switch (button) + { + case kJoy0LeftAnalogX: action = Action::kAxisLeftX; controller = 0; break; + case kJoy0LeftAnalogY: action = Action::kAxisLeftY; controller = 0; break; + case kJoy0RightAnalogX: action = Action::kAxisRightX; controller = 0; break; + case kJoy0RightAnalogY: action = Action::kAxisRightY; controller = 0; break; + case kJoy1LeftAnalogX: action = Action::kAxisLeftX; controller = 1; break; + case kJoy1LeftAnalogY: action = Action::kAxisLeftY; controller = 1; break; + case kJoy1RightAnalogX: action = Action::kAxisRightX; controller = 1; break; + case kJoy1RightAnalogY: action = Action::kAxisRightY; controller = 1; break; + + default: + return Action::kNothing; + } + + /* if we pass -32768, it sometimes causes an overflow and acts like a positive value */ + if (value == -32768) + value = -32767; + + *extra = (((unsigned)value) & 0xFFFF) | (controller << 16); + return action; +} + KeyBinds::Action KeyBinds::translate(const SDL_KeyboardEvent* key, unsigned* extra) { if (key->repeat) @@ -409,7 +451,7 @@ KeyBinds::Action KeyBinds::translate(const SDL_KeyboardEvent* key, unsigned* ext { if (_bindings[i].type == Binding::Type::Key) { - if (key->keysym.sym == _bindings[i].button && mod == _bindings[i].modifiers) + if ((uint32_t)key->keysym.sym == _bindings[i].button && mod == _bindings[i].modifiers) { if (key->state == SDL_PRESSED) return translateButtonPress(i, extra); @@ -447,19 +489,48 @@ KeyBinds::Action KeyBinds::translate(const SDL_ControllerButtonEvent* cbutton, u return Action::kNothing; } +static bool IsAnalog(int button) +{ + switch (button) + { + case kJoy0LeftAnalogX: + case kJoy0LeftAnalogY: + case kJoy0RightAnalogX: + case kJoy0RightAnalogY: + case kJoy1LeftAnalogX: + case kJoy1LeftAnalogY: + case kJoy1RightAnalogX: + case kJoy1RightAnalogY: + return true; + + default: + return false; + } +} + void KeyBinds::translate(const SDL_ControllerAxisEvent* caxis, Input& input, Action* action1, unsigned* extra1, Action* action2, unsigned* extra2) { *action1 = *action2 = Action::kNothing; int threshold = static_cast(32767 * input.getJoystickSensitivity(caxis->which)); + int analogThreshold = threshold / 4; for (size_t i = 0; i < kMaxBindings; i++) { if (_bindings[i].type == Binding::Type::Axis) { if (caxis->axis == _bindings[i].button && caxis->which == _bindings[i].joystick_id) { - if ((_bindings[i].modifiers & 0xFF) == 0xFF) // negative axis + if (IsAnalog(i)) + { + if (caxis->value > analogThreshold || caxis->value < -analogThreshold) + *action1 = translateAnalog(i, caxis->value, extra1); + else + *action1 = translateAnalog(i, 0, extra1); + + break; + } + else if ((_bindings[i].modifiers & 0xFF) == 0xFF) // negative axis { if (caxis->value < -threshold) *action1 = translateButtonPress(i, extra1); @@ -661,7 +732,6 @@ bool KeyBinds::deserializeBindings(const char* json) } else if (event == JSONSAX_STRING) { - int binding = 0; for (int i = 0; i < kMaxBindings; ++i) { if (ud->key == bindingNames[i]) @@ -799,7 +869,8 @@ class ChangeInputDialog : public Dialog const KeyBinds::Binding getButtonDescriptor() const { return _buttonDescriptor; } Input* _input = nullptr; - bool _isOpen; + bool _isOpen = false; + bool _isAnalog = false; bool show(HWND hParent) { @@ -823,6 +894,9 @@ class ChangeInputDialog : public Dialog case WM_KEYDOWN: case WM_SYSKEYDOWN: { + if (_isAnalog) + break; + const auto code = WindowsScanCodeToSDLScanCode(msg.lParam, msg.wParam); const auto sdlKey = SDL_GetKeyFromScancode(code); switch (sdlKey) @@ -903,6 +977,25 @@ class ChangeInputDialog : public Dialog _isOpen = false; } + bool MakeAnalog(KeyBinds::Binding& button) + { + if (button.type != KeyBinds::Binding::Type::Axis) + return false; + + switch (button.button) + { + case SDL_CONTROLLER_AXIS_LEFTX: + case SDL_CONTROLLER_AXIS_LEFTY: + case SDL_CONTROLLER_AXIS_RIGHTX: + case SDL_CONTROLLER_AXIS_RIGHTY: + button.modifiers = 0; + return true; + + default: + return false; + } + } + INT_PTR dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override { switch (msg) @@ -930,6 +1023,9 @@ class ChangeInputDialog : public Dialog KeyBinds::Binding button = _input->captureButtonPress(); if (button.type != KeyBinds::Binding::Type::None) { + if (_isAnalog && !MakeAnalog(button)) + break; + _buttonDescriptor = button; char buffer[32]; KeyBinds::getBindingString(buffer, _buttonDescriptor); @@ -951,7 +1047,7 @@ class InputDialog : public Dialog _bindings = bindings; const WORD WIDTH = 478; - const WORD HEIGHT = 144; + const WORD HEIGHT = 200; addButtonInput(0, 1, "L2", kJoy0L2 + base); addButtonInput(0, 9, "R2", kJoy0R2 + base); @@ -968,6 +1064,13 @@ class InputDialog : public Dialog addButtonInput(4, 1, "Down", kJoy0Down + base); addButtonInput(4, 9, "B", kJoy0B + base); + addButtonInput(5, 1, "L3", kJoy0L3 + base); + addButtonInput(5, 9, "R3", kJoy0R3 + base); + addButtonInput(6, 0, "Left Analog X", kJoy0LeftAnalogX + base); + addButtonInput(6, 2, "Left Analog Y", kJoy0LeftAnalogY + base); + addButtonInput(6, 8, "Right Analog X", kJoy0RightAnalogX + base); + addButtonInput(6, 10, "Right Analog Y", kJoy0RightAnalogY + base); + addButton("OK", IDOK, WIDTH - 55 - 50, HEIGHT - 14, 50, 14, true); addButton("Cancel", IDCANCEL, WIDTH - 50, HEIGHT - 14, 50, 14, false); } @@ -1081,6 +1184,7 @@ class InputDialog : public Dialog ChangeInputDialog db; db.init(buffer); db._input = _input; + db._isAnalog = IsAnalog(button); GetDlgItemText(hwnd, 10000 + button, buffer, sizeof(buffer)); db.addLabel(buffer, ChangeInputDialog::ID_LABEL, 0, 0, 100, 15); diff --git a/src/KeyBinds.h b/src/KeyBinds.h index 6f1d318..2683c94 100644 --- a/src/KeyBinds.h +++ b/src/KeyBinds.h @@ -52,6 +52,12 @@ class KeyBinds kButtonSelect, kButtonStart, + // Joypad analog sticks + kAxisLeftX, + kAxisLeftY, + kAxisRightX, + kAxisRightY, + // State state management (extra = slot) kSaveState, kLoadState, @@ -99,7 +105,7 @@ class KeyBinds Type type; uint16_t modifiers; }; - typedef std::array BindingList; + typedef std::array BindingList; static void getBindingString(char buffer[32], const KeyBinds::Binding& desc); @@ -111,6 +117,7 @@ class KeyBinds KeyBinds::Action translateButtonPress(int button, unsigned* extra); KeyBinds::Action translateButtonReleased(int button, unsigned* extra); + KeyBinds::Action translateAnalog(int button, Sint16 value, unsigned* extra); BindingList _bindings; diff --git a/src/Util.cpp b/src/Util.cpp index b93e71e..6ad66a4 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -363,7 +363,7 @@ bool util::downloadFile(Logger* logger, const std::string& url, const std::strin bSuccess = TRUE; while (availableBytes > 0) { - const DWORD bytesToRead = min(availableBytes, 4096); + const DWORD bytesToRead = availableBytes < 4096 ? availableBytes : 4096; sBuffer.resize(bytesToRead); DWORD bytesFetched = 0U; diff --git a/src/components/Config.cpp b/src/components/Config.cpp index a95420c..13b664b 100644 --- a/src/components/Config.cpp +++ b/src/components/Config.cpp @@ -205,6 +205,9 @@ std::string Config::serialize() for (const auto& pair : _selections) { + if (pair.first[0] == '_' && pair.first[1] == '_') + continue; + json.append(comma); comma = ","; @@ -267,7 +270,37 @@ void Config::deserialize(const char* json) _updated = true; } -void Config::showDialog(const std::string& coreName) +void Config::initializeControllerVariable(Variable& variable, const char* name, const char* key, const std::map& names, unsigned selectedDevice) +{ + variable._name = name; + variable._key = key; + variable._selected = 0; + + for (const auto& pair : names) + { + if (pair.second == selectedDevice) + variable._selected = variable._options.size(); + + variable._options.push_back(pair.first); + } +} + +void Config::initializeInput(Input& input) +{ + Variable controllerVariable; + + for (unsigned i = 2; i > 0; --i) + { + controllerVariable._key = "__controller" + std::to_string(i); + controllerVariable._name = "Controller " + std::to_string(i); + + input.getControllerNames(i - 1, controllerVariable._options, controllerVariable._selected); + if (controllerVariable._options.size() > 1) + _variables.insert(_variables.begin(), controllerVariable); + } +} + +void Config::showDialog(const std::string& coreName, Input& input) { const WORD HEADER_WIDTH = 90; const WORD VALUE_WIDTH = 100; @@ -284,7 +317,6 @@ void Config::showDialog(const std::string& coreName) if (_variables.empty()) { db.addLabel("No settings", 0, 0, HEADER_WIDTH + VALUE_WIDTH, LINE_HEIGHT); - x = HEADER_WIDTH + VALUE_WIDTH + 15; y = LINE_HEIGHT; } else @@ -303,26 +335,26 @@ void Config::showDialog(const std::string& coreName) db.addCombobox(50000 + id, x + HEADER_WIDTH + 5, y, VALUE_WIDTH, LINE_HEIGHT, 5, s_getOption, (void*)& var._options, &var._selected); - if (++row == rows) + if (++id < _variables.size()) { - y = 0; - row = 0; - x += HEADER_WIDTH + VALUE_WIDTH + 15; - } - else - { - y += LINE_HEIGHT; + if (++row == rows) + { + y = 0; + row = 0; + x += HEADER_WIDTH + VALUE_WIDTH + 15; + } + else + { + y += LINE_HEIGHT; + } } - - ++id; } - if (columns > 1 && (_variables.size() % rows) != 0) - x += HEADER_WIDTH + VALUE_WIDTH + 15; - y = rows * LINE_HEIGHT; } + x += HEADER_WIDTH + VALUE_WIDTH + 15; + db.addButton("OK", IDOK, x - 60 - 55, y + 4, 50, 14, true); db.addButton("Cancel", IDCANCEL, x - 60, y + 4, 50, 14, false); @@ -332,7 +364,15 @@ void Config::showDialog(const std::string& coreName) { for (auto& var : _variables) { - _selections[var._key] = var._options[var._selected]; + if (var._key.length() == 13 && SDL_strncmp(var._key.c_str(), "__controller", 12) == 0) + { + const unsigned port = var._key[12] - '1'; + input.setSelectedControllerIndex(port, var._selected); + } + else + { + _selections[var._key] = var._options[var._selected]; + } } } } diff --git a/src/components/Config.h b/src/components/Config.h index 7ac1b91..070bd79 100644 --- a/src/components/Config.h +++ b/src/components/Config.h @@ -19,6 +19,7 @@ along with Foobar. If not, see . #pragma once +#include "components/Input.h" #include "libretro/Components.h" #include @@ -50,7 +51,9 @@ class Config: public libretro::ConfigComponent std::string serialize(); void deserialize(const char* json); - void showDialog(const std::string& coreName); + void initializeInput(Input& input); + + void showDialog(const std::string& coreName, Input& input); protected: static const char* s_getOption(int index, void* udata); @@ -64,6 +67,8 @@ class Config: public libretro::ConfigComponent std::vector _options; }; + static void initializeControllerVariable(Variable& variable, const char* name, const char* key, const std::map& names, unsigned selectedDevice); + libretro::LoggerComponent* _logger; std::string _rootFolder; diff --git a/src/components/Dialog.cpp b/src/components/Dialog.cpp index 6192e25..667417d 100644 --- a/src/components/Dialog.cpp +++ b/src/components/Dialog.cpp @@ -368,5 +368,5 @@ INT_PTR CALLBACK Dialog::s_dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM void Dialog::markClosed(HWND hwnd) { - SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL); + SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); } diff --git a/src/components/Input.cpp b/src/components/Input.cpp index e922780..99ff68f 100644 --- a/src/components/Input.cpp +++ b/src/components/Input.cpp @@ -228,6 +228,22 @@ void Input::buttonEvent(int port, Button button, bool pressed) _info[port][_devices[port]]._state[rbutton] = pressed; } +void Input::axisEvent(int port, Axis axis, int16_t value) +{ + int raxis; + + switch (axis) + { + case Axis::kLeftAxisX: raxis = (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_X; break; + case Axis::kLeftAxisY: raxis = (RETRO_DEVICE_INDEX_ANALOG_LEFT << 1) | RETRO_DEVICE_ID_ANALOG_Y; break; + case Axis::kRightAxisX: raxis = (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_X; break; + case Axis::kRightAxisY: raxis = (RETRO_DEVICE_INDEX_ANALOG_RIGHT << 1) | RETRO_DEVICE_ID_ANALOG_Y; break; + default: return; + } + + _info[port][_devices[port]]._axis[raxis] = value; +} + void Input::processEvent(const SDL_Event* event) { switch (event->type) @@ -276,10 +292,14 @@ void Input::setControllerInfo(const struct retro_controller_info* rinfo, unsigne info._description = rinfo->types[i].desc; info._id = rinfo->types[i].id; - if ((info._id & RETRO_DEVICE_MASK) == RETRO_DEVICE_JOYPAD) + if ((info._id & RETRO_DEVICE_MASK) == RETRO_DEVICE_JOYPAD || + (info._id & RETRO_DEVICE_MASK) == RETRO_DEVICE_ANALOG) { if (port < kMaxPorts) { + memset(info._state, 0, sizeof(info._state)); + memset(info._axis, 0, sizeof(info._axis)); + _info[port].push_back(info); _ports |= 1ULL << port; } @@ -292,6 +312,28 @@ void Input::setControllerInfo(const struct retro_controller_info* rinfo, unsigne } } +void Input::getControllerNames(unsigned port, std::vector& names, int& selectedIndex) const +{ + names.clear(); + + if (port < kMaxPorts) + { + for (const ControllerInfo& info : _info[port]) + names.push_back(info._description); + + selectedIndex = _devices[port]; + } + else + { + selectedIndex = 0; + } +} + +void Input::setSelectedControllerIndex(unsigned port, int selectedIndex) +{ + _devices[port] = selectedIndex; +} + bool Input::ctrlUpdated() { bool updated = _updated; @@ -301,17 +343,8 @@ bool Input::ctrlUpdated() unsigned Input::getController(unsigned port) { - uint64_t bit = 1ULL << port; - - for (const auto& pair: _pads) - { - const Pad* pad = &pair.second; - - if ((pad->_ports & bit) != 0) - { - return _info[port][_devices[port]]._id; - } - } + if (port < kMaxPorts) + return _info[port][_devices[port]]._id; return RETRO_DEVICE_NONE; } @@ -324,7 +357,19 @@ void Input::poll() int16_t Input::read(unsigned port, unsigned device, unsigned index, unsigned id) { - return (port < kMaxPorts &&_info[port][_devices[port]]._state[id]) ? 32767 : 0; + if (port < kMaxPorts) + { + switch (device) + { + case RETRO_DEVICE_JOYPAD: + return _info[port][_devices[port]]._state[id] ? 32767 : 0; + + case RETRO_DEVICE_ANALOG: + return _info[port][_devices[port]]._axis[index << 1 | id]; + } + } + + return 0; } KeyBinds::Binding Input::captureButtonPress() @@ -391,12 +436,11 @@ void Input::removeController(const SDL_Event* event) if (it != _pads.end()) { Pad* pad = &it->second; + _logger->info(TAG "Controller %s (%s) removed", pad->_controllerName, pad->_joystickName); SDL_GameControllerClose(pad->_controller); _pads.erase(it); - _logger->info(TAG "Controller %s (%s) removed", pad->_controllerName, pad->_joystickName); - // Flag a pending update so the core will receive an event for this removal _updated = true; } diff --git a/src/components/Input.h b/src/components/Input.h index d3d4129..e90fa4f 100644 --- a/src/components/Input.h +++ b/src/components/Input.h @@ -49,7 +49,15 @@ class Input: public libretro::InputComponent kL3, kR3, kSelect, - kStart + kStart, + }; + + enum class Axis + { + kLeftAxisX, + kLeftAxisY, + kRightAxisX, + kRightAxisY }; bool init(libretro::LoggerComponent* logger); @@ -59,6 +67,7 @@ class Input: public libretro::InputComponent void addController(int which); void autoAssign(); void buttonEvent(int port, Button button, bool pressed); + void axisEvent(int port, Axis axis, int16_t value); void processEvent(const SDL_Event* event); virtual void setInputDescriptors(const struct retro_input_descriptor* descs, unsigned count) override; @@ -66,6 +75,8 @@ class Input: public libretro::InputComponent virtual void setControllerInfo(const struct retro_controller_info* info, unsigned count) override; virtual bool ctrlUpdated() override; virtual unsigned getController(unsigned port) override; + void getControllerNames(unsigned port, std::vector& names, int& selectedIndex) const; + void setSelectedControllerIndex(unsigned port, int selectedIndex); virtual void poll() override; virtual int16_t read(unsigned port, unsigned device, unsigned index, unsigned id) override; @@ -103,6 +114,7 @@ class Input: public libretro::InputComponent std::string _description; unsigned _id; bool _state[16]; + int16_t _axis[4]; }; enum