feat(libSceAppContent): implement sceAppContentGetAddcontInfo and GetAddcontInfoList
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
def8119927
commit
5b331ed022
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
static constexpr int SCE_APP_CONTENT_ERROR_PARAMETER = static_cast<int>(0x80D90002);
|
||||
static constexpr int SCE_APP_CONTENT_ERROR_NOT_FOUND = static_cast<int>(0x80D90005);
|
||||
static constexpr int SCE_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = static_cast<int>(0x80D90007);
|
||||
static constexpr uint32_t APPPARAM_ID_SKU_FLAG = 1;
|
||||
static constexpr int32_t SKU_FLAG_FULL = 3;
|
||||
|
||||
|
|
@ -18,6 +19,11 @@ static constexpr char TEMPORARY_MOUNT_POINT[] = "/temp0";
|
|||
static constexpr char DOWNLOAD_MOUNT_POINT[] = "/download0";
|
||||
static constexpr uint32_t TEMPORARY_DATA_OPTION_FORMAT = 1;
|
||||
|
||||
struct AppContentAddcontInfo {
|
||||
NpUnifiedEntitlementLabel entitlement_label;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
static std::filesystem::path TemporaryDirectory(const AppContentMountPoint* mount_point) {
|
||||
if (!mount_point || std::strncmp(mount_point->data, TEMPORARY_MOUNT_POINT, sizeof(mount_point->data)) != 0) APS5_INVALID_ARG_EX;
|
||||
return ResolvePath_nid_no_patch(TEMPORARY_MOUNT_POINT);
|
||||
|
|
@ -40,6 +46,19 @@ int APS5_VABI sceAppContentAddcontUnmount(const AppContentMountPoint* mount_poin
|
|||
return SCE_APP_CONTENT_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAppContentGetAddcontInfo(uint32_t service_label, const NpUnifiedEntitlementLabel* entitlement_label, AppContentAddcontInfo* info) {
|
||||
(void)service_label;
|
||||
if (!entitlement_label || !info) return SCE_APP_CONTENT_ERROR_PARAMETER;
|
||||
return SCE_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAppContentGetAddcontInfoList(uint32_t service_label, AppContentAddcontInfo* list, uint32_t list_num, uint32_t* hit_num) {
|
||||
(void)service_label;
|
||||
if ((!list || list_num == 0) && !hit_num) return SCE_APP_CONTENT_ERROR_PARAMETER;
|
||||
if (hit_num) *hit_num = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAppContentAppParamGetInt(uint32_t param_id, int32_t* value) {
|
||||
if (!value) return SCE_APP_CONTENT_ERROR_PARAMETER;
|
||||
switch (param_id) {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@
|
|||
extern "C" {
|
||||
int APS5_VABI sceAppContentAddcontMount(uint32_t, const NpUnifiedEntitlementLabel*, AppContentMountPoint*);
|
||||
int APS5_VABI sceAppContentAddcontUnmount(const AppContentMountPoint*);
|
||||
int APS5_VABI sceAppContentGetAddcontInfo(uint32_t, const NpUnifiedEntitlementLabel*, void*);
|
||||
int APS5_VABI sceAppContentGetAddcontInfoList(uint32_t, void*, uint32_t, uint32_t*);
|
||||
}
|
||||
|
||||
static constexpr int ErrorParameter = static_cast<int>(0x80D90002);
|
||||
static constexpr int ErrorNotFound = static_cast<int>(0x80D90005);
|
||||
static constexpr int ErrorDrmNoEntitlement = static_cast<int>(0x80D90007);
|
||||
static void Require(bool value) { if (!value) std::abort(); }
|
||||
|
||||
int main() {
|
||||
|
|
@ -24,4 +27,31 @@ int main() {
|
|||
std::memcpy(mountPoint.data, "/addcont0", 10);
|
||||
Require(sceAppContentAddcontUnmount(&mountPoint) == ErrorNotFound);
|
||||
Require(sceAppContentAddcontUnmount(nullptr) == ErrorParameter);
|
||||
|
||||
unsigned char info[24];
|
||||
std::memset(info, 0x5a, sizeof(info));
|
||||
unsigned char untouchedInfo[24];
|
||||
std::memcpy(untouchedInfo, info, sizeof(info));
|
||||
Require(sceAppContentGetAddcontInfo(0, &label, info) == ErrorDrmNoEntitlement);
|
||||
Require(std::memcmp(info, untouchedInfo, sizeof(info)) == 0);
|
||||
Require(sceAppContentGetAddcontInfo(0, nullptr, info) == ErrorParameter);
|
||||
Require(sceAppContentGetAddcontInfo(0, &label, nullptr) == ErrorParameter);
|
||||
|
||||
uint32_t hitNum = 0x5a5a5a5a;
|
||||
Require(sceAppContentGetAddcontInfoList(0, nullptr, 0, &hitNum) == 0);
|
||||
Require(hitNum == 0);
|
||||
hitNum = 0x5a5a5a5a;
|
||||
Require(sceAppContentGetAddcontInfoList(0, info, 0, &hitNum) == 0);
|
||||
Require(hitNum == 0);
|
||||
hitNum = 0x5a5a5a5a;
|
||||
Require(sceAppContentGetAddcontInfoList(0, nullptr, 1, &hitNum) == 0);
|
||||
Require(hitNum == 0);
|
||||
hitNum = 0x5a5a5a5a;
|
||||
Require(sceAppContentGetAddcontInfoList(0, info, 1, &hitNum) == 0);
|
||||
Require(hitNum == 0);
|
||||
Require(std::memcmp(info, untouchedInfo, sizeof(info)) == 0);
|
||||
Require(sceAppContentGetAddcontInfoList(0, info, 1, nullptr) == 0);
|
||||
Require(sceAppContentGetAddcontInfoList(0, nullptr, 0, nullptr) == ErrorParameter);
|
||||
Require(sceAppContentGetAddcontInfoList(0, info, 0, nullptr) == ErrorParameter);
|
||||
Require(sceAppContentGetAddcontInfoList(0, nullptr, 1, nullptr) == ErrorParameter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
### Functional
|
||||
|
||||
- [sceNetSendmsg and sceNetRecvmsg](../../core/libs/prx/libSceNet/Export.cpp) (libSceNet) copy the scatter/gather list through one host buffer and accept only the flags `sceNetSend`/`sceNetRecv` accept. Sending control data throws; a receive never returns control data (`msg_controllen` 0), since no socket option that queues it is supported
|
||||
- [Additional content](../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) is not installed or mounted: `sceAppContentAddcontMount` answers `NOT_FOUND` for every entitlement label and `sceAppContentAddcontUnmount` for every mount point, as no add-content mount is ever handed out
|
||||
- [Additional content](../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) is not installed or mounted: `sceAppContentAddcontMount` answers `NOT_FOUND` for every entitlement label and `sceAppContentAddcontUnmount` for every mount point, as no add-content mount is ever handed out; `sceAppContentGetAddcontInfo` answers `DRM_NO_ENTITLEMENT` for every label and `sceAppContentGetAddcontInfoList` reports 0 entries
|
||||
- [sceKernelInstallExceptionHandler](../../core/libs/prx/libkernel/System/src/Exception.cpp) records the handler but nothing delivers to it: a host fault still ends the process, and `sceKernelRaiseException` is not implemented. PPSA12544's PS5Util module (Unity) installs a SIGUSR1 handler that reads `uc_mcontext.mc_rsp` (offset 0xf8 of the context) and raises SIGUSR1 on other threads to stop them for garbage collection, so delivery must run the handler on the target thread with a FreeBSD `ucontext`
|
||||
- [libSceUlt queues](../../core/libs/prx/libSceUlt/Export.cpp) use preallocated host storage instead of the supplied guest work area; its existing size formula and the 512-byte object layouts remain unverified. Waiting-queue pool thread limits and waiter priority ordering are not implemented. Finalization wakes blocked queue callers with `ULT_ERROR_STATE`.
|
||||
- [Thread cancellation](../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) is not modelled: `scePthreadCancel` throws, so no cancel request is ever pending and `scePthreadTestcancel` and `pthread_testcancel` return without acting; the cancel state and type set by `scePthreadSetcancelstate` and `scePthreadSetcanceltype` are stored and not used
|
||||
|
|
|
|||
Loading…
Reference in New Issue