diff --git a/src/core/core.cpp b/src/core/core.cpp index 2d7e83522a..df26eb109b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -61,8 +61,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot( default: return FileSys::StorageId::None; } - - UNREACHABLE(); } } // Anonymous namespace diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index f82b4ae1e3..a363c6577f 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -66,6 +66,9 @@ public: std::map> GetPatchVersionNames( 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 GetGameVersion() const; // Given title_id of the program, attempts to get the control data of the update and parse diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 3bb9212105..4608490e01 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -647,16 +647,16 @@ ContentProviderUnion::ListEntriesFilterOrigin(std::optional ContentProviderUnion::GetSlotForEntry( u64 title_id, ContentRecordType type) const { - for (const auto& [slot, provider] : providers) { - if (provider == nullptr) - continue; + const auto iter = + std::find_if(providers.begin(), providers.end(), [title_id, type](const auto& provider) { + 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; diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp index 19c75ff2f9..b591ce31b6 100644 --- a/src/core/hle/service/glue/arp.cpp +++ b/src/core/hle/service/glue/arp.cpp @@ -58,7 +58,8 @@ void ARP_R::GetApplicationLaunchProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } 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!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -86,6 +88,7 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(Kernel::HLERequestCont LOG_ERROR(Service_ARP, "Failed to get launch property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } IPC::ResponseBuilder rb{ctx, 6}; @@ -103,7 +106,8 @@ void ARP_R::GetApplicationControlProperty(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "Failed to get title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } 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!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -132,6 +137,7 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(Kernel::HLERequestCon LOG_ERROR(Service_ARP, "Failed to get control property!"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } ctx.WriteBuffer(*res); @@ -168,14 +174,16 @@ private: if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_PROCESS_ID_ZERO); + rb.Push(ERR_INVALID_PROCESS_ID); + return; } if (issued) { LOG_ERROR(Service_ARP, "Attempted to issue registrar, but registrar is already issued!"); 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)); @@ -193,7 +201,8 @@ private: Service_ARP, "Attempted to set application launch property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } IPC::RequestParser rp{ctx}; @@ -211,7 +220,8 @@ private: Service_ARP, "Attempted to set application control property, but registrar is already issued!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_ALREADY_ISSUED); + rb.Push(ERR_INVALID_ACCESS); + return; } control = ctx.ReadBuffer(); @@ -247,7 +257,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) { [this](u64 process_id, ApplicationLaunchProperty launch, std::vector control) { const auto res = GetTitleIDForProcessID(system, process_id); if (!res.has_value()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return manager.Register(*res, launch, std::move(control)); @@ -267,7 +277,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (process_id == 0) { LOG_ERROR(Service_ARP, "Must have non-zero process ID!"); 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); @@ -275,7 +286,8 @@ void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { if (!title_id.has_value()) { LOG_ERROR(Service_ARP, "No title ID for process ID!"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ERR_NONEXISTENT); + rb.Push(ERR_NOT_REGISTERED); + return; } IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h index 594e20a017..c2874c5858 100644 --- a/src/core/hle/service/glue/errors.h +++ b/src/core/hle/service/glue/errors.h @@ -8,10 +8,9 @@ namespace Service::Glue { -constexpr ResultCode ERR_OUTPUT_TOO_SMALL{0x3C9D}; -constexpr ResultCode ERR_PROCESS_ID_ZERO{0x3E9D}; -constexpr ResultCode ERR_TITLE_ID_ZERO{0x3E9D}; -constexpr ResultCode ERR_ALREADY_ISSUED{0x549D}; -constexpr ResultCode ERR_NONEXISTENT{0xCC9D}; +constexpr ResultCode ERR_INVALID_RESOURCE{ErrorModule::ARP, 0x1E}; +constexpr ResultCode ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 0x1F}; +constexpr ResultCode ERR_INVALID_ACCESS{ErrorModule::ARP, 0x2A}; +constexpr ResultCode ERR_NOT_REGISTERED{ErrorModule::ARP, 0x66}; } // namespace Service::Glue diff --git a/src/core/hle/service/glue/manager.cpp b/src/core/hle/service/glue/manager.cpp index 0d5bb4d506..6da52d2d6c 100644 --- a/src/core/hle/service/glue/manager.cpp +++ b/src/core/hle/service/glue/manager.cpp @@ -7,18 +7,23 @@ namespace Service::Glue { +struct ARPManager::MapEntry { + ApplicationLaunchProperty launch; + std::vector control; +}; + ARPManager::ARPManager() = default; ARPManager::~ARPManager() = default; ResultVal ARPManager::GetLaunchProperty(u64 title_id) const { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return MakeResult(iter->second.launch); @@ -26,12 +31,12 @@ ResultVal ARPManager::GetLaunchProperty(u64 title_id) ResultVal> ARPManager::GetControlProperty(u64 title_id) const { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } return MakeResult>(iter->second.control); @@ -40,12 +45,12 @@ ResultVal> ARPManager::GetControlProperty(u64 title_id) const { ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, std::vector control) { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter != entries.end()) { - return ERR_ALREADY_ISSUED; + return ERR_INVALID_ACCESS; } 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) { if (title_id == 0) { - return ERR_TITLE_ID_ZERO; + return ERR_INVALID_PROCESS_ID; } const auto iter = entries.find(title_id); if (iter == entries.end()) { - return ERR_NONEXISTENT; + return ERR_NOT_REGISTERED; } entries.erase(iter); diff --git a/src/core/hle/service/glue/manager.h b/src/core/hle/service/glue/manager.h index 561ebf4e06..a7f5ce3ee7 100644 --- a/src/core/hle/service/glue/manager.h +++ b/src/core/hle/service/glue/manager.h @@ -4,6 +4,9 @@ #pragma once +#include +#include +#include "common/common_types.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/romfs_factory.h" #include "core/hle/result.h" @@ -15,31 +18,45 @@ struct ApplicationLaunchProperty { u32 version; FileSys::StorageId base_game_storage_id; FileSys::StorageId update_storage_id; - INSERT_PADDING_BYTES(0x2); + u8 program_index; + u8 reserved; }; static_assert(sizeof(ApplicationLaunchProperty) == 0x10, "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 { public: 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 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> 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 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); + // Removes all entries from the database, always succeeds. Should only be used when resetting + // system state. void ResetAll(); private: - struct MapEntry { - ApplicationLaunchProperty launch; - std::vector control; - }; - + struct MapEntry; std::map entries; };