Revert "Audio Core (#2)"

This reverts commit a8d0c51c69.
This commit is contained in:
Dragios
2016-04-16 01:32:48 +08:00
parent 69effbcb6e
commit 28f64f98f7
65 changed files with 52 additions and 8680 deletions

View File

@@ -20,55 +20,29 @@ namespace DSP_DSP {
static u32 read_pipe_count;
static Kernel::SharedPtr<Kernel::Event> semaphore_event;
enum class InterruptType {
Zero = 0, // Unknown purpose. Channel is always zero.
One = 1, // Unknown purpose. Channel is always zero.
Pipe = 2, // Related to a pipe
MAX
};
constexpr size_t InterruptType_MAX = static_cast<size_t>(InterruptType::MAX);
/// Map of (interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents
static std::array<std::unordered_map<u32, Kernel::SharedPtr<Kernel::Event>>, InterruptType_MAX> interrupt_events;
constexpr size_t max_number_of_interrupt_events = 6;
size_t GetNumberOfRegisteredEvents() {
size_t number = 0;
for (const auto& events : interrupt_events) {
number += events.size();
struct PairHash {
template <typename T, typename U>
std::size_t operator()(const std::pair<T, U> &x) const {
// TODO(yuriks): Replace with better hash combining function.
return std::hash<T>()(x.first) ^ std::hash<U>()(x.second);
}
return number;
}
};
/// Map of (audio interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents
static std::unordered_map<std::pair<u32, u32>, Kernel::SharedPtr<Kernel::Event>, PairHash> interrupt_events;
// DSP Interrupts:
// Interrupt (2, 2) occurs every frame tick. Userland programs normally have a thread that's waiting
// Interrupt #2 occurs every frame tick. Userland programs normally have a thread that's waiting
// for an interrupt event. Immediately after this interrupt event, userland normally updates the
// state in the next region and increments the relevant frame counter by two.
void SignalAllInterrupts() {
// HACK: The other interrupts have currently unknown purpose, we trigger them each tick in any case.
for (auto& events : interrupt_events)
for (auto& event : events)
event.second->Signal();
for (auto& interrupt_event : interrupt_events)
interrupt_event.second->Signal();
}
void SignalInterrupt(u32 interrupt, u32 channel) {
ASSERT(interrupt < interrupt_events.size());
if (interrupt == 0 || interrupt == 1)
ASSERT(channel == 0);
auto& events = interrupt_events[interrupt];
if (events.find(channel) != events.end()) {
events[channel]->Signal();
}
}
bool SemaphoreSignalled() {
if (semaphore_event->signaled) {
semaphore_event->Clear();
return true;
} else {
return false;
}
interrupt_events[std::make_pair(interrupt, channel)]->Signal();
}
/**
@@ -84,7 +58,6 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
u32 addr = cmd_buff[1];
cmd_buff[0] = 0xC0080;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
@@ -140,11 +113,9 @@ static void LoadComponent(Service::Interface* self) {
static void GetSemaphoreEventHandle(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[0] = 0x160042;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
@@ -186,47 +157,23 @@ static void FlushDataCache(Service::Interface* self) {
static void RegisterInterruptEvents(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 type_num = cmd_buff[1];
u32 interrupt = cmd_buff[1];
u32 channel = cmd_buff[2];
u32 event_handle = cmd_buff[4];
if (cmd_buff[3] != 0) {
cmd_buff[0] = 0x40;
cmd_buff[1] = 0xD9001830;
return;
}
InterruptType type = static_cast<InterruptType>(type_num);
if (type == InterruptType::Zero || type == InterruptType::One) {
channel = 0;
} else if (type == InterruptType::Pipe) {
if (channel >= DSP::HLE::DspPipe_MAX) {
LOG_ERROR(Service_DSP, "Invalid (type, channel) combination (%u, %u)", type, channel);
}
} else {
// I suspect that interrupt values greater than two are invalid.
LOG_ERROR(Service_DSP, "Unimplemented (type, channel) combination (%u, %u)", type, channel);
UNIMPLEMENTED();
}
cmd_buff[0] = 0x150040;
if (event_handle) {
auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
if (evt) {
if (GetNumberOfRegisteredEvents() < max_number_of_interrupt_events) {
interrupt_events[type_num][channel] = evt;
LOG_INFO(Service_DSP, "Registered type=%u, channel=%u, event_handle=0x%08X", type, channel, event_handle);
} else {
cmd_buff[1] = 0xC860A7FF;
LOG_ERROR(Service_DSP, "Ran out of space to register interrupts");
}
interrupt_events[std::make_pair(interrupt, channel)] = evt;
cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_INFO(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
} else {
LOG_CRITICAL(Service_DSP, "Invalid event handle! type=%u, channel=%u, event_handle=0x%08X", type, channel, event_handle);
LOG_CRITICAL(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
ASSERT(false); // This should really be handled at a IPC translation layer.
}
} else {
interrupt_events[type_num].erase(channel);
LOG_INFO(Service_DSP, "Unregistered type=%u, channel=%u, event_handle=0x%08X", type, channel, event_handle);
interrupt_events.erase(std::make_pair(interrupt, channel));
LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle);
}
}
@@ -240,13 +187,8 @@ static void RegisterInterruptEvents(Service::Interface* self) {
static void SetSemaphore(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[0] = 0x70040;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
// Observed Behaviour: Waits for DSP_PSEM to be clear then sets DSP_PSEM.
SignalAllInterrupts(); // This is a HACK
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
@@ -268,13 +210,7 @@ static void WriteProcessPipe(Service::Interface* self) {
u32 size = cmd_buff[2];
u32 buffer = cmd_buff[4];
if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) {
LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer);
cmd_buff[0] = 0x40;
cmd_buff[1] = 0xD9001830;
return;
}
ASSERT_MSG(IPC::StaticBufferDesc(size, 1) == cmd_buff[3], "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer);
ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
std::vector<u8> message(size);
@@ -285,7 +221,6 @@ static void WriteProcessPipe(Service::Interface* self) {
DSP::HLE::PipeWrite(pipe, message);
cmd_buff[0] = 0xD0040;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
@@ -315,14 +250,16 @@ static void ReadPipeIfPossible(Service::Interface* self) {
ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
cmd_buff[0] = 0x100082;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
Memory::WriteBlock(addr, response.data(), response.size());
Memory::WriteBlock(addr, response.data(), response.size());
cmd_buff[2] = static_cast<u32>(response.size());
cmd_buff[2] = static_cast<u32>(response.size());
} else {
cmd_buff[2] = 0; // Return no data
}
LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]);
}
@@ -396,7 +333,6 @@ static void SetSemaphoreMask(Service::Interface* self) {
u32 mask = cmd_buff[1];
cmd_buff[0] = 0x170040;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x%08X", mask);
@@ -414,11 +350,10 @@ static void SetSemaphoreMask(Service::Interface* self) {
static void GetHeadphoneStatus(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
cmd_buff[0] = 0x1F0080;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
cmd_buff[2] = 0; // Not using headphones?
LOG_TRACE(Service_DSP, "called");
LOG_WARNING(Service_DSP, "(STUBBED) called");
}
/**
@@ -441,7 +376,6 @@ static void RecvData(Service::Interface* self) {
// Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept.
cmd_buff[0] = 0x10080;
cmd_buff[1] = RESULT_SUCCESS.raw;
switch (DSP::HLE::GetDspState()) {
case DSP::HLE::DspState::On:
@@ -477,7 +411,6 @@ static void RecvDataIsReady(Service::Interface* self) {
ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
cmd_buff[0] = 0x20080;
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = 1; // Ready to read
@@ -532,8 +465,7 @@ Interface::Interface() {
Interface::~Interface() {
semaphore_event = nullptr;
for (auto& events : interrupt_events)
events.clear();
interrupt_events.clear();
}
} // namespace

View File

@@ -34,7 +34,4 @@ void SignalAllInterrupts();
*/
void SignalInterrupt(u32 interrupt_id, u32 channel_id);
/// Returns true it the application signalled the semaphore, then clears the semaphore.
bool SemaphoreSignalled();
} // namespace