From 1a7e79f2c9ccd119a3769bab1a18de07d2dce342 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 8 Jul 2023 23:31:16 +0300 Subject: [PATCH] Bad-but-ok for now gyroscope implementation --- include/emulator.hpp | 4 ++++ include/services/hid.hpp | 5 +++++ include/services/service_manager.hpp | 4 ++++ src/core/services/hid.cpp | 9 +++++++++ src/emulator.cpp | 22 ++++++++++++++++++++++ 5 files changed, 44 insertions(+) diff --git a/include/emulator.hpp b/include/emulator.hpp index 33f1ae6e..e1684085 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -37,6 +37,10 @@ class Emulator { bool keyboardAnalogX = false; bool keyboardAnalogY = false; + // For tracking whether to update gyroscope + // We bind gyro to right click + mouse movement + bool holdingRightClick = false; + static constexpr u32 width = 400; static constexpr u32 height = 240 * 2; // * 2 because 2 screens ROMType romType = ROMType::None; diff --git a/include/services/hid.hpp b/include/services/hid.hpp index 70bae750..6a3aab95 100644 --- a/include/services/hid.hpp +++ b/include/services/hid.hpp @@ -52,6 +52,7 @@ class HIDService { s16 circlePadX, circlePadY; // Circlepad state s16 touchScreenX, touchScreenY; // Touchscreen state + s16 roll, pitch, yaw; // Gyroscope state bool accelerometerEnabled; bool eventsInitialized; @@ -117,6 +118,10 @@ class HIDService { newButtons |= 1 << 31; } + void setRoll(s16 value) { roll = value; } + void setPitch(s16 value) { pitch = value; } + void setYaw(s16 value) { yaw = value; } + void updateInputs(u64 currentTimestamp); void setSharedMem(u8* ptr) { diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp index 3136408f..1d93641c 100644 --- a/include/services/service_manager.hpp +++ b/include/services/service_manager.hpp @@ -99,4 +99,8 @@ class ServiceManager { void updateInputs(u64 currentTimestamp) { hid.updateInputs(currentTimestamp); } void setTouchScreenPress(u16 x, u16 y) { hid.setTouchScreenPress(x, y); } void releaseTouchScreen() { hid.releaseTouchScreen(); } + + void setRoll(s16 roll) { hid.setRoll(roll); } + void setPitch(s16 pitch) { hid.setPitch(pitch); } + void setYaw(s16 yaw) { hid.setYaw(yaw); } }; diff --git a/src/core/services/hid.cpp b/src/core/services/hid.cpp index 27a078f2..0c83487c 100644 --- a/src/core/services/hid.cpp +++ b/src/core/services/hid.cpp @@ -33,6 +33,7 @@ void HIDService::reset() { newButtons = oldButtons = 0; circlePadX = circlePadY = 0; touchScreenX = touchScreenY = 0; + roll = pitch = yaw = 0; } void HIDService::handleSyncRequest(u32 messagePointer) { @@ -182,6 +183,14 @@ void HIDService::updateInputs(u64 currentTick) { writeSharedMem(0x160, readSharedMem(0x158)); // Copy previous tick count writeSharedMem(0x158, currentTick); // Write new tick count } + const size_t gyroEntryOffset = 0x178 + (nextGyroIndex * 6); // Offset in the array of 8 touchscreen entries + writeSharedMem(gyroEntryOffset, pitch); + writeSharedMem(gyroEntryOffset + 2, yaw); + writeSharedMem(gyroEntryOffset + 4, roll); + + // Since gyroscope euler angles are relative, we zero them out here and the frontend will update them again when we receive a new rotation + roll = pitch = yaw = 0; + writeSharedMem(0x168, nextGyroIndex); // Index last updated by the HID module nextGyroIndex = (nextGyroIndex + 1) % 32; // Move to next entry } diff --git a/src/emulator.cpp b/src/emulator.cpp index 7ca9e26d..198c573d 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -192,6 +192,8 @@ void Emulator::run() { } else { srv.releaseTouchScreen(); } + } else if (event.button.button == SDL_BUTTON_RIGHT) { + holdingRightClick = true; } break; } @@ -199,6 +201,8 @@ void Emulator::run() { case SDL_MOUSEBUTTONUP: if (event.button.button == SDL_BUTTON_LEFT) { srv.releaseTouchScreen(); + } else if (event.button.button == SDL_BUTTON_RIGHT) { + holdingRightClick = false; } break; @@ -244,6 +248,24 @@ void Emulator::run() { } } } + + // Detect mouse motion events for gyroscope emulation + case SDL_MOUSEMOTION: { + // We use right click to indicate we want to rotate the console. If right click is not held, then this is not a gyroscope rotation + if (!holdingRightClick) break; + + // Relative motion since last mouse motion event + const s32 motionX = event.motion.xrel; + const s32 motionY = event.motion.yrel; + + // The gyroscope involves lots of weird math I don't want to bother with atm + // So up until then, we will set the gyroscope euler angles to fixed values based on the direction of the relative motion + const s32 roll = motionX > 0 ? 0x7f : -0x7f; + const s32 pitch = motionY > 0 ? 0x7f : -0x7f; + srv.setRoll(roll); + srv.setPitch(pitch); + break; + } } }