[Controller] Slightly better analog handling

This commit is contained in:
wheremyfoodat 2023-06-28 01:40:23 +03:00
parent bc4e71bf40
commit 71582eff6d
2 changed files with 53 additions and 31 deletions

View file

@ -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());
}

View file

@ -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());