mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 05:46:56 +01:00
Add add-on (DLC) support (#1519)
Add add-on content support Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
@@ -4,15 +4,21 @@
|
||||
#include "common/emulatorConfig.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "kernel/fileSystem.h"
|
||||
#include "libs/errno.h"
|
||||
#include "libs/libs.h"
|
||||
#include "libs/systemService.h"
|
||||
#include "loader/additionalContent.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
#include "loader/systemContent.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
namespace Libs {
|
||||
|
||||
@@ -20,10 +26,21 @@ LIB_VERSION("AppContent", 1, "AppContentUtil", 1, 1);
|
||||
|
||||
namespace AppContent {
|
||||
|
||||
constexpr uint32_t APP_CONTENT_APPPARAM_SKU_FLAG_FULL = 3;
|
||||
constexpr int APP_CONTENT_ERROR_PARAMETER = -2133262334; /* 0x80D90002 */
|
||||
constexpr int APP_CONTENT_ERROR_NOT_MOUNTED = -2133262332; /* 0x80D90004 */
|
||||
constexpr int APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = -2133262329; /* 0x80D90007 */
|
||||
constexpr uint32_t APP_CONTENT_APPPARAM_SKU_FLAG_FULL = 3;
|
||||
constexpr int APP_CONTENT_ERROR_PARAMETER = -2133262334; /* 0x80D90002 */
|
||||
constexpr int APP_CONTENT_ERROR_BUSY = -2133262333; /* 0x80D90003 */
|
||||
constexpr int APP_CONTENT_ERROR_NOT_MOUNTED = -2133262332; /* 0x80D90004 */
|
||||
constexpr int APP_CONTENT_ERROR_NOT_FOUND = -2133262331; /* 0x80D90005 */
|
||||
constexpr int APP_CONTENT_ERROR_MOUNT_FULL = -2133262330; /* 0x80D90006 */
|
||||
constexpr size_t APP_CONTENT_ADDCONT_MOUNT_MAXNUM = 64;
|
||||
|
||||
struct AddcontMount {
|
||||
std::string label;
|
||||
std::string point;
|
||||
};
|
||||
|
||||
static std::mutex g_addcont_mutex;
|
||||
static std::vector<AddcontMount> g_addcont_mounts;
|
||||
|
||||
static std::string g_title_id;
|
||||
|
||||
@@ -174,13 +191,51 @@ int KYTY_SYSV_ABI AppContentAddcontMount(uint32_t servic
|
||||
service_label, reinterpret_cast<uint64_t>(entitlement_label),
|
||||
reinterpret_cast<uint64_t>(mount_point));
|
||||
|
||||
if (entitlement_label == nullptr || mount_point == nullptr) {
|
||||
if (service_label != 0 || entitlement_label == nullptr || mount_point == nullptr) {
|
||||
return APP_CONTENT_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
std::memset(mount_point->data, 0, sizeof(mount_point->data));
|
||||
|
||||
return APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT;
|
||||
const auto* entry =
|
||||
Loader::AddContentFind(entitlement_label->data, sizeof(entitlement_label->data));
|
||||
if (entry == nullptr) {
|
||||
return APP_CONTENT_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
std::lock_guard lock(g_addcont_mutex);
|
||||
|
||||
for (const auto& m: g_addcont_mounts) {
|
||||
if (m.label == entry->entitlement_label) {
|
||||
return APP_CONTENT_ERROR_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_addcont_mounts.size() == APP_CONTENT_ADDCONT_MOUNT_MAXNUM) {
|
||||
return APP_CONTENT_ERROR_MOUNT_FULL;
|
||||
}
|
||||
std::error_code ec;
|
||||
if (!std::filesystem::is_directory(entry->mount_dir, ec)) {
|
||||
return APP_CONTENT_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
uint32_t index = 0;
|
||||
while (
|
||||
std::any_of(g_addcont_mounts.begin(), g_addcont_mounts.end(), [&](const AddcontMount& m) {
|
||||
return m.point == "/addcont" + std::to_string(index) + "/";
|
||||
})) {
|
||||
index++;
|
||||
}
|
||||
|
||||
AddcontMount mount {entry->entitlement_label, "/addcont" + std::to_string(index) + "/"};
|
||||
LibKernel::FileSystem::Mount(entry->mount_dir, mount.point);
|
||||
LOGF("\t mounted %s -> %s\n", mount.point.c_str(),
|
||||
Common::PathToString(entry->mount_dir).c_str());
|
||||
|
||||
std::strncpy(mount_point->data, mount.point.c_str(), sizeof(mount_point->data) - 1);
|
||||
g_addcont_mounts.push_back(std::move(mount));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI AppContentAddcontUnmount(const AppContentMountPoint* mount_point) {
|
||||
@@ -196,6 +251,19 @@ int KYTY_SYSV_ABI AppContentAddcontUnmount(const AppContentMountPoint* mount_poi
|
||||
return APP_CONTENT_ERROR_NOT_MOUNTED;
|
||||
}
|
||||
|
||||
const std::string point(mount_point->data,
|
||||
strnlen(mount_point->data, sizeof(mount_point->data)));
|
||||
|
||||
std::lock_guard lock(g_addcont_mutex);
|
||||
|
||||
const auto it = std::find_if(g_addcont_mounts.begin(), g_addcont_mounts.end(),
|
||||
[&](const AddcontMount& m) { return m.point == point; });
|
||||
if (it == g_addcont_mounts.end()) {
|
||||
return APP_CONTENT_ERROR_NOT_MOUNTED;
|
||||
}
|
||||
LibKernel::FileSystem::Umount(point);
|
||||
g_addcont_mounts.erase(it);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#include "common/abi.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "libs/libs.h"
|
||||
#include "loader/additionalContent.h"
|
||||
#include "loader/symbolDatabase.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
@@ -164,6 +167,16 @@ static constexpr NpEntitlementAccessAddcontEntitlementInfo NP_ENTITLEMENT_ACCESS
|
||||
{{{"_mtqu6"}, {}}, 3, 4}, // GTA V hash 0x9cd1bcad
|
||||
};
|
||||
|
||||
static NpEntitlementAccessAddcontEntitlementInfo
|
||||
MakeAddcontInfo(const Loader::AddContentEntry& entry) {
|
||||
NpEntitlementAccessAddcontEntitlementInfo info {};
|
||||
std::memcpy(info.entitlement_label.data, entry.entitlement_label.data(),
|
||||
entry.entitlement_label.size());
|
||||
info.package_type = 2; // Additional content with extra data.
|
||||
info.download_status = 4; // Installed.
|
||||
return info;
|
||||
}
|
||||
|
||||
static int KYTY_SYSV_ABI NpEntitlementAccessInitialize(
|
||||
const NpEntitlementAccessInitParam* init_param, NpEntitlementAccessBootParam* boot_param) {
|
||||
PRINT_NAME();
|
||||
@@ -404,19 +417,21 @@ static int KYTY_SYSV_ABI NpEntitlementAccessGetAddcontEntitlementInfoList(
|
||||
LOGF("\t list_num = %" PRIu32 "\n", list_num);
|
||||
LOGF("\t hit_num = 0x%016" PRIx64 "\n", reinterpret_cast<uint64_t>(hit_num));
|
||||
|
||||
if (hit_num == nullptr || (list == nullptr && list_num != 0)) {
|
||||
if (hit_num == nullptr) {
|
||||
return NP_ENTITLEMENT_ACCESS_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
*hit_num = static_cast<uint32_t>(sizeof(NP_ENTITLEMENT_ACCESS_ADDON_LIST) /
|
||||
sizeof(NP_ENTITLEMENT_ACCESS_ADDON_LIST[0]));
|
||||
constexpr auto legacy_count = std::size(NP_ENTITLEMENT_ACCESS_ADDON_LIST);
|
||||
const auto& entries = Loader::AddContentGetAll();
|
||||
*hit_num = static_cast<uint32_t>(legacy_count + entries.size());
|
||||
|
||||
if (list != nullptr && list_num != 0) {
|
||||
memset(list, 0, sizeof(*list) * list_num);
|
||||
|
||||
const auto copy_num = (list_num < *hit_num ? list_num : *hit_num);
|
||||
const auto copy_num = std::min(list_num, *hit_num);
|
||||
for (uint32_t i = 0; i < copy_num; i++) {
|
||||
list[i] = NP_ENTITLEMENT_ACCESS_ADDON_LIST[i];
|
||||
list[i] = i < legacy_count ? NP_ENTITLEMENT_ACCESS_ADDON_LIST[i]
|
||||
: MakeAddcontInfo(entries[i - legacy_count]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,6 +462,12 @@ static int KYTY_SYSV_ABI NpEntitlementAccessGetAddcontEntitlementInfo(
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto* entry =
|
||||
Loader::AddContentFind(entitlement_label->data, sizeof(entitlement_label->data))) {
|
||||
*info = MakeAddcontInfo(*entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return NP_ENTITLEMENT_ACCESS_ERROR_NO_ENTITLEMENT;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user