Merge pull request #4893 from Lorkydey/feat/audioout2-user-supported-attributes
feat(audioout2): report supported user attributes
This commit is contained in:
commit
20890629f2
|
|
@ -29,11 +29,6 @@ int APS5_VABI sceAudioOut2SetSystemDebugState(const AudioOut2SystemDebugStatePar
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAudioOut2UserGetSupportedAttributes(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAudioOut2EnableChat(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,44 @@
|
|||
#include <cstdint>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <unordered_set>
|
||||
|
||||
static constexpr int SCE_AUDIO_OUT2_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80260502);
|
||||
|
||||
static std::atomic<AudioOut2UserHandle> g_nextUser{1};
|
||||
static std::mutex g_usersLock;
|
||||
static AudioOut2UserHandle g_nextUser = 1;
|
||||
static std::unordered_set<AudioOut2UserHandle> g_users;
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI sceAudioOut2UserCreate(uint32_t user_id, AudioOut2UserHandle* handle) {
|
||||
(void)user_id;
|
||||
if (!handle) return SCE_AUDIO_OUT2_ERROR_INVALID_ARGUMENT;
|
||||
*handle = g_nextUser.fetch_add(1, std::memory_order_relaxed);
|
||||
std::lock_guard lock(g_usersLock);
|
||||
if (g_nextUser == std::numeric_limits<AudioOut2UserHandle>::max())
|
||||
throw std::runtime_error("AudioOut2: user handles exhausted");
|
||||
g_users.insert(g_nextUser);
|
||||
*handle = g_nextUser++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAudioOut2UserDestroy(AudioOut2UserHandle handle) {
|
||||
(void)handle;
|
||||
std::lock_guard lock(g_usersLock);
|
||||
g_users.erase(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAudioOut2UserGetSupportedAttributes(AudioOut2UserHandle handle, uint32_t* contextAttributes, uint32_t* portAttributes) {
|
||||
if (!contextAttributes || !portAttributes)
|
||||
throw std::runtime_error("sceAudioOut2UserGetSupportedAttributes: null output");
|
||||
std::lock_guard lock(g_usersLock);
|
||||
if (!g_users.contains(handle))
|
||||
throw std::runtime_error("sceAudioOut2UserGetSupportedAttributes: unknown user handle");
|
||||
*contextAttributes = 0;
|
||||
*portAttributes = (1u << 0) | (1u << 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,15 @@
|
|||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceAudioOut2UserCreate(std::uint32_t, AudioOut2UserHandle*);
|
||||
int APS5_VABI sceAudioOut2UserDestroy(AudioOut2UserHandle);
|
||||
int APS5_VABI sceAudioOut2UserGetSupportedAttributes(AudioOut2UserHandle, std::uint32_t*, std::uint32_t*);
|
||||
int APS5_VABI sceAudioOut2ContextResetParam(AudioOut2ContextParam*);
|
||||
int APS5_VABI sceAudioOut2ContextCreate(const AudioOut2ContextParam*, void*, std::size_t, AudioOut2ContextHandle*);
|
||||
int APS5_VABI sceAudioOut2ContextDestroy(AudioOut2ContextHandle);
|
||||
|
|
@ -48,6 +53,51 @@ constexpr float masterGain = 0.5f;
|
|||
constexpr float fold = 0.70710678f;
|
||||
constexpr float tolerance = 1e-5f;
|
||||
|
||||
void TestUserAttributes() {
|
||||
struct Output {
|
||||
std::uint32_t before = 0x12345678u;
|
||||
std::uint32_t value = 0xFFFFFFFFu;
|
||||
std::uint32_t after = 0x87654321u;
|
||||
} context, port;
|
||||
AudioOut2UserHandle first = 0;
|
||||
AudioOut2UserHandle second = 0;
|
||||
Require(sceAudioOut2UserCreate(1, &first) == 0);
|
||||
Require(sceAudioOut2UserCreate(2, &second) == 0 && second != first);
|
||||
Require(sceAudioOut2UserGetSupportedAttributes(first, &context.value, &port.value) == 0);
|
||||
Require(context.value == 0 && port.value == ((1u << attributeData) | (1u << attributeVolume)));
|
||||
Require(context.before == 0x12345678u && context.after == 0x87654321u);
|
||||
Require(port.before == 0x12345678u && port.after == 0x87654321u);
|
||||
const auto rejects = [&](AudioOut2UserHandle handle, bool nullContext, bool nullPort) {
|
||||
context.value = port.value = 0xFFFFFFFFu;
|
||||
bool threw = false;
|
||||
try {
|
||||
sceAudioOut2UserGetSupportedAttributes(handle, nullContext ? nullptr : &context.value, nullPort ? nullptr : &port.value);
|
||||
} catch (const std::runtime_error& error) {
|
||||
threw = std::string(error.what()).find("sceAudioOut2UserGetSupportedAttributes") != std::string::npos;
|
||||
}
|
||||
Require(threw && context.value == 0xFFFFFFFFu && port.value == 0xFFFFFFFFu);
|
||||
};
|
||||
rejects(first, true, false);
|
||||
rejects(first, false, true);
|
||||
rejects(first, true, true);
|
||||
rejects(0, false, false);
|
||||
rejects(std::numeric_limits<AudioOut2UserHandle>::max(), false, false);
|
||||
Require(sceAudioOut2UserDestroy(first) == 0);
|
||||
rejects(first, false, false);
|
||||
std::thread([&] {
|
||||
Require(sceAudioOut2UserGetSupportedAttributes(second, &context.value, &port.value) == 0);
|
||||
}).join();
|
||||
Require(context.value == 0 && port.value == 3);
|
||||
AudioOut2UserHandle next = 0;
|
||||
Require(sceAudioOut2UserCreate(1, &next) == 0 && next != first && next != second);
|
||||
rejects(first, false, false);
|
||||
Require(sceAudioOut2UserGetSupportedAttributes(next, &context.value, &port.value) == 0);
|
||||
Require(context.value == 0 && port.value == 3);
|
||||
Require(sceAudioOut2UserDestroy(next) == 0 && sceAudioOut2UserDestroy(second) == 0);
|
||||
Require(context.before == 0x12345678u && context.after == 0x87654321u);
|
||||
Require(port.before == 0x12345678u && port.after == 0x87654321u);
|
||||
}
|
||||
|
||||
struct Layout {
|
||||
std::uint32_t channels;
|
||||
std::vector<float> left;
|
||||
|
|
@ -282,6 +332,7 @@ void TestMeasuredMainPortFormats() {
|
|||
}
|
||||
|
||||
int main() {
|
||||
TestUserAttributes();
|
||||
SetEnvironment("SDL_AUDIODRIVER", "disk");
|
||||
for (const Layout* layout : {&mono, &stereo, &surround71, &surround714}) {
|
||||
TestFloatLayout(*layout);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
### Unknown function info
|
||||
|
||||
- PPSA23566 imports declared without parameters, signatures unknown: [sceAudioOut2UserGetSupportedAttributes](../../../core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp), [sceConvertKeycodeGetCharacterFromKeyboardData](../../../core/libs/prx/libSceConvertKeycode/Export.cpp), [sce::Json::MemAllocator::notifyError](../../../core/libs/prx/libSceJson2/Export.cpp), [sceNpCommerceDialogOpen2](../../../core/libs/prx/libSceNpCommerce/Export.cpp), [sceProprietaryVoiceChatHelper{Initialize,Terminate,SetVoiceChatState,GetVoiceChatUsageState}](../../../core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp), [sceVoice{GetResourceInfo,ResetPort,EnableChat,DisableChat}](../../../core/libs/prx/libSceVoice/Export.cpp). Names from the shadPS4 aerolib NID list
|
||||
- [sceAudioOut2UserGetSupportedAttributes](../../../core/libs/prx/libSceAudioOut/src/AudioOut2User.cpp) (libSceAudioOut) - the user handle and two uint32 output pointers follow [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/5dfdb4b0b166e83dc9ae275001afb695f12c7174/src/SharpProspero/Interop/Audio/AudioOut2.cs) and [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/df5b9b92be7dfd463b47756b707d6d356a9f0550/src/libs/libAudio2.cpp), not a console measurement. The masks describe this runtime: no context attributes and port attributes PCM (bit 0) and gain (bit 1). Null outputs and unknown or destroyed user handles throw; console validation order and error values are unknown. Users are tracked for this query, but port ownership and busy-user destruction are not implemented. The other PPSA23566 imports remain declared without parameters, with unknown signatures: [sceConvertKeycodeGetCharacterFromKeyboardData](../../../core/libs/prx/libSceConvertKeycode/Export.cpp), [sce::Json::MemAllocator::notifyError](../../../core/libs/prx/libSceJson2/Export.cpp), [sceNpCommerceDialogOpen2](../../../core/libs/prx/libSceNpCommerce/Export.cpp), [sceProprietaryVoiceChatHelper{Initialize,Terminate,SetVoiceChatState,GetVoiceChatUsageState}](../../../core/libs/prx/libSceProprietaryVoiceChatHelperPrx/Export.cpp), [sceVoice{GetResourceInfo,ResetPort,EnableChat,DisableChat}](../../../core/libs/prx/libSceVoice/Export.cpp). Names from the shadPS4 aerolib NID list
|
||||
- PPSA28416 imports declared without parameters, signatures unknown: [sceAudioOut2EnableChat](../../../core/libs/prx/libSceAudioOut/src/AudioOut2System.cpp), imported by its bundled `party-ps5-shipping.prx`. Name from the shadPS4 aerolib NID list
|
||||
- [sceAudioOutExClose, sceAudioOutExConfigureOutput, sceAudioOutExOpen](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) - imported by PPSA99505, which fails to load without them; added without an implementation and declared without parameters. PPSA99505 calls them only for its HDMI bitstream output, an option that is off by default, to read the formats the TV or receiver lists, switch the HDMI output mode and open a port for IEC 61937 bursts ([Jelly5](https://github.com/02dnot/Jelly5/blob/552b866d89b2a58b27f7f7b0484dc743ce235526/app/src/jelly5_bitstream.cpp#L110-L179)); [EVO-PLAYER-PS5](https://github.com/sainsaji/EVO-PLAYER-PS5/blob/da0c0451333bab82e79fffd2de4718e917f9dcb0/projects/evoplayer/core/src/audio/evo_pt.cpp) also calls `sceAudioOutExOpen`, `sceAudioOutExConfigureOutput` and `sceAudioOutExClose` for HDMI bitstream output. The two declare the arguments of `sceAudioOutExConfigureOutput` differently and neither is confirmed on a console. Audio reaches the host device through SDL as PCM, so there is no encoded HDMI output to switch to
|
||||
- [sceAudioOutExGetMonitorInfo](../../../core/libs/prx/libSceAudioOut/src/AudioOut.cpp) (libSceAudioOut) reports a sink without audio descriptors: it zeroes the buffer and returns 0, as `sceAudioOutSysGetHdmiMonitorInfo` does, since audio reaches the host through SDL as PCM and there is no EDID to describe. The arguments `(0, 0, info, size)` and the descriptor count as a 32-bit value at +0x98, with 8-byte descriptors from +0xA0, follow [Jelly5](https://github.com/02dnot/Jelly5/blob/552b866d89b2a58b27f7f7b0484dc743ce235526/app/src/jelly5_bitstream.cpp#L62-L117) (PPSA99505), which passes a 0x400-byte buffer and read that layout from one TV; with no descriptor listed it decodes the audio itself instead of opening a bitstream port. The meaning of the first two arguments and the structure's size are unknown: nonzero first or second arguments and sizes below 0xA0, which cannot hold the count, throw, and every byte of the declared size is written as 0. A null buffer returns `0x80260004` like the other AudioOut calls; the console's code is not measured
|
||||
|
|
|
|||
Loading…
Reference in New Issue