diff --git a/include/services/mic.hpp b/include/services/mic.hpp index e193db1c..508e9bbc 100644 --- a/include/services/mic.hpp +++ b/include/services/mic.hpp @@ -5,13 +5,19 @@ #include "memory.hpp" #include "result/result.hpp" +// Circular dependencies, yay +class Kernel; + class MICService { Handle handle = KernelHandles::MIC; Memory& mem; + Kernel& kernel; MAKE_LOG_FUNCTION(log, micLogger) // Service commands + void getEventHandle(u32 messagePointer); void getGain(u32 messagePointer); + void isSampling(u32 messagePointer); void mapSharedMem(u32 messagePointer); void setClamp(u32 messagePointer); void setGain(u32 messagePointer); @@ -19,15 +25,18 @@ class MICService { void setPower(u32 messagePointer); void startSampling(u32 messagePointer); void stopSampling(u32 messagePointer); + void unmapSharedMem(u32 messagePointer); void theCaptainToadFunction(u32 messagePointer); u8 gain = 0; // How loud our microphone input signal is bool micEnabled = false; bool shouldClamp = false; - bool isSampling = false; + bool currentlySampling = false; + + std::optional eventHandle; public: - MICService(Memory& mem) : mem(mem) {} + MICService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); void handleSyncRequest(u32 messagePointer); }; \ No newline at end of file diff --git a/src/core/services/mic.cpp b/src/core/services/mic.cpp index 055f5c1d..d3336c5f 100644 --- a/src/core/services/mic.cpp +++ b/src/core/services/mic.cpp @@ -1,11 +1,15 @@ #include "services/mic.hpp" #include "ipc.hpp" +#include "kernel/kernel.hpp" namespace MICCommands { enum : u32 { MapSharedMem = 0x00010042, + UnmapSharedMem = 0x00020000, StartSampling = 0x00030140, StopSampling = 0x00050000, + IsSampling = 0x00060000, + GetEventHandle = 0x00070000, SetGain = 0x00080040, GetGain = 0x00090000, SetPower = 0x000A0040, @@ -18,14 +22,18 @@ namespace MICCommands { void MICService::reset() { micEnabled = false; shouldClamp = false; - isSampling = false; + currentlySampling = false; gain = 0; + + eventHandle = std::nullopt; } void MICService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { + case MICCommands::GetEventHandle: getEventHandle(messagePointer); break; case MICCommands::GetGain: getGain(messagePointer); break; + case MICCommands::IsSampling: isSampling(messagePointer); break; case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break; case MICCommands::SetClamp: setClamp(messagePointer); break; case MICCommands::SetGain: setGain(messagePointer); break; @@ -33,6 +41,7 @@ void MICService::handleSyncRequest(u32 messagePointer) { case MICCommands::SetPower: setPower(messagePointer); break; case MICCommands::StartSampling: startSampling(messagePointer); break; case MICCommands::StopSampling: stopSampling(messagePointer); break; + case MICCommands::UnmapSharedMem: unmapSharedMem(messagePointer); break; case MICCommands::CaptainToadFunction: theCaptainToadFunction(messagePointer); break; default: Helpers::panic("MIC service requested. Command: %08X\n", command); } @@ -47,6 +56,27 @@ void MICService::mapSharedMem(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); } +void MICService::unmapSharedMem(u32 messagePointer) { + log("MIC::UnmapSharedMem (stubbed)\n"); + + mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); +} + +void MICService::getEventHandle(u32 messagePointer) { + log("MIC::GetEventHandle\n"); + Helpers::warn("Acquire MIC event handle"); + + if (!eventHandle.has_value()) { + eventHandle = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer, IPC::responseHeader(0x7, 1, 2)); + mem.write32(messagePointer + 4, Result::Success); + // TODO: Translation descriptor + mem.write32(messagePointer + 12, eventHandle.value()); +} + void MICService::getGain(u32 messagePointer) { log("MIC::GetGain\n"); mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0)); @@ -91,19 +121,27 @@ void MICService::startSampling(u32 messagePointer) { encoding, sampleRate, offset, dataSize, loop ? "yes" : "no" ); - isSampling = true; + currentlySampling = true; mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 0)); mem.write32(messagePointer + 4, Result::Success); } void MICService::stopSampling(u32 messagePointer) { log("MIC::StopSampling\n"); - isSampling = false; + currentlySampling = false; mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0)); mem.write32(messagePointer + 4, Result::Success); } +void MICService::isSampling(u32 messagePointer) { + log("MIC::IsSampling"); + + mem.write32(messagePointer, IPC::responseHeader(0x6, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write8(messagePointer + 8, currentlySampling ? 1 : 0); +} + void MICService::setIirFilter(u32 messagePointer) { const u32 size = mem.read32(messagePointer + 4); const u32 pointer = mem.read32(messagePointer + 12); diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 2f196362..cb93b627 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -8,7 +8,7 @@ ServiceManager::ServiceManager(std::span regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config) : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel), - gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem), + gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem), news_u(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {} static constexpr int MAX_NOTIFICATION_COUNT = 16;