glue: Correct missing bytes in ApplicationLaunchParameter
This commit is contained in:
parent
d40a38df8d
commit
d10fc2d727
7 changed files with 71 additions and 37 deletions
|
@ -61,8 +61,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||||
default:
|
default:
|
||||||
return FileSys::StorageId::None;
|
return FileSys::StorageId::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
|
@ -66,6 +66,9 @@ public:
|
||||||
std::map<std::string, std::string, std::less<>> GetPatchVersionNames(
|
std::map<std::string, std::string, std::less<>> GetPatchVersionNames(
|
||||||
VirtualFile update_raw = nullptr) const;
|
VirtualFile update_raw = nullptr) const;
|
||||||
|
|
||||||
|
// If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails,
|
||||||
|
// it will fallback to the Meta-type NCA of the base game. If that fails, the result will be
|
||||||
|
// std::nullopt
|
||||||
std::optional<u32> GetGameVersion() const;
|
std::optional<u32> GetGameVersion() const;
|
||||||
|
|
||||||
// Given title_id of the program, attempts to get the control data of the update and parse
|
// Given title_id of the program, attempts to get the control data of the update and parse
|
||||||
|
|
|
@ -647,18 +647,18 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional<ContentProviderUnion
|
||||||
|
|
||||||
std::optional<ContentProviderUnionSlot> ContentProviderUnion::GetSlotForEntry(
|
std::optional<ContentProviderUnionSlot> ContentProviderUnion::GetSlotForEntry(
|
||||||
u64 title_id, ContentRecordType type) const {
|
u64 title_id, ContentRecordType type) const {
|
||||||
for (const auto& [slot, provider] : providers) {
|
const auto iter =
|
||||||
if (provider == nullptr)
|
std::find_if(providers.begin(), providers.end(), [title_id, type](const auto& provider) {
|
||||||
continue;
|
return provider.second != nullptr && provider.second->HasEntry(title_id, type);
|
||||||
|
});
|
||||||
if (provider->HasEntry(title_id, type)) {
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (iter == providers.end()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return iter->first;
|
||||||
|
}
|
||||||
|
|
||||||
ManualContentProvider::~ManualContentProvider() = default;
|
ManualContentProvider::~ManualContentProvider() = default;
|
||||||
|
|
||||||
void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type,
|
void ManualContentProvider::AddEntry(TitleType title_type, ContentRecordType content_type,
|
||||||
|
|
|
@ -58,7 +58,8 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
|
||||||
if (!title_id.has_value()) {
|
if (!title_id.has_value()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
|
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_NONEXISTENT);
|
rb.Push(ERR_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto res = manager.GetLaunchProperty(*title_id);
|
const auto res = manager.GetLaunchProperty(*title_id);
|
||||||
|
@ -67,6 +68,7 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res.Code());
|
rb.Push(res.Code());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
@ -86,6 +88,7 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestCont
|
||||||
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
LOG_ERROR(Service_ARP, "Failed to get launch property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res.Code());
|
rb.Push(res.Code());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
IPC::ResponseBuilder rb{ctx, 6};
|
||||||
|
@ -103,7 +106,8 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
|
||||||
if (!title_id.has_value()) {
|
if (!title_id.has_value()) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
|
LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_NONEXISTENT);
|
rb.Push(ERR_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto res = manager.GetControlProperty(*title_id);
|
const auto res = manager.GetControlProperty(*title_id);
|
||||||
|
@ -112,6 +116,7 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res.Code());
|
rb.Push(res.Code());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.WriteBuffer(*res);
|
ctx.WriteBuffer(*res);
|
||||||
|
@ -132,6 +137,7 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestCon
|
||||||
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
LOG_ERROR(Service_ARP, "Failed to get control property!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(res.Code());
|
rb.Push(res.Code());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.WriteBuffer(*res);
|
ctx.WriteBuffer(*res);
|
||||||
|
@ -168,14 +174,16 @@ private:
|
||||||
if (process_id == 0) {
|
if (process_id == 0) {
|
||||||
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
|
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_PROCESS_ID_ZERO);
|
rb.Push(ERR_INVALID_PROCESS_ID);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (issued) {
|
if (issued) {
|
||||||
LOG_ERROR(Service_ARP,
|
LOG_ERROR(Service_ARP,
|
||||||
"Attempted to issue registrar, but registrar is already issued!");
|
"Attempted to issue registrar, but registrar is already issued!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_ALREADY_ISSUED);
|
rb.Push(ERR_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_process_id(process_id, launch, std::move(control));
|
issue_process_id(process_id, launch, std::move(control));
|
||||||
|
@ -193,7 +201,8 @@ private:
|
||||||
Service_ARP,
|
Service_ARP,
|
||||||
"Attempted to set application launch property, but registrar is already issued!");
|
"Attempted to set application launch property, but registrar is already issued!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_ALREADY_ISSUED);
|
rb.Push(ERR_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
|
@ -211,7 +220,8 @@ private:
|
||||||
Service_ARP,
|
Service_ARP,
|
||||||
"Attempted to set application control property, but registrar is already issued!");
|
"Attempted to set application control property, but registrar is already issued!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_ALREADY_ISSUED);
|
rb.Push(ERR_INVALID_ACCESS);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
control = ctx.ReadBuffer();
|
control = ctx.ReadBuffer();
|
||||||
|
@ -247,7 +257,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
|
||||||
[this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
|
[this](u64 process_id, ApplicationLaunchProperty launch, std::vector<u8> control) {
|
||||||
const auto res = GetTitleIDForProcessID(system, process_id);
|
const auto res = GetTitleIDForProcessID(system, process_id);
|
||||||
if (!res.has_value()) {
|
if (!res.has_value()) {
|
||||||
return ERR_NONEXISTENT;
|
return ERR_NOT_REGISTERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return manager.Register(*res, launch, std::move(control));
|
return manager.Register(*res, launch, std::move(control));
|
||||||
|
@ -267,7 +277,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) {
|
||||||
if (process_id == 0) {
|
if (process_id == 0) {
|
||||||
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
|
LOG_ERROR(Service_ARP, "Must have non-zero process ID!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_PROCESS_ID_ZERO);
|
rb.Push(ERR_INVALID_PROCESS_ID);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto title_id = GetTitleIDForProcessID(system, process_id);
|
const auto title_id = GetTitleIDForProcessID(system, process_id);
|
||||||
|
@ -275,7 +286,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) {
|
||||||
if (!title_id.has_value()) {
|
if (!title_id.has_value()) {
|
||||||
LOG_ERROR(Service_ARP, "No title ID for process ID!");
|
LOG_ERROR(Service_ARP, "No title ID for process ID!");
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ERR_NONEXISTENT);
|
rb.Push(ERR_NOT_REGISTERED);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
|
|
||||||
namespace Service::Glue {
|
namespace Service::Glue {
|
||||||
|
|
||||||
constexpr ResultCode ERR_OUTPUT_TOO_SMALL{0x3C9D};
|
constexpr ResultCode ERR_INVALID_RESOURCE{ErrorModule::ARP, 0x1E};
|
||||||
constexpr ResultCode ERR_PROCESS_ID_ZERO{0x3E9D};
|
constexpr ResultCode ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 0x1F};
|
||||||
constexpr ResultCode ERR_TITLE_ID_ZERO{0x3E9D};
|
constexpr ResultCode ERR_INVALID_ACCESS{ErrorModule::ARP, 0x2A};
|
||||||
constexpr ResultCode ERR_ALREADY_ISSUED{0x549D};
|
constexpr ResultCode ERR_NOT_REGISTERED{ErrorModule::ARP, 0x66};
|
||||||
constexpr ResultCode ERR_NONEXISTENT{0xCC9D};
|
|
||||||
|
|
||||||
} // namespace Service::Glue
|
} // namespace Service::Glue
|
||||||
|
|
|
@ -7,18 +7,23 @@
|
||||||
|
|
||||||
namespace Service::Glue {
|
namespace Service::Glue {
|
||||||
|
|
||||||
|
struct ARPManager::MapEntry {
|
||||||
|
ApplicationLaunchProperty launch;
|
||||||
|
std::vector<u8> control;
|
||||||
|
};
|
||||||
|
|
||||||
ARPManager::ARPManager() = default;
|
ARPManager::ARPManager() = default;
|
||||||
|
|
||||||
ARPManager::~ARPManager() = default;
|
ARPManager::~ARPManager() = default;
|
||||||
|
|
||||||
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
|
ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
return ERR_TITLE_ID_ZERO;
|
return ERR_INVALID_PROCESS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto iter = entries.find(title_id);
|
const auto iter = entries.find(title_id);
|
||||||
if (iter == entries.end()) {
|
if (iter == entries.end()) {
|
||||||
return ERR_NONEXISTENT;
|
return ERR_NOT_REGISTERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeResult<ApplicationLaunchProperty>(iter->second.launch);
|
return MakeResult<ApplicationLaunchProperty>(iter->second.launch);
|
||||||
|
@ -26,12 +31,12 @@ ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id)
|
||||||
|
|
||||||
ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
|
ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
return ERR_TITLE_ID_ZERO;
|
return ERR_INVALID_PROCESS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto iter = entries.find(title_id);
|
const auto iter = entries.find(title_id);
|
||||||
if (iter == entries.end()) {
|
if (iter == entries.end()) {
|
||||||
return ERR_NONEXISTENT;
|
return ERR_NOT_REGISTERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeResult<std::vector<u8>>(iter->second.control);
|
return MakeResult<std::vector<u8>>(iter->second.control);
|
||||||
|
@ -40,12 +45,12 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
|
||||||
ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
||||||
std::vector<u8> control) {
|
std::vector<u8> control) {
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
return ERR_TITLE_ID_ZERO;
|
return ERR_INVALID_PROCESS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto iter = entries.find(title_id);
|
const auto iter = entries.find(title_id);
|
||||||
if (iter != entries.end()) {
|
if (iter != entries.end()) {
|
||||||
return ERR_ALREADY_ISSUED;
|
return ERR_INVALID_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)});
|
entries.insert_or_assign(title_id, MapEntry{launch, std::move(control)});
|
||||||
|
@ -54,12 +59,12 @@ ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
|
||||||
|
|
||||||
ResultCode ARPManager::Unregister(u64 title_id) {
|
ResultCode ARPManager::Unregister(u64 title_id) {
|
||||||
if (title_id == 0) {
|
if (title_id == 0) {
|
||||||
return ERR_TITLE_ID_ZERO;
|
return ERR_INVALID_PROCESS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto iter = entries.find(title_id);
|
const auto iter = entries.find(title_id);
|
||||||
if (iter == entries.end()) {
|
if (iter == entries.end()) {
|
||||||
return ERR_NONEXISTENT;
|
return ERR_NOT_REGISTERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.erase(iter);
|
entries.erase(iter);
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/romfs_factory.h"
|
#include "core/file_sys/romfs_factory.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
@ -15,31 +18,45 @@ struct ApplicationLaunchProperty {
|
||||||
u32 version;
|
u32 version;
|
||||||
FileSys::StorageId base_game_storage_id;
|
FileSys::StorageId base_game_storage_id;
|
||||||
FileSys::StorageId update_storage_id;
|
FileSys::StorageId update_storage_id;
|
||||||
INSERT_PADDING_BYTES(0x2);
|
u8 program_index;
|
||||||
|
u8 reserved;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ApplicationLaunchProperty) == 0x10,
|
static_assert(sizeof(ApplicationLaunchProperty) == 0x10,
|
||||||
"ApplicationLaunchProperty has incorrect size.");
|
"ApplicationLaunchProperty has incorrect size.");
|
||||||
|
|
||||||
|
// A class to manage state related to the arp:w and arp:r services, specifically the registration
|
||||||
|
// and unregistration of launch and control properties.
|
||||||
class ARPManager {
|
class ARPManager {
|
||||||
public:
|
public:
|
||||||
ARPManager();
|
ARPManager();
|
||||||
~ARPManager();
|
~ARPManager();
|
||||||
|
|
||||||
|
// Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was
|
||||||
|
// previously registered, otherwise ERR_NOT_REGISTERED if it was never registered or
|
||||||
|
// ERR_INVALID_PROCESS_ID if the title ID is 0.
|
||||||
ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const;
|
ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const;
|
||||||
|
|
||||||
|
// Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to
|
||||||
|
// the provided title ID if it was previously registered, otherwise ERR_NOT_REGISTERED if it was
|
||||||
|
// never registered or ERR_INVALID_PROCESS_ID if the title ID is 0.
|
||||||
ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const;
|
ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const;
|
||||||
|
|
||||||
|
// Adds a new entry to the internal database with the provided parameters, returning
|
||||||
|
// ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister
|
||||||
|
// step, and ERR_INVALID_PROCESS_ID if the title ID is 0.
|
||||||
ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control);
|
ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control);
|
||||||
|
|
||||||
|
// Removes the registration for the provided title ID from the database, returning
|
||||||
|
// ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the
|
||||||
|
// title ID is 0.
|
||||||
ResultCode Unregister(u64 title_id);
|
ResultCode Unregister(u64 title_id);
|
||||||
|
|
||||||
|
// Removes all entries from the database, always succeeds. Should only be used when resetting
|
||||||
|
// system state.
|
||||||
void ResetAll();
|
void ResetAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct MapEntry {
|
struct MapEntry;
|
||||||
ApplicationLaunchProperty launch;
|
|
||||||
std::vector<u8> control;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<u64, MapEntry> entries;
|
std::map<u64, MapEntry> entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue