From 608bf88c5f49c9e24bea403df5f2ea764dd0e962 Mon Sep 17 00:00:00 2001 From: liuk7071 Date: Mon, 5 Jun 2023 13:25:06 +0200 Subject: [PATCH 1/6] Basic input --- include/kernel/kernel.hpp | 5 ++++ include/services/hid.hpp | 5 ++++ include/services/service_manager.hpp | 5 ++++ src/core/services/hid.cpp | 5 ++++ src/emulator.cpp | 37 +++++++++++++++++++++++++++- 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp index 9d46d1b9..ddeec2e1 100644 --- a/include/kernel/kernel.hpp +++ b/include/kernel/kernel.hpp @@ -201,5 +201,10 @@ public: void sendGPUInterrupt(GPUInterrupt type) { serviceManager.requestGPUInterrupt(type); } void signalDSPEvents() { serviceManager.signalDSPEvents(); } + + void pressKey(u32 key) { serviceManager.pressKey(key); } + void releaseKey(u32 key) { serviceManager.releaseKey(key); } + void setCirclepadX(u16 x) { serviceManager.setCirclepadX(x); } + void setCirclepadY(u16 y) { serviceManager.setCirclepadY(y); } void updateInputs() { serviceManager.updateInputs(); } }; \ No newline at end of file diff --git a/include/services/hid.hpp b/include/services/hid.hpp index 8464cd48..2199d367 100644 --- a/include/services/hid.hpp +++ b/include/services/hid.hpp @@ -34,6 +34,11 @@ public: HIDService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); void handleSyncRequest(u32 messagePointer); + + void pressKey(u32 key); + void releaseKey(u32 key); + void setCirclepadX(u16 x); + void setCirclepadY(u16 y); void updateInputs(); void setSharedMem(u8* ptr) { diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp index 2a50ffaf..c67794de 100644 --- a/include/services/service_manager.hpp +++ b/include/services/service_manager.hpp @@ -84,5 +84,10 @@ public: void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); } void signalDSPEvents() { dsp.signalEvents(); } + + void pressKey(u32 key) { hid.pressKey(key); } + void releaseKey(u32 key) { hid.releaseKey(key); } + void setCirclepadX(u16 x) { hid.setCirclepadX(x); } + void setCirclepadY(u16 y) { hid.setCirclepadY(y); } void updateInputs() { hid.updateInputs(); } }; \ No newline at end of file diff --git a/src/core/services/hid.cpp b/src/core/services/hid.cpp index 21e38dba..854a4286 100644 --- a/src/core/services/hid.cpp +++ b/src/core/services/hid.cpp @@ -108,6 +108,11 @@ void HIDService::getIPCHandles(u32 messagePointer) { } } +void HIDService::pressKey(u32 key) { sharedMem[0]++; *(u32*)&sharedMem[0x28] |= key; } +void HIDService::releaseKey(u32 key) { sharedMem[0]++; *(u32*)&sharedMem[0x28] &= ~key; } +void HIDService::setCirclepadX(u16 x) { sharedMem[0]++; *(u16*)&sharedMem[0x28 + 0xC] = x; } +void HIDService::setCirclepadY(u16 y) { sharedMem[0]++; *(u16*)&sharedMem[0x28 + 0xC + 2] = y; } + // TODO: We don't currently have inputs but we must at least try to signal the HID key input events now and then void HIDService::updateInputs() { // For some reason, the original developers decided to signal the HID events each time the OS rescanned inputs diff --git a/src/emulator.cpp b/src/emulator.cpp index 56e555c7..a404e19c 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -36,10 +36,45 @@ void Emulator::run() { SDL_Event event; while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { + switch (event.type) { + case SDL_QUIT: printf("Bye :(\n"); running = false; return; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_z: kernel.pressKey(1 << 0); break; + case SDLK_RIGHT: kernel.pressKey(1 << 4); break; + case SDLK_LEFT: kernel.pressKey(1 << 5); break; + case SDLK_UP: kernel.pressKey(1 << 6); break; + case SDLK_DOWN: kernel.pressKey(1 << 7); break; + case SDLK_w: kernel.setCirclepadY(0x9C); break; + case SDLK_a: kernel.setCirclepadX(-0x9C); break; + case SDLK_s: kernel.setCirclepadY(-0x9C); break; + case SDLK_d: kernel.setCirclepadX(0x9C); break; + case SDLK_j: kernel.pressKey(1 << 1); break; + case SDLK_k: kernel.pressKey(1 << 10); break; + case SDLK_l: kernel.pressKey(1 << 11); break; + case SDLK_r: kernel.pressKey(1 << 8); break; + } + break; + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_z: kernel.releaseKey(1 << 0); break; + case SDLK_RIGHT: kernel.releaseKey(1 << 4); break; + case SDLK_LEFT: kernel.releaseKey(1 << 5); break; + case SDLK_UP: kernel.releaseKey(1 << 6); break; + case SDLK_DOWN: kernel.releaseKey(1 << 7); break; + case SDLK_w: kernel.setCirclepadY(0); break; + case SDLK_a: kernel.setCirclepadX(0); break; + case SDLK_s: kernel.setCirclepadY(0); break; + case SDLK_d: kernel.setCirclepadX(0); break; + case SDLK_j: kernel.releaseKey(1 << 1); break; + case SDLK_k: kernel.releaseKey(1 << 10); break; + case SDLK_l: kernel.releaseKey(1 << 11); break; + case SDLK_r: kernel.releaseKey(1 << 8); break; + } + break; } } From 0c0e7a4cb90f8edea50e250565b8adc5cef9f3d8 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Mon, 5 Jun 2023 15:28:44 +0300 Subject: [PATCH 2/6] Clean up srv interface for HID --- include/kernel/kernel.hpp | 10 ++--- include/services/service_manager.hpp | 2 +- src/emulator.cpp | 60 ++++++++++++++-------------- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp index ddeec2e1..b4790056 100644 --- a/include/kernel/kernel.hpp +++ b/include/kernel/kernel.hpp @@ -199,12 +199,8 @@ public: return &objects[handle]; } - void sendGPUInterrupt(GPUInterrupt type) { serviceManager.requestGPUInterrupt(type); } - void signalDSPEvents() { serviceManager.signalDSPEvents(); } + ServiceManager& getServiceManager() { return serviceManager; } - void pressKey(u32 key) { serviceManager.pressKey(key); } - void releaseKey(u32 key) { serviceManager.releaseKey(key); } - void setCirclepadX(u16 x) { serviceManager.setCirclepadX(x); } - void setCirclepadY(u16 y) { serviceManager.setCirclepadY(y); } - void updateInputs() { serviceManager.updateInputs(); } + void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); } + void signalDSPEvents() { serviceManager.signalDSPEvents(); } }; \ No newline at end of file diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp index c67794de..088adbc5 100644 --- a/include/services/service_manager.hpp +++ b/include/services/service_manager.hpp @@ -79,7 +79,7 @@ public: void sendCommandToService(u32 messagePointer, Handle handle); // Wrappers for communicating with certain services - void requestGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); } + void sendGPUInterrupt(GPUInterrupt type) { gsp_gpu.requestInterrupt(type); } void setGSPSharedMem(u8* ptr) { gsp_gpu.setSharedMem(ptr); } void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); } diff --git a/src/emulator.cpp b/src/emulator.cpp index a404e19c..757f1e7e 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -27,12 +27,14 @@ void Emulator::run() { runFrame(); // Run 1 frame of instructions gpu.display(); // Display graphics + ServiceManager& srv = kernel.getServiceManager(); + // Send VBlank interrupts - kernel.sendGPUInterrupt(GPUInterrupt::VBlank0); - kernel.sendGPUInterrupt(GPUInterrupt::VBlank1); + srv.sendGPUInterrupt(GPUInterrupt::VBlank0); + srv.sendGPUInterrupt(GPUInterrupt::VBlank1); // Update inputs in the HID module - kernel.updateInputs(); + srv.updateInputs(); SDL_Event event; while (SDL_PollEvent(&event)) { @@ -43,36 +45,36 @@ void Emulator::run() { return; case SDL_KEYDOWN: switch (event.key.keysym.sym) { - case SDLK_z: kernel.pressKey(1 << 0); break; - case SDLK_RIGHT: kernel.pressKey(1 << 4); break; - case SDLK_LEFT: kernel.pressKey(1 << 5); break; - case SDLK_UP: kernel.pressKey(1 << 6); break; - case SDLK_DOWN: kernel.pressKey(1 << 7); break; - case SDLK_w: kernel.setCirclepadY(0x9C); break; - case SDLK_a: kernel.setCirclepadX(-0x9C); break; - case SDLK_s: kernel.setCirclepadY(-0x9C); break; - case SDLK_d: kernel.setCirclepadX(0x9C); break; - case SDLK_j: kernel.pressKey(1 << 1); break; - case SDLK_k: kernel.pressKey(1 << 10); break; - case SDLK_l: kernel.pressKey(1 << 11); break; - case SDLK_r: kernel.pressKey(1 << 8); break; + case SDLK_z: srv.pressKey(1 << 0); break; + case SDLK_RIGHT: srv.pressKey(1 << 4); break; + case SDLK_LEFT: srv.pressKey(1 << 5); break; + case SDLK_UP: srv.pressKey(1 << 6); break; + case SDLK_DOWN: srv.pressKey(1 << 7); 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_j: srv.pressKey(1 << 1); break; + case SDLK_k: srv.pressKey(1 << 10); break; + case SDLK_l: srv.pressKey(1 << 11); break; + case SDLK_r: srv.pressKey(1 << 8); break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { - case SDLK_z: kernel.releaseKey(1 << 0); break; - case SDLK_RIGHT: kernel.releaseKey(1 << 4); break; - case SDLK_LEFT: kernel.releaseKey(1 << 5); break; - case SDLK_UP: kernel.releaseKey(1 << 6); break; - case SDLK_DOWN: kernel.releaseKey(1 << 7); break; - case SDLK_w: kernel.setCirclepadY(0); break; - case SDLK_a: kernel.setCirclepadX(0); break; - case SDLK_s: kernel.setCirclepadY(0); break; - case SDLK_d: kernel.setCirclepadX(0); break; - case SDLK_j: kernel.releaseKey(1 << 1); break; - case SDLK_k: kernel.releaseKey(1 << 10); break; - case SDLK_l: kernel.releaseKey(1 << 11); break; - case SDLK_r: kernel.releaseKey(1 << 8); break; + case SDLK_z: srv.releaseKey(1 << 0); break; + case SDLK_RIGHT: srv.releaseKey(1 << 4); break; + case SDLK_LEFT: srv.releaseKey(1 << 5); break; + case SDLK_UP: srv.releaseKey(1 << 6); break; + case SDLK_DOWN: srv.releaseKey(1 << 7); break; + 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_j: srv.releaseKey(1 << 1); break; + case SDLK_k: srv.releaseKey(1 << 10); break; + case SDLK_l: srv.releaseKey(1 << 11); break; + case SDLK_r: srv.releaseKey(1 << 8); break; } break; } From 629e00251ce862bc38801fb3315e595db18ac856 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Mon, 5 Jun 2023 22:43:59 +0300 Subject: [PATCH 3/6] [HID] Remap keys --- include/services/hid.hpp | 25 ++++++++++++++ src/emulator.cpp | 74 ++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/include/services/hid.hpp b/include/services/hid.hpp index 2199d367..c13d0756 100644 --- a/include/services/hid.hpp +++ b/include/services/hid.hpp @@ -6,6 +6,31 @@ #include "logger.hpp" #include "memory.hpp" +namespace HID::Keys { + enum : u32 { + A = 1 << 0, + B = 1 << 1, + Select = 1 << 2, + Start = 1 << 3, + Right = 1 << 4, + Left = 1 << 5, + Up = 1 << 6, + Down = 1 << 7, + R = 1 << 8, + L = 1 << 9, + X = 1 << 10, + Y = 1 << 11, + + GPIO0Inv = 1 << 12, // Inverted value of GPIO bit 0 + GPIO14Inv = 1 << 13, // Inverted value of GPIO bit 14 + + CirclePadRight = 1 << 28, // X >= 41 + CirclePadLeft = 1 << 29, // X <= -41 + CirclePadUp = 1 << 30, // Y >= 41 + CirclePadDown = 1 << 31 // Y <= -41 + }; +} + // Circular dependency because we need HID to spawn events class Kernel; diff --git a/src/emulator.cpp b/src/emulator.cpp index 757f1e7e..19fdcd82 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -33,11 +33,10 @@ void Emulator::run() { srv.sendGPUInterrupt(GPUInterrupt::VBlank0); srv.sendGPUInterrupt(GPUInterrupt::VBlank1); - // Update inputs in the HID module - srv.updateInputs(); - SDL_Event event; while (SDL_PollEvent(&event)) { + namespace Keys = HID::Keys; + switch (event.type) { case SDL_QUIT: printf("Bye :(\n"); @@ -45,41 +44,58 @@ void Emulator::run() { return; case SDL_KEYDOWN: switch (event.key.keysym.sym) { - case SDLK_z: srv.pressKey(1 << 0); break; - case SDLK_RIGHT: srv.pressKey(1 << 4); break; - case SDLK_LEFT: srv.pressKey(1 << 5); break; - case SDLK_UP: srv.pressKey(1 << 6); break; - case SDLK_DOWN: srv.pressKey(1 << 7); 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_j: srv.pressKey(1 << 1); break; - case SDLK_k: srv.pressKey(1 << 10); break; - case SDLK_l: srv.pressKey(1 << 11); break; - case SDLK_r: srv.pressKey(1 << 8); break; + case SDLK_l: srv.pressKey(Keys::A); break; + case SDLK_k: srv.pressKey(Keys::B); break; + case SDLK_o: srv.pressKey(Keys::X); break; + case SDLK_i: srv.pressKey(Keys::Y); break; + + case SDLK_q: srv.pressKey(Keys::L); break; + case SDLK_p: srv.pressKey(Keys::R); break; + + case SDLK_RIGHT: srv.pressKey(Keys::Right); break; + case SDLK_LEFT: srv.pressKey(Keys::Left); break; + 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_RETURN: srv.pressKey(Keys::Start); break; + case SDLK_BACKSPACE: srv.pressKey(Keys::Select); break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { - case SDLK_z: srv.releaseKey(1 << 0); break; - case SDLK_RIGHT: srv.releaseKey(1 << 4); break; - case SDLK_LEFT: srv.releaseKey(1 << 5); break; - case SDLK_UP: srv.releaseKey(1 << 6); break; - case SDLK_DOWN: srv.releaseKey(1 << 7); break; - 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_j: srv.releaseKey(1 << 1); break; - case SDLK_k: srv.releaseKey(1 << 10); break; - case SDLK_l: srv.releaseKey(1 << 11); break; - case SDLK_r: srv.releaseKey(1 << 8); break; + case SDLK_l: srv.releaseKey(Keys::A); break; + case SDLK_k: srv.releaseKey(Keys::B); break; + case SDLK_o: srv.releaseKey(Keys::X); break; + case SDLK_i: srv.releaseKey(Keys::Y); break; + + case SDLK_q: srv.releaseKey(Keys::L); break; + case SDLK_p: srv.releaseKey(Keys::R); break; + + case SDLK_RIGHT: srv.releaseKey(Keys::Right); break; + case SDLK_LEFT: srv.releaseKey(Keys::Left); break; + case SDLK_UP: srv.releaseKey(Keys::Up); break; + 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_RETURN: srv.releaseKey(Keys::Start); break; + case SDLK_BACKSPACE: srv.releaseKey(Keys::Select); break; } break; } } + // Update inputs in the HID module + srv.updateInputs(); SDL_GL_SwapWindow(window); } } From dea8b9ec2e402e6dd3a59dc6ac83c79463e9d2a4 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Tue, 6 Jun 2023 00:57:48 +0300 Subject: [PATCH 4/6] [HID] Redo service --- include/services/hid.hpp | 56 ++++++++++++++++++++++--- include/services/service_manager.hpp | 2 +- src/core/services/hid.cpp | 63 +++++++++++++++++++++++++--- src/emulator.cpp | 2 +- 4 files changed, 109 insertions(+), 14 deletions(-) diff --git a/include/services/hid.hpp b/include/services/hid.hpp index c13d0756..70a25673 100644 --- a/include/services/hid.hpp +++ b/include/services/hid.hpp @@ -27,7 +27,7 @@ namespace HID::Keys { CirclePadRight = 1 << 28, // X >= 41 CirclePadLeft = 1 << 29, // X <= -41 CirclePadUp = 1 << 30, // Y >= 41 - CirclePadDown = 1 << 31 // Y <= -41 + CirclePadDown = 1u << 31 // Y <= -41 }; } @@ -40,6 +40,16 @@ class HIDService { Kernel& kernel; u8* sharedMem = nullptr; // Pointer to HID shared memory + uint nextPadIndex; + uint nextTouchscreenIndex; + uint nextAccelerometerIndex; + uint nextGyroIndex; + + u32 newButtons; // The button state currently being edited + u32 oldButtons; // The previous pad state + + s16 circlePadX, circlePadY; // Circlepad state + bool accelerometerEnabled; bool eventsInitialized; bool gyroEnabled; @@ -55,16 +65,50 @@ class HIDService { void getGyroscopeCoefficient(u32 messagePointer); void getIPCHandles(u32 messagePointer); + // Don't call these prior to initializing shared mem pls + template + T readSharedMem(size_t offset) { + return *(T*)&sharedMem[offset]; + } + + template + void writeSharedMem(size_t offset, T value) { + *(T*)&sharedMem[offset] = value; + } + public: HIDService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); void handleSyncRequest(u32 messagePointer); - void pressKey(u32 key); - void releaseKey(u32 key); - void setCirclepadX(u16 x); - void setCirclepadY(u16 y); - void updateInputs(); + void pressKey(u32 mask) { newButtons |= mask; } + void releaseKey(u32 mask) { newButtons &= ~mask; } + + void setCirclepadX(s16 x) { + circlePadX = x; + + // Turn bits 28 and 29 off in the new button state, which indicate whether the circlepad is steering left or right + // Then, set them according to the new value of x + newButtons &= ~0x3000'0000; + if (x >= 41) // Pressing right + newButtons |= 1 << 28; + else if (x <= -41) // Pressing left + newButtons |= 1 << 29; + } + + void setCirclepadY(s16 y) { + circlePadY = y; + + // Turn bits 30 and 31 off in the new button state, which indicate whether the circlepad is steering up or down + // Then, set them according to the new value of y + newButtons &= ~0xC000'0000; + if (y >= 41) // Pressing up + newButtons |= 1 << 30; + else if (y <= -41) // Pressing down + newButtons |= 1 << 31; + } + + void updateInputs(u64 currentTimestamp); void setSharedMem(u8* ptr) { sharedMem = ptr; diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp index 088adbc5..8084c1ea 100644 --- a/include/services/service_manager.hpp +++ b/include/services/service_manager.hpp @@ -89,5 +89,5 @@ public: void releaseKey(u32 key) { hid.releaseKey(key); } void setCirclepadX(u16 x) { hid.setCirclepadX(x); } void setCirclepadY(u16 y) { hid.setCirclepadY(y); } - void updateInputs() { hid.updateInputs(); } + void updateInputs(u64 currentTimestamp) { hid.updateInputs(currentTimestamp); } }; \ No newline at end of file diff --git a/src/core/services/hid.cpp b/src/core/services/hid.cpp index 854a4286..cc4d5575 100644 --- a/src/core/services/hid.cpp +++ b/src/core/services/hid.cpp @@ -30,6 +30,12 @@ void HIDService::reset() { for (auto& e : events) { e = std::nullopt; } + + // Reset indices for the various HID shared memory entries + nextPadIndex = nextTouchscreenIndex = nextAccelerometerIndex = nextGyroIndex = 0; + // Reset button states + newButtons = oldButtons = 0; + circlePadX = circlePadY = 0; } void HIDService::handleSyncRequest(u32 messagePointer) { @@ -108,13 +114,58 @@ void HIDService::getIPCHandles(u32 messagePointer) { } } -void HIDService::pressKey(u32 key) { sharedMem[0]++; *(u32*)&sharedMem[0x28] |= key; } -void HIDService::releaseKey(u32 key) { sharedMem[0]++; *(u32*)&sharedMem[0x28] &= ~key; } -void HIDService::setCirclepadX(u16 x) { sharedMem[0]++; *(u16*)&sharedMem[0x28 + 0xC] = x; } -void HIDService::setCirclepadY(u16 y) { sharedMem[0]++; *(u16*)&sharedMem[0x28 + 0xC + 2] = y; } +void HIDService::updateInputs(u64 currentTick) { + // Update shared memory if it has been initialized + if (sharedMem) { + // First, update the pad state + if (nextPadIndex == 0) { + writeSharedMem(0x8, readSharedMem(0x0)); // Copy previous tick count + writeSharedMem(0x0, currentTick); // Write new tick count + } + + writeSharedMem(0x10, nextPadIndex); // Index last updated by the HID module + writeSharedMem(0x1C, newButtons); // Current PAD state + writeSharedMem(0x20, circlePadX); // Current circle pad state + writeSharedMem(0x22, circlePadY); + + const size_t padEntryOffset = 0x28 + (nextPadIndex * 0x10); // Offset in the array of 8 pad entries + nextPadIndex = (nextPadIndex + 1) % 8; // Move to next entry + + const u32 pressed = (newButtons ^ oldButtons) & newButtons; // Pressed buttons + const u32 released = (newButtons ^ oldButtons) & oldButtons; // Released buttons + oldButtons = newButtons; + + writeSharedMem(padEntryOffset, newButtons); + writeSharedMem(padEntryOffset + 4, pressed); + writeSharedMem(padEntryOffset + 8, released); + writeSharedMem(padEntryOffset + 12, circlePadX); + writeSharedMem(padEntryOffset + 14, circlePadY); + + // Next, update touchscreen state + if (nextTouchscreenIndex == 0) { + writeSharedMem(0xB0, readSharedMem(0xA8)); // Copy previous tick count + writeSharedMem(0xA8, currentTick); // Write new tick count + } + writeSharedMem(0xB8, nextTouchscreenIndex); // Index last updated by the HID module + nextTouchscreenIndex = (nextTouchscreenIndex + 1) % 8; // Move to next entry + + // Next, update accelerometer state + if (nextAccelerometerIndex == 0) { + writeSharedMem(0x110, readSharedMem(0x108)); // Copy previous tick count + writeSharedMem(0x108, currentTick); // Write new tick count + } + writeSharedMem(0x118, nextAccelerometerIndex); // Index last updated by the HID module + nextAccelerometerIndex = (nextAccelerometerIndex + 1) % 8; // Move to next entry + + // Next, update gyro state + if (nextGyroIndex == 0) { + writeSharedMem(0x160, readSharedMem(0x158)); // Copy previous tick count + writeSharedMem(0x158, currentTick); // Write new tick count + } + writeSharedMem(0x168, nextGyroIndex); // Index last updated by the HID module + nextGyroIndex = (nextGyroIndex + 1) % 32; // Move to next entry + } -// TODO: We don't currently have inputs but we must at least try to signal the HID key input events now and then -void HIDService::updateInputs() { // For some reason, the original developers decided to signal the HID events each time the OS rescanned inputs // Rather than once every time the state of a key, or the accelerometer state, etc is updated // This means that the OS will signal the events even if literally nothing happened diff --git a/src/emulator.cpp b/src/emulator.cpp index 19fdcd82..9d274ebf 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -95,7 +95,7 @@ void Emulator::run() { } // Update inputs in the HID module - srv.updateInputs(); + srv.updateInputs(cpu.getTicks()); SDL_GL_SwapWindow(window); } } From 560b53eb42d95a2177804ba044f6ba131ab3c09b Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Tue, 6 Jun 2023 02:14:57 +0300 Subject: [PATCH 5/6] Update readme (we have inputs now :sunglasses:) --- readme.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/readme.md b/readme.md index a7e75f22..a3b2b37a 100644 --- a/readme.md +++ b/readme.md @@ -5,9 +5,7 @@ Panda3DS is an HLE, red-panda-themed Nintendo 3DS emulator written in C++ which ![screenshot1](docs/img/MK7_Car_Select.png) ![screenshot2](docs/img/OoT_Title.png) ![screenshot3](docs/img/Mayro.png) # Compatibility -Panda3DS is still in the early stages of development. Many games boot, many don't. Most games have at least some hilariously broken graphics, audio is not supported, performance leaves a bit to be desired mainly thanks to lack of shader acceleration, and most QoL features (including input, or a GUI!) are missing. - -In fact, the screenshots in the repo were created after I hooked the input state to rand() locally. +Panda3DS is still in the early stages of development. Many games boot, many don't. Most games have at least some hilariously broken graphics, audio is not supported, performance leaves a bit to be desired mainly thanks to lack of shader acceleration, and most QoL features (including a GUI) are missing. In addition, some games don't quiiite work with the upstream code. A lot of them might need some panics in the source code to be commented out before they work, etc. However, just the fact things can work as well as they do now is promising in itself. From afb577487c089d3852b38b24e64f429acab06ece Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Tue, 6 Jun 2023 18:15:27 +0300 Subject: [PATCH 6/6] Maybe fix Mac build --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fc6fe2a..44cbd873 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,8 @@ include_directories(${SDL2_INCLUDE_DIR}) set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/third_party/boost") set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/third_party/boost") set(Boost_NO_SYSTEM_PATHS ON) +add_compile_definitions(BOOST_NO_CXX98_FUNCTION_BASE) # Forbid Boost from using std::unary_function (Fixes MacOS build) + add_library(boost INTERFACE) target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR})