mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
Update DSP semaphore on semaphore event signal
Fixes Pokemon X and other DSP-needy games...
This commit is contained in:
parent
d3dc9e2f71
commit
f58354af06
7 changed files with 53 additions and 15 deletions
|
@ -79,7 +79,7 @@ namespace Audio {
|
||||||
|
|
||||||
u16 recvData(u32 regId) override { return teakra.RecvData(regId); }
|
u16 recvData(u32 regId) override { return teakra.RecvData(regId); }
|
||||||
bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); }
|
bool recvDataIsReady(u32 regId) override { return teakra.RecvDataIsReady(regId); }
|
||||||
void setSemaphore(u16 value) override { return teakra.SetSemaphore(value); }
|
void setSemaphore(u16 value) override { teakra.SetSemaphore(value); }
|
||||||
void setSemaphoreMask(u16 value) override { teakra.MaskSemaphore(value); }
|
void setSemaphoreMask(u16 value) override { teakra.MaskSemaphore(value); }
|
||||||
|
|
||||||
void writeProcessPipe(u32 channel, u32 size, u32 buffer) override;
|
void writeProcessPipe(u32 channel, u32 size, u32 buffer) override;
|
||||||
|
|
|
@ -66,14 +66,19 @@ class Kernel {
|
||||||
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
|
Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Handle makeEvent(ResetType resetType); // Needs to be public to be accessible to the APT/HID services
|
// Needs to be public to be accessible to the APT/HID services
|
||||||
Handle makeMutex(bool locked = false); // Needs to be public to be accessible to the APT/DSP services
|
Handle makeEvent(ResetType resetType, Event::CallbackType callback = Event::CallbackType::None);
|
||||||
Handle makeSemaphore(u32 initialCount, u32 maximumCount); // Needs to be public to be accessible to the service manager port
|
// Needs to be public to be accessible to the APT/DSP services
|
||||||
|
Handle makeMutex(bool locked = false);
|
||||||
|
// Needs to be public to be accessible to the service manager port
|
||||||
|
Handle makeSemaphore(u32 initialCount, u32 maximumCount);
|
||||||
Handle makeTimer(ResetType resetType);
|
Handle makeTimer(ResetType resetType);
|
||||||
void pollTimers();
|
void pollTimers();
|
||||||
|
|
||||||
// Signals an event, returns true on success or false if the event does not exist
|
// Signals an event, returns true on success or false if the event does not exist
|
||||||
bool signalEvent(Handle e);
|
bool signalEvent(Handle e);
|
||||||
|
// Run the callback for "special" events that have callbacks
|
||||||
|
void runEventCallback(Event::CallbackType callback);
|
||||||
|
|
||||||
void clearEvent(Handle e) {
|
void clearEvent(Handle e) {
|
||||||
KernelObject* object = getObject(e, KernelObjectType::Event);
|
KernelObject* object = getObject(e, KernelObjectType::Event);
|
||||||
|
|
|
@ -62,11 +62,19 @@ struct Process {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
|
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
|
||||||
|
// This enum stores what kind of callback they should execute
|
||||||
|
enum class CallbackType : u32 {
|
||||||
|
None, DSPSemaphore,
|
||||||
|
};
|
||||||
|
|
||||||
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
||||||
ResetType resetType = ResetType::OneShot;
|
ResetType resetType = ResetType::OneShot;
|
||||||
|
CallbackType callback = CallbackType::None;
|
||||||
bool fired = false;
|
bool fired = false;
|
||||||
|
|
||||||
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
||||||
|
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Port {
|
struct Port {
|
||||||
|
|
|
@ -27,6 +27,7 @@ class DSPService {
|
||||||
DSPEvent interrupt0;
|
DSPEvent interrupt0;
|
||||||
DSPEvent interrupt1;
|
DSPEvent interrupt1;
|
||||||
std::array<DSPEvent, pipeCount> pipeEvents;
|
std::array<DSPEvent, pipeCount> pipeEvents;
|
||||||
|
u16 semaphoreMask = 0;
|
||||||
|
|
||||||
DSPEvent& getEventRef(u32 type, u32 pipe);
|
DSPEvent& getEventRef(u32 type, u32 pipe);
|
||||||
static constexpr size_t maxEventCount = 6;
|
static constexpr size_t maxEventCount = 6;
|
||||||
|
@ -56,6 +57,9 @@ public:
|
||||||
void handleSyncRequest(u32 messagePointer);
|
void handleSyncRequest(u32 messagePointer);
|
||||||
void setDSPCore(Audio::DSPCore* pointer) { dsp = pointer; }
|
void setDSPCore(Audio::DSPCore* pointer) { dsp = pointer; }
|
||||||
|
|
||||||
|
// Special callback that's ran when the semaphore event is signalled
|
||||||
|
void onSemaphoreEventSignal() { dsp->setSemaphore(semaphoreMask); }
|
||||||
|
|
||||||
enum class SoundOutputMode : u8 {
|
enum class SoundOutputMode : u8 {
|
||||||
Mono = 0,
|
Mono = 0,
|
||||||
Stereo = 1,
|
Stereo = 1,
|
||||||
|
|
|
@ -38,16 +38,20 @@ TeakraDSP::TeakraDSP(Memory& mem, DSPService& dspService) : DSPCore(mem, dspServ
|
||||||
// Set up callbacks for Teakra
|
// Set up callbacks for Teakra
|
||||||
Teakra::AHBMCallback ahbm;
|
Teakra::AHBMCallback ahbm;
|
||||||
|
|
||||||
ahbm.read8 = [&](u32 addr) -> u8 { return mem.read8(addr); };
|
// The AHBM read handlers read from paddrs rather than vaddrs which mem.read8 and the like use
|
||||||
ahbm.read16 = [&](u32 addr) -> u16 { return mem.read16(addr); };
|
// TODO: When we implement more efficient paddr accesses with a page table or similar, these handlers
|
||||||
ahbm.read32 = [&](u32 addr) -> u32 { return mem.read32(addr); };
|
// Should be made to properly use it, since this method is hacky and will segfault if given an invalid addr
|
||||||
|
ahbm.read8 = [&](u32 addr) -> u8 { return mem.getFCRAM()[addr - PhysicalAddrs::FCRAM]; };
|
||||||
|
ahbm.read16 = [&](u32 addr) -> u16 { return *(u16*)&mem.getFCRAM()[addr - PhysicalAddrs::FCRAM]; };
|
||||||
|
ahbm.read32 = [&](u32 addr) -> u32 { return *(u32*)&mem.getFCRAM()[addr - PhysicalAddrs::FCRAM]; };
|
||||||
|
|
||||||
ahbm.write8 = [&](u32 addr, u8 value) { mem.write8(addr, value); };
|
ahbm.write8 = [&](u32 addr, u8 value) { mem.getFCRAM()[addr - PhysicalAddrs::FCRAM] = value; };
|
||||||
ahbm.write16 = [&](u32 addr, u16 value) { mem.write16(addr, value); };
|
ahbm.write16 = [&](u32 addr, u16 value) { *(u16*)&mem.getFCRAM()[addr - PhysicalAddrs::FCRAM] = value; };
|
||||||
ahbm.write32 = [&](u32 addr, u32 value) { mem.write32(addr, value); };
|
ahbm.write32 = [&](u32 addr, u32 value) { *(u32*)&mem.getFCRAM()[addr - PhysicalAddrs::FCRAM] = value; };
|
||||||
|
|
||||||
teakra.SetAHBMCallback(ahbm);
|
teakra.SetAHBMCallback(ahbm);
|
||||||
teakra.SetAudioCallback([=](std::array<s16, 2> sample) {
|
teakra.SetAudioCallback([=](std::array<s16, 2> sample) {
|
||||||
|
//printf("%d %d\n", sample[0], sample[1]);
|
||||||
// NOP for now
|
// NOP for now
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ const char* Kernel::resetTypeToString(u32 type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle Kernel::makeEvent(ResetType resetType) {
|
Handle Kernel::makeEvent(ResetType resetType, Event::CallbackType callback) {
|
||||||
Handle ret = makeObject(KernelObjectType::Event);
|
Handle ret = makeObject(KernelObjectType::Event);
|
||||||
objects[ret].data = new Event(resetType);
|
objects[ret].data = new Event(resetType, callback);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@ bool Kernel::signalEvent(Handle handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rescheduleThreads();
|
rescheduleThreads();
|
||||||
|
// Run the callback for events that require a special callback
|
||||||
|
if (event->callback != Event::CallbackType::None) [[unlikely]] {
|
||||||
|
runEventCallback(event->callback);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,3 +236,11 @@ void Kernel::waitSynchronizationN() {
|
||||||
Helpers::panic("WaitSynchronizationN with waitAll");
|
Helpers::panic("WaitSynchronizationN with waitAll");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kernel::runEventCallback(Event::CallbackType callback) {
|
||||||
|
switch (callback) {
|
||||||
|
case Event::CallbackType::None: break;
|
||||||
|
case Event::CallbackType::DSPSemaphore: serviceManager.getDSP().onSemaphoreEventSignal(); break;
|
||||||
|
default: Helpers::panic("Unimplemented special callback for kernel event!"); break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ namespace Result {
|
||||||
|
|
||||||
void DSPService::reset() {
|
void DSPService::reset() {
|
||||||
totalEventCount = 0;
|
totalEventCount = 0;
|
||||||
|
semaphoreMask = 0;
|
||||||
|
|
||||||
semaphoreEvent = std::nullopt;
|
semaphoreEvent = std::nullopt;
|
||||||
interrupt0 = std::nullopt;
|
interrupt0 = std::nullopt;
|
||||||
|
@ -83,6 +84,7 @@ void DSPService::loadComponent(u32 messagePointer) {
|
||||||
for (u32 i = 0; i < size; i++) {
|
for (u32 i = 0; i < size; i++) {
|
||||||
data[i] = mem.read8(buffer + i);
|
data[i] = mem.read8(buffer + i);
|
||||||
}
|
}
|
||||||
|
printf("Loado compartment: %08X %08X %08X %08X\n", data[0], data[1], data[2], data[3]);
|
||||||
|
|
||||||
log("DSP::LoadComponent (size = %08X, program mask = %X, data mask = %X\n", size, programMask, dataMask);
|
log("DSP::LoadComponent (size = %08X, program mask = %X, data mask = %X\n", size, programMask, dataMask);
|
||||||
dsp->loadComponent(data, programMask, dataMask);
|
dsp->loadComponent(data, programMask, dataMask);
|
||||||
|
@ -200,7 +202,7 @@ void DSPService::getSemaphoreEventHandle(u32 messagePointer) {
|
||||||
log("DSP::GetSemaphoreEventHandle\n");
|
log("DSP::GetSemaphoreEventHandle\n");
|
||||||
|
|
||||||
if (!semaphoreEvent.has_value()) {
|
if (!semaphoreEvent.has_value()) {
|
||||||
semaphoreEvent = kernel.makeEvent(ResetType::OneShot);
|
semaphoreEvent = kernel.makeEvent(ResetType::OneShot, Event::CallbackType::DSPSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x16, 1, 2));
|
mem.write32(messagePointer, IPC::responseHeader(0x16, 1, 2));
|
||||||
|
@ -224,6 +226,8 @@ void DSPService::setSemaphoreMask(u32 messagePointer) {
|
||||||
log("DSP::SetSemaphoreMask(mask = %04X)\n", mask);
|
log("DSP::SetSemaphoreMask(mask = %04X)\n", mask);
|
||||||
|
|
||||||
dsp->setSemaphoreMask(mask);
|
dsp->setSemaphoreMask(mask);
|
||||||
|
semaphoreMask = mask;
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x17, 1, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x17, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue