Merge pull request #85 from wheremyfoodat/gyro

Initial gyroscope support
This commit is contained in:
wheremyfoodat 2023-07-09 00:05:21 +03:00 committed by GitHub
commit 409f26b8e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 1 deletions

View file

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

View file

@ -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) {

View file

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

View file

@ -59,7 +59,8 @@ Keyboard & Mouse
- R button P
- Start button Enter
- Select button Backspace
- Touch Screen Left click
- Touch Screen Left click
- Gyroscope Hold right click and swipe your mouse left and right (support is kind of shaky atm, but games that require gyro here and there like Kirby should work)
Panda3DS also supports controller input using the SDL2 GameController API.

View file

@ -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<u64>(0x160, readSharedMem<u64>(0x158)); // Copy previous tick count
writeSharedMem<u64>(0x158, currentTick); // Write new tick count
}
const size_t gyroEntryOffset = 0x178 + (nextGyroIndex * 6); // Offset in the array of 8 touchscreen entries
writeSharedMem<u16>(gyroEntryOffset, pitch);
writeSharedMem<u16>(gyroEntryOffset + 2, yaw);
writeSharedMem<u16>(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<u32>(0x168, nextGyroIndex); // Index last updated by the HID module
nextGyroIndex = (nextGyroIndex + 1) % 32; // Move to next entry
}

View file

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