mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-23 00:53:02 -05:00
PPSA01289 (Sackboy: A Big Adventure) calls sceAudioOut2MasteringTerm when it replaces its world, which threw. Like Init and SetParam it has no effect, as there is no mastering stage. The title creates its next world's audio device before it destroys the previous one, so Init runs twice before Term runs twice; whether the console reports an error for either is unknown, so both return 0 and the case is recorded in TechnicalDebt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
73 lines
2.5 KiB
C++
73 lines
2.5 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <stdexcept>
|
|
|
|
extern "C" {
|
|
int APS5_VABI sceAudioOut2Initialize();
|
|
int APS5_VABI sceAudioOut2Set3DLatency(int, std::uint32_t);
|
|
int APS5_VABI sceAudioOut2MasteringInit(std::uint32_t);
|
|
int APS5_VABI sceAudioOut2MasteringTerm();
|
|
int APS5_VABI sceAudioOut2MasteringSetParam(const void*, std::uint32_t, std::uint32_t);
|
|
}
|
|
|
|
static void Require(bool value, const char* message) {
|
|
if (value) return;
|
|
std::fprintf(stderr, "%s\n", message);
|
|
std::abort();
|
|
}
|
|
|
|
template<typename TFunction>
|
|
static bool ThrowsRuntimeError(TFunction function) {
|
|
try {
|
|
function();
|
|
} catch (const std::runtime_error&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
namespace {
|
|
|
|
constexpr int systemUser = 0xFF;
|
|
constexpr int user = 0x10000000;
|
|
|
|
void TestSet3DLatency() {
|
|
Require(sceAudioOut2Set3DLatency(systemUser, 2) == 0, "latency 2 for the system user must be accepted");
|
|
Require(sceAudioOut2Set3DLatency(systemUser, 2) == 0, "latency 2 must be accepted again");
|
|
Require(sceAudioOut2Set3DLatency(systemUser, 1) == 0, "latency 1 for the system user must be accepted");
|
|
Require(ThrowsRuntimeError([] { sceAudioOut2Set3DLatency(systemUser, 0); }), "latency 0 must throw");
|
|
Require(ThrowsRuntimeError([] { sceAudioOut2Set3DLatency(systemUser, 3); }), "latency 3 must throw");
|
|
Require(ThrowsRuntimeError([] { sceAudioOut2Set3DLatency(user, 2); }), "a user other than the system user must throw");
|
|
}
|
|
|
|
void TestMasteringInit() {
|
|
Require(sceAudioOut2MasteringInit(0) == 0, "flags 0 must be accepted");
|
|
Require(ThrowsRuntimeError([] { sceAudioOut2MasteringInit(1); }), "flags 1 must throw");
|
|
}
|
|
|
|
void TestMasteringTerm() {
|
|
Require(sceAudioOut2MasteringInit(0) == 0, "a second initialization must be accepted");
|
|
Require(sceAudioOut2MasteringTerm() == 0, "termination must be accepted");
|
|
Require(sceAudioOut2MasteringTerm() == 0, "termination must be accepted for each initialization");
|
|
}
|
|
|
|
void TestMasteringSetParam() {
|
|
const std::uint32_t params[4] = {1u, 0u, 0u, 0u};
|
|
Require(sceAudioOut2MasteringSetParam(params, 0, 0) == 0, "mastering parameters must be accepted");
|
|
Require(ThrowsRuntimeError([] { sceAudioOut2MasteringSetParam(nullptr, 0, 0); }), "null mastering parameters must throw");
|
|
}
|
|
|
|
}
|
|
|
|
int main() {
|
|
Require(sceAudioOut2Initialize() == 0, "initialization must succeed");
|
|
TestSet3DLatency();
|
|
TestMasteringInit();
|
|
TestMasteringTerm();
|
|
TestMasteringSetParam();
|
|
return 0;
|
|
}
|