mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 14:15:41 +12:00
Make DSP backends properly configurable
This commit is contained in:
parent
33eb096ef8
commit
7a5bb2859e
8 changed files with 58 additions and 7 deletions
|
@ -2,15 +2,17 @@
|
|||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "helpers.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
// The DSP core must have access to the DSP service to be able to trigger interrupts properly
|
||||
class DSPService;
|
||||
class Memory;
|
||||
|
||||
namespace Audio {
|
||||
// There are 160 stereo samples in 1 audio frame, so 320 samples total
|
||||
|
@ -44,6 +46,9 @@ namespace Audio {
|
|||
virtual void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) = 0;
|
||||
virtual void unloadComponent() = 0;
|
||||
virtual void setSemaphoreMask(u16 value) = 0;
|
||||
|
||||
static Audio::DSPCore::Type typeFromString(std::string inString);
|
||||
static const char* typeToString(Audio::DSPCore::Type type);
|
||||
};
|
||||
|
||||
std::unique_ptr<DSPCore> makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include <array>
|
||||
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
namespace Audio {
|
||||
class NullDSP : public DSPCore {
|
||||
|
@ -27,7 +29,7 @@ namespace Audio {
|
|||
u8* getDspMemory() override { return dspRam.data(); }
|
||||
|
||||
u16 recvData(u32 regId) override;
|
||||
bool recvDataIsReady(u32 regId) override { return true; } // Treat data as always ready
|
||||
bool recvDataIsReady(u32 regId) override { return true; } // Treat data as always ready
|
||||
void writeProcessPipe(u32 channel, u32 size, u32 buffer) override;
|
||||
std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) override;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "swap.hpp"
|
||||
#include "teakra/teakra.h"
|
||||
|
||||
|
@ -35,9 +36,9 @@ namespace Audio {
|
|||
bool isFull() const { return (readPointer ^ writePointer) == wrapBit; }
|
||||
bool isEmpty() const { return (readPointer ^ writePointer) == 0; }
|
||||
|
||||
// isWrapped: Are read and write pointers in different memory passes.
|
||||
// true: xxxx]----[xxxx (data is wrapping around the end of memory)
|
||||
// false: ----[xxxx]----
|
||||
// isWrapped: Are read and write pointers in different memory passes.
|
||||
// true: xxxx]----[xxxx (data is wrapping around the end of memory)
|
||||
// false: ----[xxxx]----
|
||||
bool isWrapped() const { return (readPointer ^ writePointer) >= wrapBit; }
|
||||
};
|
||||
static_assert(sizeof(PipeStatus) == 10, "Teakra: Pipe Status size is wrong");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <filesystem>
|
||||
|
||||
#include "audio/dsp_core.hpp"
|
||||
#include "renderer.hpp"
|
||||
|
||||
// Remember to initialize every field here to its default value otherwise bad things will happen
|
||||
|
@ -15,6 +16,7 @@ struct EmulatorConfig {
|
|||
bool shaderJitEnabled = shaderJitDefault;
|
||||
bool discordRpcEnabled = false;
|
||||
RendererType rendererType = RendererType::OpenGL;
|
||||
Audio::DSPCore::Type dspType = Audio::DSPCore::Type::Null;
|
||||
|
||||
bool sdCardInserted = true;
|
||||
bool sdWriteProtected = false;
|
||||
|
|
|
@ -62,6 +62,16 @@ void EmulatorConfig::load() {
|
|||
}
|
||||
}
|
||||
|
||||
if (data.contains("Audio")) {
|
||||
auto audioResult = toml::expect<toml::value>(data.at("Audio"));
|
||||
if (audioResult.is_ok()) {
|
||||
auto audio = audioResult.unwrap();
|
||||
|
||||
auto dspCoreName = toml::find_or<std::string>(audio, "DSPEmulation", "Null");
|
||||
dspType = Audio::DSPCore::typeFromString(dspCoreName);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.contains("Battery")) {
|
||||
auto batteryResult = toml::expect<toml::value>(data.at("Battery"));
|
||||
if (batteryResult.is_ok()) {
|
||||
|
@ -109,6 +119,7 @@ void EmulatorConfig::save() {
|
|||
data["General"]["UsePortableBuild"] = usePortableBuild;
|
||||
data["GPU"]["EnableShaderJIT"] = shaderJitEnabled;
|
||||
data["GPU"]["Renderer"] = std::string(Renderer::typeToString(rendererType));
|
||||
data["Audio"]["DSPEmulation"] = std::string(Audio::DSPCore::typeToString(dspType));
|
||||
|
||||
data["Battery"]["ChargerPlugged"] = chargerPlugged;
|
||||
data["Battery"]["BatteryPercentage"] = batteryPercentage;
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include "audio/null_core.hpp"
|
||||
#include "audio/teakra_core.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <unordered_map>
|
||||
|
||||
std::unique_ptr<Audio::DSPCore> Audio::makeDSPCore(DSPCore::Type type, Memory& mem, Scheduler& scheduler, DSPService& dspService) {
|
||||
std::unique_ptr<DSPCore> core;
|
||||
|
||||
|
@ -19,3 +23,30 @@ std::unique_ptr<Audio::DSPCore> Audio::makeDSPCore(DSPCore::Type type, Memory& m
|
|||
mem.setDSPMem(core->getDspMemory());
|
||||
return core;
|
||||
}
|
||||
|
||||
Audio::DSPCore::Type Audio::DSPCore::typeFromString(std::string inString) {
|
||||
// Transform to lower-case to make the setting case-insensitive
|
||||
std::transform(inString.begin(), inString.end(), inString.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
static const std::unordered_map<std::string, Audio::DSPCore::Type> map = {
|
||||
{"null", Audio::DSPCore::Type::Null},
|
||||
{"none", Audio::DSPCore::Type::Null},
|
||||
{"lle", Audio::DSPCore::Type::Teakra},
|
||||
{"teakra", Audio::DSPCore::Type::Teakra},
|
||||
};
|
||||
|
||||
if (auto search = map.find(inString); search != map.end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
printf("Invalid DSP type. Defaulting to null\n");
|
||||
return Audio::DSPCore::Type::Null;
|
||||
}
|
||||
|
||||
const char* Audio::DSPCore::typeToString(Audio::DSPCore::Type type) {
|
||||
switch (type) {
|
||||
case Audio::DSPCore::Type::Null: return "null";
|
||||
case Audio::DSPCore::Type::Teakra: return "teakra";
|
||||
default: return "invalid";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ void DSPService::loadComponent(u32 messagePointer) {
|
|||
for (u32 i = 0; i < size; 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);
|
||||
dsp->loadComponent(data, programMask, dataMask);
|
||||
|
|
|
@ -26,7 +26,7 @@ Emulator::Emulator()
|
|||
{
|
||||
DSPService& dspService = kernel.getServiceManager().getDSP();
|
||||
|
||||
dsp = Audio::makeDSPCore(Audio::DSPCore::Type::Teakra, memory, scheduler, dspService);
|
||||
dsp = Audio::makeDSPCore(config.dspType, memory, scheduler, dspService);
|
||||
dspService.setDSPCore(dsp.get());
|
||||
|
||||
#ifdef PANDA3DS_ENABLE_DISCORD_RPC
|
||||
|
|
Loading…
Add table
Reference in a new issue