mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-05 13:20:11 +00:00
feat(ngs2): report custom sampler voice state
Dead Cells (PPSA15552) calls sceNgs2VoiceGetState on custom sampler voices with a 48-byte buffer and reads the 64-bit value at offset 16 as a running counter. Fill it with the decoded sample count, keep the common state flags, and return INVALID_OUT_SIZE for other sizes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
a0f5916a29
commit
87f2c7de83
4 files changed
+25
No files matched your search
@@ -619,6 +619,15 @@ struct Ngs2SamplerVoiceState {
|
||||
};
|
||||
static_assert(sizeof(Ngs2SamplerVoiceState) == 56);
|
||||
|
||||
struct Ngs2CustomSamplerVoiceState {
|
||||
Ngs2VoiceState voice_state;
|
||||
std::uint32_t reserved[2];
|
||||
std::uint64_t num_decoded_samples;
|
||||
std::uint64_t reserved2[3];
|
||||
};
|
||||
static_assert(sizeof(Ngs2CustomSamplerVoiceState) == 48);
|
||||
static_assert(offsetof(Ngs2CustomSamplerVoiceState, num_decoded_samples) == 16);
|
||||
|
||||
struct Ngs2WaveformInfo {
|
||||
Ngs2WaveformFormat format;
|
||||
std::uint32_t data_offset;
|
||||
|
||||
@@ -452,6 +452,14 @@ int APS5_VABI sceNgs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* state
|
||||
submixer.voice_state.state_flags = voice.stateFlags;
|
||||
return SCE_NGS2_OK;
|
||||
}
|
||||
case SCE_NGS2_RACK_ID_CUSTOM_SAMPLER: {
|
||||
if (state_size != sizeof(Ngs2CustomSamplerVoiceState)) return SCE_NGS2_ERROR_INVALID_OUT_SIZE;
|
||||
auto& sampler = *reinterpret_cast<Ngs2CustomSamplerVoiceState*>(state);
|
||||
sampler = {};
|
||||
sampler.voice_state.state_flags = voice.stateFlags;
|
||||
sampler.num_decoded_samples = voice.decodedSamples;
|
||||
return SCE_NGS2_OK;
|
||||
}
|
||||
default: throw std::runtime_error("NGS2: voice state of rack " + Ngs2Hex(voice.rack->rackId) + " is not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,6 +281,13 @@ static void TestCustomSampler() {
|
||||
const auto out = Render(system);
|
||||
for (std::uint32_t i = 0; i < Grain; i++) Require(out[i * 2] == 0.5f && out[i * 2 + 1] == 0.75f);
|
||||
|
||||
Ngs2CustomSamplerVoiceState state{};
|
||||
Require(sceNgs2VoiceGetState(voice, &state.voice_state, sizeof(Ngs2SamplerVoiceState)) == SCE_NGS2_ERROR_INVALID_OUT_SIZE);
|
||||
Require(sceNgs2VoiceGetState(voice, &state.voice_state, sizeof(state)) == SCE_NGS2_OK);
|
||||
Require(state.voice_state.state_flags == (SCE_NGS2_VOICE_STATE_FLAG_INUSE | SCE_NGS2_VOICE_STATE_FLAG_PLAYING) && state.num_decoded_samples == Grain);
|
||||
Render(system);
|
||||
Require(sceNgs2VoiceGetState(voice, &state.voice_state, sizeof(state)) == SCE_NGS2_OK && state.num_decoded_samples == Grain * 2);
|
||||
|
||||
Require(sceNgs2RackDestroy(rack, nullptr) == SCE_NGS2_OK);
|
||||
Require(sceNgs2SystemDestroy(system, nullptr) == SCE_NGS2_OK);
|
||||
}
|
||||
|
||||
@@ -25,3 +25,4 @@
|
||||
- [sceNgs2GeomResetListenerParam, sceNgs2GeomResetSourceParam](../../../core/libs/prx/libSceNgs2.native/src/Geom.cpp) (libSceNgs2.native) - the structures (12, 16, 16, 60, 96, 108, 32 and 308 bytes) come from [KytyPS5](https://github.com/KytyPS5/KytyPS5)'s `ngs2.cpp` and match [shadPS4](https://github.com/shadps4-emu/shadPS4)'s `ngs2_geom.h` field for field, but only KytyPS5 gives the behaviour - shadPS4 logs and returns success without writing the output. The defaults (orient front +Z, orient up +Y, sound speed 343, cone 1/360/1/360, rolloff 0/1000000/1/1, doppler factor, full-band, LFE and maximum level 1, two speakers and matrix format 2) are unverified on a PS5 title; KytyPS5 and iStark/PS5PCEM agree on them. PPSA15552 (Dead Cells) calls `sceNgs2GeomResetSourceParam` after creating its racks. A null output address returns `INVALID_OUT_ADDRESS` as elsewhere in the library rather than throwing as KytyPS5 does. `sceNgs2GeomApply` stays unimplemented
|
||||
- [sceNgs2GeomCalcListener](../../../core/libs/prx/libSceNgs2.native/src/Geom.cpp) supports only a listener at the origin with front +Z, up +Y and flags 0. The identity matrix and preserved finite velocity and positive finite sound speed follow [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/ngs2.cpp) and [PS5PCEM](https://github.com/iStark/PS5PCEM/blob/d2534bac6325a2c61c0fa88977e5321074304484/src/hle/ngs2_geom.zig) for that case, not a PS5 measurement. Other orientations (including non-unit vectors), translations and flags throw without changing the output; the matrix convention, handedness flags and console error codes remain unverified. Nonfinite input and nonpositive sound speed also throw. Dead Cells (PPSA15552) reaches this call after the custom sampler rack in #4334, but its arguments have not been captured here. Source attenuation, panning and Doppler in `sceNgs2GeomApply` remain unimplemented
|
||||
- [NGS2 custom sampler rack](../../../core/libs/prx/libSceNgs2.native/src/Custom.cpp) (libSceNgs2.native, rack 0x4001) - implements bounded support for the custom sampler rack and its built-in module 0x13 (Custom Voice Filter), unblocking PPSA15552 (Dead Cells) startup. Structure layouts come from [shadPS4's ngs2_custom.h](https://raw.githubusercontent.com/shadps4-emu/shadPS4/main/src/core/libraries/ngs2/ngs2_custom.h) (OrbisNgs2CustomVoiceFilterParam, 40 bytes) and live trace correlation from [prosper's hle_audio.cpp](https://raw.githubusercontent.com/mattias800/prosper/main/prosper/src/hle/audio/hle_audio.cpp) (0x40001300 command and parameters like 10000.0f and 0.707f). Routes parameter updates via the 0x40001300 command family into the Biquad filter engine, supporting only filter type 1; other filter types and unmodeled configurations throw.
|
||||
- [sceNgs2VoiceGetState custom sampler](../../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native, rack 0x4001) - only the size and one field come from a title. PPSA15552 (Dead Cells) calls it on custom sampler voices with a 48-byte buffer at two sites (eboot `0x1740f90`, `0x1741009`) and reads only the 64-bit value at offset 16: the first site keeps it and the second subtracts the kept value, so it is filled with the voice's decoded sample count. Other sizes return `INVALID_OUT_SIZE` as for the other racks. The state flags fill the common voice state; the remaining fields stay zero. shadPS4's `OrbisNgs2CustomSamplerVoiceState` is about 80 bytes and does not match the size this title passes, so the field names and the console's value are unverified
|
||||
Reference in new issue
Block a user