diff --git a/include/emulator.hpp b/include/emulator.hpp index 81502960..5c55fc90 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -28,6 +28,12 @@ class Emulator { SDL_GameController* gameController; int gameControllerID; + // Variables to keep track of whether the user is controlling the 3DS analog stick with their keyboard + // This is done so when a gamepad is connected, we won't automatically override the 3DS analog stick settings with the gamepad's state + // And so the user can still use the keyboard to control the analog + bool keyboardAnalogX = false; + bool keyboardAnalogY = false; + static constexpr u32 width = 400; static constexpr u32 height = 240 * 2; // * 2 because 2 screens ROMType romType = ROMType::None; @@ -46,7 +52,6 @@ public: // Make SDL use consistent positional button mapping SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0"); - if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) { Helpers::warn("Failed to initialize SDL2 GameController: %s", SDL_GetError()); } @@ -63,7 +68,6 @@ public: } glContext = SDL_GL_CreateContext(window); - if (glContext == nullptr) { Helpers::panic("OpenGL context creation failed: %s", SDL_GetError()); } diff --git a/src/emulator.cpp b/src/emulator.cpp index b973a28e..7eccc82c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -57,10 +57,25 @@ void Emulator::run() { case SDLK_UP: srv.pressKey(Keys::Up); break; case SDLK_DOWN: srv.pressKey(Keys::Down); break; - case SDLK_w: srv.setCirclepadY(0x9C); break; - case SDLK_a: srv.setCirclepadX(-0x9C); break; - case SDLK_s: srv.setCirclepadY(-0x9C); break; - case SDLK_d: srv.setCirclepadX(0x9C); break; + case SDLK_w: + srv.setCirclepadY(0x9C); + keyboardAnalogY = true; + break; + + case SDLK_a: + srv.setCirclepadX(-0x9C); + keyboardAnalogX = true; + break; + + case SDLK_s: + srv.setCirclepadY(-0x9C); + keyboardAnalogY = true; + break; + + case SDLK_d: + srv.setCirclepadX(0x9C); + keyboardAnalogX = true; + break; case SDLK_RETURN: srv.pressKey(Keys::Start); break; case SDLK_BACKSPACE: srv.pressKey(Keys::Select); break; @@ -82,10 +97,17 @@ void Emulator::run() { case SDLK_DOWN: srv.releaseKey(Keys::Down); break; // Err this is probably not ideal - case SDLK_w: srv.setCirclepadY(0); break; - case SDLK_a: srv.setCirclepadX(0); break; - case SDLK_s: srv.setCirclepadY(0); break; - case SDLK_d: srv.setCirclepadX(0); break; + case SDLK_w: + case SDLK_s: + srv.setCirclepadY(0); + keyboardAnalogY = false; + break; + + case SDLK_a: + case SDLK_d: + srv.setCirclepadX(0); + keyboardAnalogX = false; + break; case SDLK_RETURN: srv.releaseKey(Keys::Start); break; case SDLK_BACKSPACE: srv.releaseKey(Keys::Select); break; @@ -163,29 +185,25 @@ void Emulator::run() { } if (gameController != nullptr) { - const s16 stickX = SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTX); - const s16 stickY = SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTY); - constexpr s16 deadzone = 3276; - constexpr s16 maxValue = 0x9C; - constexpr s16 div = 0x8000 / maxValue; + const s16 stickX = SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTX); + const s16 stickY = SDL_GameControllerGetAxis(gameController, SDL_CONTROLLER_AXIS_LEFTY); + constexpr s16 deadzone = 3276; + constexpr s16 maxValue = 0x9C; + constexpr s16 div = 0x8000 / maxValue; - if (abs(stickX) < deadzone) { - // Avoid overriding the keyboard's circlepad input - if (abs(srv.getCirclepadX()) != maxValue) { - srv.setCirclepadX(0); - } - } else { - srv.setCirclepadX(stickX / div); - } + // Avoid overriding the keyboard's circlepad input + if (abs(stickX) < deadzone && !keyboardAnalogX) { + srv.setCirclepadX(0); + } else { + srv.setCirclepadX(stickX / div); + } - if (abs(stickY) < deadzone) { - if (abs(srv.getCirclepadY()) != maxValue) { - srv.setCirclepadY(0); - } - } else { - srv.setCirclepadY(-(stickY / div)); - } - } + if (abs(stickY) < deadzone && !keyboardAnalogY) { + srv.setCirclepadY(0); + } else { + srv.setCirclepadY(-(stickY / div)); + } + } // Update inputs in the HID module srv.updateInputs(cpu.getTicks());