mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-09 15:01:00 +01:00
136 lines
5 KiB
C++
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
|