Make DSP emulation opt-in

This commit is contained in:
Tony Wasserka 2024-03-09 20:02:29 +01:00
parent efa3272b67
commit b094815ecb
5 changed files with 29 additions and 7 deletions

2
externals/teakra vendored

@ -1 +1 @@
Subproject commit ad99cb93dec7a042e3736d506783fb2dc1117851 Subproject commit 019d18c7ee137899030b378feca038cd7789a1b7

View file

@ -89,6 +89,10 @@ struct ShaderEngineTag : Config::OptionDefault<ShaderEngine> {
static constexpr const char* name = "ShaderEngine"; static constexpr const char* name = "ShaderEngine";
}; };
struct EnableAudioEmulation : Config::BooleanOption<EnableAudioEmulation> {
static constexpr const char* name = "EnableAudioEmulation";
};
struct Settings : Config::Options<CPUEngineTag, struct Settings : Config::Options<CPUEngineTag,
InitialApplicationTag, InitialApplicationTag,
@ -100,6 +104,7 @@ struct Settings : Config::Options<CPUEngineTag,
AttachToProcessOnStartup, AttachToProcessOnStartup,
AppMemType, AppMemType,
RendererTag, RendererTag,
ShaderEngineTag> { }; ShaderEngineTag,
EnableAudioEmulation> { };
} // namespace Settings } // namespace Settings

View file

@ -196,6 +196,7 @@ int main(int argc, char* argv[]) {
("shader_engine", bpo::value<Settings::ShaderEngine>()->default_value(Settings::ShaderEngineTag::default_value()), "Select which Shader engine to use (interpreter, bytecode, or glsl)") ("shader_engine", bpo::value<Settings::ShaderEngine>()->default_value(Settings::ShaderEngineTag::default_value()), "Select which Shader engine to use (interpreter, bytecode, or glsl)")
("enable_logging", bpo::bool_switch(&enable_logging), "Enable logging (slow!)") ("enable_logging", bpo::bool_switch(&enable_logging), "Enable logging (slow!)")
("bootstrap_nand", bpo::bool_switch(&bootstrap_nand), "Bootstrap NAND from game update partition") ("bootstrap_nand", bpo::bool_switch(&bootstrap_nand), "Bootstrap NAND from game update partition")
("enable_audio", bpo::bool_switch(), "Enable audio emulation (slow!)")
; ;
boost::program_options::positional_options_description p; boost::program_options::positional_options_description p;
@ -252,6 +253,8 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
settings.set<Settings::EnableAudioEmulation>(vm["enable_audio"].as<bool>());
if (vm.count("input")) { if (vm.count("input")) {
Settings::InitialApplicationTag::HostFile file{vm["input"].as<std::string>()}; Settings::InitialApplicationTag::HostFile file{vm["input"].as<std::string>()};
settings.set<Settings::InitialApplicationTag>({file}); settings.set<Settings::InitialApplicationTag>({file});

View file

@ -5432,6 +5432,17 @@ uint64_t OS::GetTimeInNanoSeconds() const {
static ticks dsp_tick; static ticks dsp_tick;
OS* g_os = nullptr; OS* g_os = nullptr;
static ticks GetDspTick(OS& os) {
if (os.settings.get<Settings::EnableAudioEmulation>()) {
// DSP clock rate is half the CPU clock rate
return os.system_tick / 2;
} else {
// Disabling DSP emulation entirely would break games.
// However we can safely underclock the DSP to save work.
return os.system_tick / 64;
}
}
void SetupOSDSPCallbacks(OS& os) { void SetupOSDSPCallbacks(OS& os) {
static auto dsp_interrupt_handlera = [&os]() { static auto dsp_interrupt_handlera = [&os]() {
fprintf(stderr, "DSP INTERRUPT0\n"); fprintf(stderr, "DSP INTERRUPT0\n");
@ -5457,7 +5468,7 @@ void SetupOSDSPCallbacks(OS& os) {
g_teakra->SetRecvDataHandler(2, dsp_interrupt_handlerc); g_teakra->SetRecvDataHandler(2, dsp_interrupt_handlerc);
g_teakra->SetSemaphoreHandler(dsp_interrupt_handler2); g_teakra->SetSemaphoreHandler(dsp_interrupt_handler2);
} }
dsp_tick = os.system_tick / 2; dsp_tick = GetDspTick(os);
} }
void OS::EnterExecutionLoop() { void OS::EnterExecutionLoop() {
@ -5479,7 +5490,7 @@ void OS::EnterExecutionLoop() {
// NotifyInterrupt(0x4a); // NotifyInterrupt(0x4a);
// }; // };
/*auto */dsp_tick = system_tick / 2; /*auto */dsp_tick = GetDspTick(*this);
while (!stop_requested) { while (!stop_requested) {
// TODO: Gather these from the "caller" (i.e. the coroutine) // TODO: Gather these from the "caller" (i.e. the coroutine)
@ -5492,20 +5503,20 @@ void OS::EnterExecutionLoop() {
// g_teakra->SetRecvDataHandler(1, dsp_interrupt_handlerb); // g_teakra->SetRecvDataHandler(1, dsp_interrupt_handlerb);
// g_teakra->SetRecvDataHandler(2, dsp_interrupt_handlerc); // g_teakra->SetRecvDataHandler(2, dsp_interrupt_handlerc);
// g_teakra->SetSemaphoreHandler(dsp_interrupt_handler2); // g_teakra->SetSemaphoreHandler(dsp_interrupt_handler2);
// dsp_tick = system_tick / 2; // dsp_tick = GetDspTick(*this);
// } // }
// Run DSP time slices of at least 100 ticks. // Run DSP time slices of at least 100 ticks.
// This number was carefully chosen, since too large minimum bounds // This number was carefully chosen, since too large minimum bounds
// trigger hangs. // trigger hangs.
auto dsp_tick_diff = system_tick / 2 - dsp_tick; auto dsp_tick_diff = GetDspTick(*this) - dsp_tick;
if (dsp_tick_diff.count() > 100) { if (dsp_tick_diff.count() > 100) {
// For profiling, present DSP emulation as one logical fiber // For profiling, present DSP emulation as one logical fiber
TracyFiberEnter("DSP"); TracyFiberEnter("DSP");
TracyCZoneN(DSPSliceZone, "DSPSlice", true); TracyCZoneN(DSPSliceZone, "DSPSlice", true);
// fprintf(stderr, "Running %d teakra cycles\n", (int)dsp_tick_diff.count()); // fprintf(stderr, "Running %d teakra cycles\n", (int)dsp_tick_diff.count());
g_teakra->Run(dsp_tick_diff.count()); g_teakra->Run(dsp_tick_diff.count());
dsp_tick = system_tick / 2; dsp_tick = GetDspTick(*this);
TracyCZoneEnd(DSPSliceZone); TracyCZoneEnd(DSPSliceZone);
TracyFiberLeave; TracyFiberLeave;
} }

View file

@ -35,4 +35,7 @@ Settings::Renderer OptionDefault<Settings::Renderer>::default_val = Settings::Re
template<> template<>
Settings::ShaderEngine OptionDefault<Settings::ShaderEngine>::default_val = Settings::ShaderEngine::Bytecode; Settings::ShaderEngine OptionDefault<Settings::ShaderEngine>::default_val = Settings::ShaderEngine::Bytecode;
template<>
bool BooleanOption<Settings::EnableAudioEmulation>::default_val = false;
} // namespace Config } // namespace Config