mikage-dev/source/processes/pdn.cpp
2024-03-08 10:54:13 +01:00

136 lines
5 KiB
C++

#include "pdn.hpp"
#include <framework/exceptions.hpp>
#include <teakra/teakra.h>
extern Teakra::Teakra* g_teakra; // TODO: Remove
namespace HLE {
namespace OS {
const uint32_t session_limit = 1;
struct FakePDN final {
spdlog::logger& logger;
public:
FakePDN(FakeThread& thread);
void ServiceThread( FakeThread& thread, const char* service_name,
decltype(ServiceHelper::SendReply) (*command_handler)(FakeThread&, FakePDN&, const IPC::CommandHeader&));
};
static decltype(ServiceHelper::SendReply) CommandHandlerD(FakeThread& thread, FakePDN&, const IPC::CommandHeader& header) {
using ResetDSP = IPC::IPCCommand<0x1>::add_uint32::add_uint32::add_uint32::response;
switch (header.command_id) {
case ResetDSP::id:
{
uint32_t enable = thread.ReadTLS(0x84);
uint32_t reset = thread.ReadTLS(0x88);
if (!enable) {
// TODO: What to do here?
// TODO: Do we still need to reset the DSP if the corresponding flag is set?
// g_dsp_running = false;
}
if (reset) {
// Memory::WriteLegacy<uint16_t>(thread.GetOS().setup.mem, Memory::IO_DSP2::start + 0x8, 1);
// Memory::WriteLegacy<uint16_t>(thread.GetOS().setup.mem, Memory::IO_DSP2::start + 0x8, 0);
// TODO: Reset via MMIO control register instead
// std::vector<std::uint8_t> temp(0x80000);
// memcpy(temp.data(), g_teakra->GetDspMemory().data(), temp.size());
// g_teakra->Reset();
// memcpy(g_teakra->GetDspMemory().data(), temp.data(), temp.size());
// // TODO: Shouldn't need to sync memory here
// for (uint32_t word_index = 0; word_index < Memory::DSP::size / sizeof(uint16_t); ++word_index) {
// g_teakra->ProgramWrite(word_index, Memory::ReadLegacy<uint16_t>(thread.GetOS().setup.mem, Memory::DSP::start + word_index * sizeof(uint16_t)));
// }
// if (enable) {
// g_dsp_running = true; // TODO: Remove
// g_dsp_just_reset = true;
// }
}
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0, 1, 0).raw);
thread.WriteTLS(0x84, RESULT_OK);
break;
}
default:
throw Mikage::Exceptions::NotImplemented("Unknown pdn:d command request with header {:#010x}", header.raw);
}
return ServiceHelper::SendReply;
}
static decltype(ServiceHelper::SendReply) CommandHandlerI(FakeThread&, FakePDN&, const IPC::CommandHeader& header) {
switch (header.command_id) {
default:
throw Mikage::Exceptions::NotImplemented("Unknown pdn:i command request with header {:#010x}", header.raw);
}
return ServiceHelper::SendReply;
}
static decltype(ServiceHelper::SendReply) CommandHandlerG(FakeThread& thread, FakePDN& context, const IPC::CommandHeader& header) {
switch (header.command_id) {
case IPC::IPCCommand<0x1>::add_uint32::add_uint32::add_uint32::id:
{
context.logger.info("{}received command 0x1", ThreadPrinter{thread});
thread.WriteTLS(0x80, IPC::CommandHeader::Make(0, 1, 0).raw);
thread.WriteTLS(0x84, RESULT_OK);
break;
}
default:
throw Mikage::Exceptions::NotImplemented("Unknown pdn:g command request with header {:#010x}", header.raw);
}
return ServiceHelper::SendReply;
}
void FakePDN::ServiceThread(FakeThread& thread, const char* service_name, decltype(ServiceHelper::SendReply) (*command_handler)(FakeThread&, FakePDN&, const IPC::CommandHeader&)) {
ServiceHelper service;
service.Append(ServiceUtil::SetupService(thread, service_name, session_limit));
auto InvokeCommandHandler = [&](FakeThread& thread, uint32_t /*signalled_handle_index*/) {
Platform::IPC::CommandHeader header = { thread.ReadTLS(0x80) };
return command_handler(thread, *this, header);
};
service.Run(thread, std::move(InvokeCommandHandler));
}
FakePDN::FakePDN(FakeThread& thread)
: logger(*thread.GetLogger()) {
{
auto new_thread = std::make_shared<WrappedFakeThread>( thread.GetParentProcess(),
[this](FakeThread& thread) { ServiceThread(thread, "pdn:d", CommandHandlerD); });
new_thread->name = "pdn:dThread";
thread.GetParentProcess().AttachThread(new_thread);
}
{
auto new_thread = std::make_shared<WrappedFakeThread>( thread.GetParentProcess(),
[this](FakeThread& thread) { ServiceThread(thread, "pdn:i", CommandHandlerI); });
new_thread->name = "pdn:iThread";
thread.GetParentProcess().AttachThread(new_thread);
}
thread.name = "pdn:gThread";
ServiceThread(thread, "pdn:g", CommandHandlerG);
}
template<> std::shared_ptr<WrappedFakeProcess> CreateFakeProcessViaContext<FakePDN>(OS& os, Interpreter::Setup& setup, uint32_t pid, const std::string& name) {
return WrappedFakeProcess::CreateWithContext<FakePDN>(os, setup, pid, name);
}
} // namespace OS
} // namespace HLE