mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
fix(voice): restore initialization and thread parameter validation
This commit is contained in:
1 parent
ee76c0cd98
commit
fe4016f612
5 files changed
+94
-13
No files matched your search
+49
-2
@@ -975,13 +975,60 @@ struct AudiodecM4aacInfo {
|
||||
std::int32_t i_result;
|
||||
};
|
||||
|
||||
struct VoiceEvent {
|
||||
std::int32_t type;
|
||||
std::uint32_t reserved;
|
||||
void* userData;
|
||||
union {
|
||||
struct {
|
||||
std::uint16_t count;
|
||||
std::uint16_t ports[7];
|
||||
} dataReady;
|
||||
struct {
|
||||
std::uint16_t port;
|
||||
std::uint8_t state;
|
||||
std::uint8_t reserved[13];
|
||||
} deviceState;
|
||||
};
|
||||
};
|
||||
|
||||
using VoiceEventHandler = void (APS5_VABI*)(const VoiceEvent* event);
|
||||
|
||||
struct VoiceThreadsParams {
|
||||
std::uint32_t mode;
|
||||
std::int32_t firstPriority;
|
||||
std::uint64_t firstAffinity;
|
||||
std::int32_t secondPriority;
|
||||
std::uint32_t reserved20;
|
||||
std::uint64_t secondAffinity;
|
||||
std::int32_t thirdPriority;
|
||||
std::uint32_t reserved36;
|
||||
std::uint64_t thirdAffinity;
|
||||
};
|
||||
|
||||
static_assert(sizeof(VoiceEvent) == 32);
|
||||
static_assert(offsetof(VoiceEvent, userData) == 8);
|
||||
static_assert(offsetof(VoiceEvent, dataReady) == 16);
|
||||
static_assert(offsetof(VoiceEvent, deviceState) == 16);
|
||||
static_assert(sizeof(VoiceThreadsParams) == 48);
|
||||
static_assert(offsetof(VoiceThreadsParams, firstAffinity) == 8);
|
||||
static_assert(offsetof(VoiceThreadsParams, secondPriority) == 16);
|
||||
static_assert(offsetof(VoiceThreadsParams, secondAffinity) == 24);
|
||||
static_assert(offsetof(VoiceThreadsParams, thirdPriority) == 32);
|
||||
static_assert(offsetof(VoiceThreadsParams, thirdAffinity) == 40);
|
||||
|
||||
struct VoiceInitParam {
|
||||
std::int32_t app_type;
|
||||
std::uint64_t on_event;
|
||||
VoiceEventHandler on_event;
|
||||
void* user_data;
|
||||
std::uint8_t reserved[32 - sizeof(std::int32_t) - sizeof(std::uint64_t) - sizeof(void*)];
|
||||
std::uint8_t reserved[16];
|
||||
};
|
||||
|
||||
static_assert(sizeof(VoiceInitParam) == 40);
|
||||
static_assert(offsetof(VoiceInitParam, on_event) == 8);
|
||||
static_assert(offsetof(VoiceInitParam, user_data) == 16);
|
||||
static_assert(offsetof(VoiceInitParam, reserved) == 24);
|
||||
|
||||
struct VoicePortParam {
|
||||
std::int32_t port_type;
|
||||
std::uint16_t threshold;
|
||||
|
||||
@@ -68,20 +68,26 @@ bool IsInput(std::int32_t type) { return type == PortInDevice || type == PortInP
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI sceVoiceInit(VoiceInitParam* param, int32_t version) {
|
||||
(void)version;
|
||||
if (param == nullptr) APS5_INVALID_ARG_EX;
|
||||
int APS5_VABI sceVoiceInit(const VoiceInitParam* param, std::int32_t version) {
|
||||
auto& voice = State();
|
||||
std::lock_guard lock(voice.mutex);
|
||||
if (voice.initialized) return VoiceErrorAlreadyInitialized;
|
||||
if (voice.initialized) return static_cast<std::int32_t>(0x804e0802u);
|
||||
if (!param || version != 100) return InvalidArgument;
|
||||
if (param->app_type != 4 && param->app_type != 0x08000000 && param->app_type != 0x10000000 && param->app_type != 0x20000000) return InvalidArgument;
|
||||
voice.appType = param->app_type;
|
||||
voice.initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceVoiceSetThreadsParams(void* params) {
|
||||
if (params == nullptr) APS5_INVALID_ARG_EX;
|
||||
return 0;
|
||||
int APS5_VABI sceVoiceSetThreadsParams(const VoiceThreadsParams* params) {
|
||||
auto& voice = State();
|
||||
std::lock_guard lock(voice.mutex);
|
||||
if (!voice.initialized) return NotInitialized;
|
||||
if (!params) return InvalidArgument;
|
||||
if (voice.started) return static_cast<std::int32_t>(0x804e080bu);
|
||||
if (params->mode == 0) return 0;
|
||||
if (params->mode != 1) return InvalidArgument;
|
||||
Fail(__func__, "worker priority and affinity are not implemented");
|
||||
}
|
||||
|
||||
int APS5_VABI sceVoiceStart(const VoiceStartParam* param) {
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include <stdexcept>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceVoiceInit(VoiceInitParam*, std::int32_t);
|
||||
int APS5_VABI sceVoiceInit(const VoiceInitParam*, std::int32_t);
|
||||
int APS5_VABI sceVoiceSetThreadsParams(const VoiceThreadsParams*);
|
||||
int APS5_VABI sceVoiceStart(const VoiceStartParam*);
|
||||
int APS5_VABI sceVoiceEnd_nid_postfix();
|
||||
int APS5_VABI sceVoiceCreatePort(std::uint32_t*, const VoicePortParam*);
|
||||
@@ -89,12 +90,37 @@ int main() {
|
||||
Require(sceVoiceGetResourceInfo(nullptr) == notInitialized);
|
||||
Require(sceVoiceEnableChat() == notInitialized);
|
||||
Require(sceVoiceDisableChat() == notInitialized);
|
||||
Require(sceVoiceSetThreadsParams(nullptr) == notInitialized);
|
||||
VoiceThreadsParams threads{};
|
||||
Require(sceVoiceSetThreadsParams(&threads) == notInitialized);
|
||||
VoiceInitParam init{};
|
||||
Require(sceVoiceInit(nullptr, 100) == invalidArgument);
|
||||
for (const auto mode : {-1, 0, 1, 3, 5, 0x07ffffff, 0x08000001, 0x10000001, 0x20000001, INT32_MAX}) {
|
||||
init.app_type = mode;
|
||||
Require(sceVoiceInit(&init, 100) == invalidArgument);
|
||||
Require(sceVoiceGetResourceInfo(nullptr) == notInitialized);
|
||||
}
|
||||
init.app_type = 0x10000000;
|
||||
for (const auto version : {-1, 0, 99, 101, INT32_MAX}) {
|
||||
Require(sceVoiceInit(&init, version) == invalidArgument);
|
||||
Require(sceVoiceGetResourceInfo(nullptr) == notInitialized);
|
||||
}
|
||||
VoiceStartParam start{};
|
||||
Require(sceVoiceInit(&init, 100) == 0);
|
||||
Require(sceVoiceInit(&init, 100) == AlreadyInitialized);
|
||||
Require(sceVoiceInit(nullptr, 0) == static_cast<std::int32_t>(0x804e0802u));
|
||||
Require(sceVoiceInit(&init, 100) == static_cast<std::int32_t>(0x804e0802u));
|
||||
Require(sceVoiceSetThreadsParams(nullptr) == invalidArgument);
|
||||
Require(sceVoiceSetThreadsParams(&threads) == 0);
|
||||
threads.mode = 2;
|
||||
Require(sceVoiceSetThreadsParams(&threads) == invalidArgument);
|
||||
threads.mode = UINT32_MAX;
|
||||
Require(sceVoiceSetThreadsParams(&threads) == invalidArgument);
|
||||
threads.mode = 1;
|
||||
RequireThrows([&] { sceVoiceSetThreadsParams(&threads); });
|
||||
threads.mode = 0;
|
||||
Require(sceVoiceStart(&start) == 0);
|
||||
Require(sceVoiceSetThreadsParams(nullptr) == invalidArgument);
|
||||
Require(sceVoiceSetThreadsParams(&threads) == static_cast<std::int32_t>(0x804e080bu));
|
||||
Require(sceVoiceGetResourceInfo(nullptr) == invalidArgument);
|
||||
struct ResourceOutput {
|
||||
VoiceResourceInfo info;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <string_view>
|
||||
|
||||
extern "C" {
|
||||
int APS5_VABI sceVoiceInit(VoiceInitParam*, int32_t);
|
||||
int APS5_VABI sceVoiceInit(const VoiceInitParam*, int32_t);
|
||||
int APS5_VABI sceVoiceEnd_nid_postfix(void);
|
||||
int APS5_VABI sceVoiceCreatePort(uint32_t*, const VoicePortParam*);
|
||||
int APS5_VABI sceVoiceDeletePort(uint32_t);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Functional
|
||||
|
||||
- [Voice resource and port state](../../../core/libs/prx/libSceVoice/Export.cpp): resource information is eight bytes containing four 16-bit limits selected by initialization mode. Reset, pause and resume use confirmed initialization, range and missing-port errors; repeated pause/resume succeed. The host has no buffered voice processing or device reset backend, so reset only covers empty software ports and pause flags currently affect no audio. Initialization still lacks native mode/version validation, allocator callbacks and backend creation; port creation does not enforce native resource limits.
|
||||
- [Voice resource and port state](../../../core/libs/prx/libSceVoice/Export.cpp): resource information is eight bytes containing four 16-bit limits selected by initialization mode. Reset, pause and resume use confirmed initialization, range and missing-port errors; repeated pause/resume succeed. The host has no buffered voice processing or device reset backend, so reset only covers empty software ports and pause flags currently affect no audio. Initialization validates native modes and version 100, but still lacks event callback delivery and backend creation; port creation does not enforce native resource limits.
|
||||
- [sceVoiceEnableChat and sceVoiceDisableChat](../../../core/libs/prx/libSceVoice/Export.cpp): zero-argument signatures and the not-initialized error are confirmed. Initialized calls throw because the required audio chat backend is not implemented; they no longer report success for a local flag change.
|
||||
|
||||
### Unknown function info
|
||||
@@ -20,3 +20,5 @@
|
||||
- [sceVoiceSetBitRate](../../../core/libs/prx/libSceVoice/Export.cpp) (libSceVoice) - unknown signature
|
||||
- [sceVoiceUpdatePort](../../../core/libs/prx/libSceVoice/Export.cpp) (libSceVoice) - unknown signature
|
||||
- [sceVoiceGetPortAttr](../../../core/libs/prx/libSceVoice/Export.cpp): native initialization, port-range, pointer, attribute-size and port-type validation is implemented. Supported device attributes throw because the host has no device state or voice-activity processing. The former constant-zero voice-activity fallback is removed; failed calls leave output untouched.
|
||||
|
||||
- [sceVoiceSetThreadsParams](../../../core/libs/prx/libSceVoice/Export.cpp): the 48-byte mode/priority/affinity layout and initialization, null, started-state and mode validation are recovered. Mode 1 throws because worker scheduling is not implemented; mode 0 is the native no-op. The 32-byte event callback union is recovered, but callback delivery and device-state byte semantics remain unimplemented.
|
||||
Reference in new issue
Block a user