From 64190988515e2ae3b1a0f94dcf4708ab8c68f0bb Mon Sep 17 00:00:00 2001
From: wheremyfoodat <gponiris2004@gmail.com>
Date: Sat, 29 Apr 2023 02:45:21 +0300
Subject: [PATCH] [HID] Implement events

---
 include/kernel/handles.hpp            |  6 ------
 include/kernel/kernel.hpp             |  1 +
 include/services/hid.hpp              | 12 +++++++++++-
 include/services/service_manager.hpp  |  1 +
 src/core/services/hid.cpp             | 21 +++++++++++++++------
 src/core/services/service_manager.cpp |  5 +++--
 src/emulator.cpp                      |  3 +++
 7 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/include/kernel/handles.hpp b/include/kernel/handles.hpp
index 32616c97..9b13460a 100644
--- a/include/kernel/handles.hpp
+++ b/include/kernel/handles.hpp
@@ -41,12 +41,6 @@ namespace KernelHandles {
 
 		MinSharedMemHandle = GSPSharedMemHandle,
 		MaxSharedMemHandle = HIDSharedMemHandle,
-
-		HIDEvent0,
-		HIDEvent1,
-		HIDEvent2,
-		HIDEvent3,
-		HIDEvent4
 	};
 
 	// Returns whether "handle" belongs to one of the OS services
diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp
index dd6ce745..95a6bf88 100644
--- a/include/kernel/kernel.hpp
+++ b/include/kernel/kernel.hpp
@@ -198,4 +198,5 @@ public:
 
 	void sendGPUInterrupt(GPUInterrupt type) { serviceManager.requestGPUInterrupt(type); }
 	void signalDSPEvents() { serviceManager.signalDSPEvents(); }
+	void updateInputs() { serviceManager.updateInputs(); }
 };
\ No newline at end of file
diff --git a/include/services/hid.hpp b/include/services/hid.hpp
index 7629da3b..8464cd48 100644
--- a/include/services/hid.hpp
+++ b/include/services/hid.hpp
@@ -1,17 +1,26 @@
 #pragma once
+#include <array>
+#include <optional>
 #include "helpers.hpp"
 #include "kernel_types.hpp"
 #include "logger.hpp"
 #include "memory.hpp"
 
+// Circular dependency because we need HID to spawn events
+class Kernel;
+
 class HIDService {
 	Handle handle = KernelHandles::HID;
 	Memory& mem;
+	Kernel& kernel;
 	u8* sharedMem = nullptr; // Pointer to HID shared memory
 
 	bool accelerometerEnabled;
+	bool eventsInitialized;
 	bool gyroEnabled;
 
+	std::array<std::optional<Handle>, 5> events;
+
 	MAKE_LOG_FUNCTION(log, hidLogger)
 
 	// Service commands
@@ -22,9 +31,10 @@ class HIDService {
 	void getIPCHandles(u32 messagePointer);
 
 public:
-	HIDService(Memory& mem) : mem(mem) {}
+	HIDService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
 	void reset();
 	void handleSyncRequest(u32 messagePointer);
+	void updateInputs();
 
 	void setSharedMem(u8* ptr) {
 		sharedMem = ptr;
diff --git a/include/services/service_manager.hpp b/include/services/service_manager.hpp
index 10d816c1..25e4d8f0 100644
--- a/include/services/service_manager.hpp
+++ b/include/services/service_manager.hpp
@@ -82,4 +82,5 @@ public:
 	void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); }
 
 	void signalDSPEvents() { dsp.signalEvents(); }
+	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 e3056f70..204d2afe 100644
--- a/src/core/services/hid.cpp
+++ b/src/core/services/hid.cpp
@@ -1,5 +1,6 @@
 #include "services/hid.hpp"
 #include "ipc.hpp"
+#include "kernel.hpp"
 #include <bit>
 
 namespace HIDCommands {
@@ -80,15 +81,23 @@ void HIDService::getGyroscopeCoefficient(u32 messagePointer) {
 
 void HIDService::getIPCHandles(u32 messagePointer) {
 	log("HID::GetIPCHandles\n");
+
+	// Initialize HID events
+	if (!eventsInitialized) {
+		eventsInitialized = true;
+
+		for (auto& e : events) {
+			e = kernel.makeEvent(ResetType::OneShot);
+		}
+	}
+
 	mem.write32(messagePointer, IPC::responseHeader(0xA, 1, 7));
 	mem.write32(messagePointer + 4, Result::Success); // Result code
 	mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
 	mem.write32(messagePointer + 12, KernelHandles::HIDSharedMemHandle); // Shared memory handle
 
-	// HID event handles
-	mem.write32(messagePointer + 16, KernelHandles::HIDEvent0);
-	mem.write32(messagePointer + 20, KernelHandles::HIDEvent1);
-	mem.write32(messagePointer + 24, KernelHandles::HIDEvent2);
-	mem.write32(messagePointer + 28, KernelHandles::HIDEvent3);
-	mem.write32(messagePointer + 32, KernelHandles::HIDEvent4);
+	// Write HID event handles
+	for (int i = 0; i < events.size(); i++) {
+		mem.write32(messagePointer + 16 + sizeof(Handle) * i, events[i].value());
+	}
 }
\ No newline at end of file
diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp
index 9ab529d3..8b14e5e1 100644
--- a/src/core/services/service_manager.cpp
+++ b/src/core/services/service_manager.cpp
@@ -5,8 +5,9 @@
 
 ServiceManager::ServiceManager(std::array<u32, 16>& regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel)
 	: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem),
-	cecd(mem, kernel), cfg(mem), dsp(mem, kernel), hid(mem), frd(mem), fs(mem, kernel), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem),
-	ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem), ptm(mem), y2r(mem, kernel) {}
+	cecd(mem, kernel), cfg(mem), dsp(mem, kernel), hid(mem, kernel), frd(mem), fs(mem, kernel),
+	gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem),
+	ptm(mem), y2r(mem, kernel) {}
 
 static constexpr int MAX_NOTIFICATION_COUNT = 16;
 
diff --git a/src/emulator.cpp b/src/emulator.cpp
index 7f0ded12..56e555c7 100644
--- a/src/emulator.cpp
+++ b/src/emulator.cpp
@@ -31,6 +31,9 @@ void Emulator::run() {
         kernel.sendGPUInterrupt(GPUInterrupt::VBlank0);
         kernel.sendGPUInterrupt(GPUInterrupt::VBlank1);
 
+        // Update inputs in the HID module
+        kernel.updateInputs();
+
         SDL_Event event;
         while (SDL_PollEvent(&event)) {
             if (event.type == SDL_QUIT) {