mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-22 08:33:12 -05:00
100 lines
4.6 KiB
C++
100 lines
4.6 KiB
C++
#include "prx/libScePad/include/PadState.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <stdexcept>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
extern "C" {
|
|
int APS5_VABI sceAudioOutOpen(int, int, int, std::uint32_t, std::uint32_t, std::uint32_t);
|
|
int APS5_VABI sceAudioOutExOpen(int, std::uint32_t);
|
|
int APS5_VABI sceAudioOutClose(int);
|
|
int APS5_VABI sceAudioOutOutput(int, const void*);
|
|
int APS5_VABI sceAudioOutOutputs(AudioOutOutputParam*, std::uint32_t);
|
|
int APS5_VABI sceAudioOutSetVolume(int, std::uint32_t, int*);
|
|
}
|
|
|
|
static void Require(bool value, const char* message) {
|
|
if (!value) throw std::runtime_error(message);
|
|
}
|
|
|
|
struct Case {
|
|
std::string_view name;
|
|
std::uint32_t format = 1;
|
|
bool batch = false;
|
|
std::array<int, 2> volume{32768, 32768};
|
|
std::array<std::uint8_t, 2> expected{128, 255};
|
|
bool silence = false;
|
|
bool drain = false;
|
|
bool ex = false;
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
try {
|
|
const std::string_view mode = argc == 2 ? argv[1] : "--s16";
|
|
const Case cases[] = {
|
|
{"--s16"}, {"--f32", 4}, {"--batch_s16", 1, true}, {"--batch_f32", 4, true},
|
|
{"--mono_s16", 0, false, {32768, 32768}, {128, 128}},
|
|
{"--mono_f32", 3, false, {32768, 32768}, {128, 128}},
|
|
{"--gain_s16", 1, false, {16384, 8192}, {64, 64}},
|
|
{"--gain_f32", 4, true, {16384, 8192}, {64, 64}},
|
|
{"--muted", 4, false, {0, 0}, {0, 0}},
|
|
{"--silence", 1, true, {32768, 32768}, {0, 0}, true},
|
|
{"--drain", 4, false, {32768, 32768}, {0, 0}, false, true},
|
|
{"--ex", 1, true, {32768, 32768}, {0, 0}, false, false, true},
|
|
{"--pad_control"}
|
|
};
|
|
const Case* selected = nullptr;
|
|
for (const auto& entry : cases) if (entry.name == mode) selected = &entry;
|
|
Require(argc <= 2 && selected != nullptr, "invalid test arguments");
|
|
const auto& test = *selected;
|
|
Pad::Initialize();
|
|
Pad::SetVibrationMode(1);
|
|
std::uint32_t seen = 0;
|
|
PadOutputState output{};
|
|
static_cast<void>(PadFetchOutput_nid_postfix(&seen, &output));
|
|
struct Port {
|
|
int handle = -1;
|
|
~Port() { if (handle > 0) sceAudioOutClose(handle); }
|
|
} port;
|
|
if (mode == "--pad_control") {
|
|
PadSubmitAudioHaptics_nid_postfix(128, 255);
|
|
} else {
|
|
const std::uint32_t frames = test.ex ? 256u : 48000u;
|
|
const bool floating = test.format == 3 || test.format == 4;
|
|
const std::uint32_t channels = test.format == 0 || test.format == 3 ? 1u : 2u;
|
|
std::vector<std::int16_t> integers(frames * 2);
|
|
std::vector<float> floats(frames * 2);
|
|
for (std::uint32_t frame = 0; frame < frames && !test.silence; ++frame) {
|
|
integers[frame * channels] = 8192;
|
|
floats[frame * channels] = 0.25f;
|
|
if (channels == 2) {
|
|
integers[frame * channels + 1] = -16384;
|
|
floats[frame * channels + 1] = -0.5f;
|
|
}
|
|
}
|
|
port.handle = test.ex ? sceAudioOutExOpen(0x10000000, 0) : sceAudioOutOpen(0x10000000, 10, 0, frames, 48000, test.format);
|
|
Require(port.handle > 0, "legacy vibration port did not open");
|
|
auto volume = test.volume;
|
|
Require(sceAudioOutSetVolume(port.handle, 3, volume.data()) == 0, "legacy vibration volume failed");
|
|
const void* samples = test.drain ? nullptr : floating ? static_cast<const void*>(floats.data()) : static_cast<const void*>(integers.data());
|
|
AudioOutOutputParam param{};
|
|
param.handle = port.handle;
|
|
param.ptr = samples;
|
|
const int result = test.batch ? sceAudioOutOutputs(¶m, 1) : sceAudioOutOutput(port.handle, samples);
|
|
Require(result == static_cast<int>(frames), "legacy vibration output returned the wrong frame count");
|
|
}
|
|
const bool changed = PadFetchOutput_nid_postfix(&seen, &output);
|
|
Require(changed == (test.expected[0] != 0 || test.expected[1] != 0), "legacy vibration output published the wrong controller state");
|
|
Require(output.audioVibrationLarge == test.expected[0] && output.audioVibrationSmall == test.expected[1], "legacy vibration PCM did not reach the existing motor bridge");
|
|
Require(output.vibrationLarge == 0 && output.vibrationSmall == 0, "audio vibration replaced regular motor state");
|
|
std::puts("legacy vibration bridge test passed");
|
|
return 0;
|
|
} catch (const std::exception& error) {
|
|
std::fprintf(stderr, "%s\n", error.what());
|
|
return 1;
|
|
}
|
|
}
|