diff --git a/stratosphere/ncm/source/impl/lr_redirection.cpp b/stratosphere/ncm/source/impl/lr_redirection.cpp index 21e9c63ac..59edfb5ff 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.cpp +++ b/stratosphere/ncm/source/impl/lr_redirection.cpp @@ -23,16 +23,21 @@ namespace sts::lr::impl { NON_MOVEABLE(LocationRedirection); private: ncm::TitleId title_id; + ncm::TitleId application_id; Path path; u32 flags; public: - LocationRedirection(ncm::TitleId title_id, const Path& path, u32 flags) : - title_id(title_id), path(path), flags(flags) { /* ... */ } + LocationRedirection(ncm::TitleId title_id, ncm::TitleId application_id, const Path& path, u32 flags) : + title_id(title_id), application_id(application_id), path(path), flags(flags) { /* ... */ } ncm::TitleId GetTitleId() const { return this->title_id; } + ncm::TitleId GetApplicationId() const { + return this->application_id; + } + void GetPath(Path *out) const { *out = this->path; } @@ -61,8 +66,12 @@ namespace sts::lr::impl { } void LocationRedirector::SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags) { + this->SetRedirection(title_id, path, flags); + } + + void LocationRedirector::SetRedirection(ncm::TitleId title_id, ncm::TitleId application_id, const Path &path, u32 flags) { this->EraseRedirection(title_id); - this->redirection_list.push_back(*(new LocationRedirection(title_id, path, flags))); + this->redirection_list.push_back(*(new LocationRedirection(title_id, application_id, path, flags))); } void LocationRedirector::SetRedirectionFlags(ncm::TitleId title_id, u32 flags) { @@ -96,4 +105,27 @@ namespace sts::lr::impl { } } + void LocationRedirector::ClearRedirections(const ncm::TitleId* excluding_tids, size_t num_tids) { + for (auto it = this->redirection_list.begin(); it != this->redirection_list.end();) { + bool skip = false; + for (size_t i = 0; i < num_tids; i++) { + ncm::TitleId tid = excluding_tids[i]; + + if (it->GetApplicationId() == tid) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + auto old = it; + it = this->redirection_list.erase(it); + delete &(*old); + it++; + } + } + } diff --git a/stratosphere/ncm/source/impl/lr_redirection.hpp b/stratosphere/ncm/source/impl/lr_redirection.hpp index d31693219..3cf142a1c 100644 --- a/stratosphere/ncm/source/impl/lr_redirection.hpp +++ b/stratosphere/ncm/source/impl/lr_redirection.hpp @@ -37,9 +37,11 @@ namespace sts::lr::impl { bool FindRedirection(Path *out, ncm::TitleId title_id); void SetRedirection(ncm::TitleId title_id, const Path &path, u32 flags = RedirectionFlags_None); + void SetRedirection(ncm::TitleId title_id, ncm::TitleId application_id, const Path &path, u32 flags = RedirectionFlags_None); void SetRedirectionFlags(ncm::TitleId title_id, u32 flags); void EraseRedirection(ncm::TitleId title_id); void ClearRedirections(u32 flags = RedirectionFlags_None); + void ClearRedirections(const ncm::TitleId* excluding_tids, size_t num_tids); }; } diff --git a/stratosphere/ncm/source/impl/lr_registered_data.hpp b/stratosphere/ncm/source/impl/lr_registered_data.hpp index 456708074..91af52fba 100644 --- a/stratosphere/ncm/source/impl/lr_registered_data.hpp +++ b/stratosphere/ncm/source/impl/lr_registered_data.hpp @@ -27,19 +27,21 @@ namespace sts::lr::impl { private: struct Entry { Value value; + ncm::TitleId application_id; Key key; bool is_valid; }; private: Entry entries[NumEntries]; + size_t soft_entry_limit; public: - RegisteredData() { + RegisteredData(size_t soft_entry_limit = NumEntries) : soft_entry_limit(soft_entry_limit) { this->Clear(); } - bool Register(const Key &key, const Value &value) { + bool Register(const Key &key, const Value &value, const ncm::TitleId application_id) { /* Try to find an existing value. */ - for (size_t i = 0; i < NumEntries; i++) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { Entry& entry = this->entries[i]; if (entry.is_valid && entry.key == key) { entry.value = value; @@ -47,11 +49,12 @@ namespace sts::lr::impl { } } - for (size_t i = 0; i < NumEntries; i++) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { Entry& entry = this->entries[i]; if (!entry.is_valid) { entry.key = key; entry.value = value; + entry.application_id = application_id; entry.is_valid = true; return true; } @@ -61,7 +64,7 @@ namespace sts::lr::impl { } void Unregister(const Key &key) { - for (size_t i = 0; i < NumEntries; i++) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { Entry& entry = this->entries[i]; if (entry.is_valid && entry.key == key) { entry.is_valid = false; @@ -69,8 +72,17 @@ namespace sts::lr::impl { } } + void UnregisterApplication(ncm::TitleId application_id) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { + Entry& entry = this->entries[i]; + if (entry.application_id == application_id) { + entry.is_valid = false; + } + } + } + bool Find(Value *out, const Key &key) { - for (size_t i = 0; i < NumEntries; i++) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { Entry& entry = this->entries[i]; if (entry.is_valid && entry.key == key) { *out = entry.value; @@ -82,10 +94,34 @@ namespace sts::lr::impl { } void Clear() { - for (size_t i = 0; i < NumEntries; i++) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { this->entries[i].is_valid = false; } } + + void ClearExcluding(const ncm::TitleId* tids, size_t num_tids) { + for (size_t i = 0; i < this->GetSoftEntryLimit(); i++) { + Entry& entry = this->entries[i]; + bool found = false; + + for (size_t j = 0; j < num_tids; j++) { + ncm::TitleId tid = tids[j]; + + if (entry.application_id == tid) { + found = true; + break; + } + } + + if (!found) { + entry.is_valid = false; + } + } + } + + size_t GetSoftEntryLimit() const { + return this->soft_entry_limit; + } }; template diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp index 78f5fa8a0..5b7ec734c 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.cpp @@ -39,8 +39,16 @@ namespace sts::lr { return ResultSuccess; } - Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid) { - if (!this->registered_storages.Register(tid, storage_id)) { + Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorageDeprecated(ncm::StorageId storage_id, ncm::TitleId tid) { + if (!this->registered_storages.Register(tid, storage_id, ncm::TitleId::Invalid)) { + return ResultLrTooManyRegisteredPaths; + } + + return ResultSuccess; + } + + Result AddOnContentLocationResolverInterface::RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid, ncm::TitleId application_tid) { + if (!this->registered_storages.Register(tid, storage_id, application_tid)) { return ResultLrTooManyRegisteredPaths; } @@ -52,4 +60,19 @@ namespace sts::lr { return ResultSuccess; } + Result AddOnContentLocationResolverInterface::RefreshApplicationAddOnContent(InBuffer tids) { + if (tids.num_elements == 0) { + this->registered_storages.Clear(); + return ResultSuccess; + } + + this->registered_storages.ClearExcluding(tids.buffer, tids.num_elements); + return ResultSuccess; + } + + Result AddOnContentLocationResolverInterface::UnregisterApplicationAddOnContent(ncm::TitleId tid) { + this->registered_storages.UnregisterApplication(tid); + return ResultSuccess; + } + } diff --git a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp index 16febe352..882f7edbc 100644 --- a/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_addoncontentlocationresolver.hpp @@ -26,20 +26,31 @@ namespace sts::lr { protected: enum class CommandId { ResolveAddOnContentPath = 0, + RegisterAddOnContentStorageDeprecated = 1, RegisterAddOnContentStorage = 1, UnregisterAllAddOnContentPath = 2, + RefreshApplicationAddOnContent = 3, + UnregisterApplicationAddOnContent = 4, }; private: impl::RegisteredStorages registered_storages; public: + AddOnContentLocationResolverInterface() : registered_storages(GetRuntimeFirmwareVersion() < FirmwareVersion_900 ? 0x800 : 0x2) { /* ... */ } + virtual Result ResolveAddOnContentPath(OutPointerWithServerSize out, ncm::TitleId tid); - virtual Result RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid); + virtual Result RegisterAddOnContentStorageDeprecated(ncm::StorageId storage_id, ncm::TitleId tid); + virtual Result RegisterAddOnContentStorage(ncm::StorageId storage_id, ncm::TitleId tid, ncm::TitleId application_tid); virtual Result UnregisterAllAddOnContentPath(); + virtual Result RefreshApplicationAddOnContent(InBuffer tids); + virtual Result UnregisterApplicationAddOnContent(ncm::TitleId tid); public: DEFINE_SERVICE_DISPATCH_TABLE { - MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, ResolveAddOnContentPath), - MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, RegisterAddOnContentStorage), - MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, UnregisterAllAddOnContentPath), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, ResolveAddOnContentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, RegisterAddOnContentStorageDeprecated, FirmwareVersion_200, FirmwareVersion_810), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, RegisterAddOnContentStorage, FirmwareVersion_900), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, UnregisterAllAddOnContentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, RefreshApplicationAddOnContent, FirmwareVersion_900), + MAKE_SERVICE_COMMAND_META(AddOnContentLocationResolverInterface, UnregisterApplicationAddOnContent, FirmwareVersion_900), }; }; diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp index 939cf3de6..dac7e7b1a 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.cpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.cpp @@ -28,14 +28,14 @@ namespace sts::lr { this->program_redirector.ClearRedirections(); } - void RegisteredLocationResolverInterface::RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid) { - if (!locations->Register(tid, path)) { + void RegisteredLocationResolverInterface::RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid, ncm::TitleId application_id) { + if (!locations->Register(tid, path, application_id)) { locations->Clear(); - locations->Register(tid, path); + locations->Register(tid, path, application_id); } } - bool RegisteredLocationResolverInterface::ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid) { + bool RegisteredLocationResolverInterface::ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid) { if (!redirector->FindRedirection(out, tid)) { if (!locations->Find(out, tid)) { return false; @@ -44,6 +44,24 @@ namespace sts::lr { return true; } + Result RegisteredLocationResolverInterface::RefreshImpl(const ncm::TitleId* excluding_tids, size_t num_tids) { + if (GetRuntimeFirmwareVersion() < FirmwareVersion_900) { + this->ClearRedirections(); + return ResultSuccess; + } + + if (num_tids == 0) { + this->ClearRedirections(); + } else { + this->registered_program_locations.ClearExcluding(excluding_tids, num_tids); + this->registered_html_docs_locations.ClearExcluding(excluding_tids, num_tids); + } + + this->program_redirector.ClearRedirections(excluding_tids, num_tids); + this->html_docs_redirector.ClearRedirections(excluding_tids, num_tids); + return ResultSuccess; + } + Result RegisteredLocationResolverInterface::ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid) { if (!this->ResolvePath(out.pointer, &this->program_redirector, &this->registered_program_locations, tid)) { return ResultLrProgramNotFound; @@ -52,8 +70,13 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid) { - this->RegisterPath(*path.pointer, &this->registered_program_locations, tid); + Result RegisteredLocationResolverInterface::RegisterProgramPathDeprecated(InPointer path, ncm::TitleId tid) { + this->RegisterPath(*path.pointer, &this->registered_program_locations, tid, ncm::TitleId::Invalid); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::RegisterProgramPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id) { + this->RegisterPath(*path.pointer, &this->registered_program_locations, tid, application_id); return ResultSuccess; } @@ -62,11 +85,16 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid) { + Result RegisteredLocationResolverInterface::RedirectProgramPathDeprecated(InPointer path, ncm::TitleId tid) { this->program_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } + Result RegisteredLocationResolverInterface::RedirectProgramPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id) { + this->program_redirector.SetRedirection(tid, application_id, *path.pointer); + return ResultSuccess; + } + Result RegisteredLocationResolverInterface::ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid) { if (!this->ResolvePath(out.pointer, &this->html_docs_redirector, &this->registered_html_docs_locations, tid)) { return ResultLrHtmlDocumentNotFound; @@ -75,8 +103,13 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid) { - this->RegisterPath(*path.pointer, &this->registered_html_docs_locations, tid); + Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPathDeprecated(InPointer path, ncm::TitleId tid) { + this->RegisterPath(*path.pointer, &this->registered_html_docs_locations, tid, ncm::TitleId::Invalid); + return ResultSuccess; + } + + Result RegisteredLocationResolverInterface::RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id) { + this->RegisterPath(*path.pointer, &this->registered_html_docs_locations, tid, application_id); return ResultSuccess; } @@ -85,14 +118,22 @@ namespace sts::lr { return ResultSuccess; } - Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid) { + Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPathDeprecated(InPointer path, ncm::TitleId tid) { this->html_docs_redirector.SetRedirection(tid, *path.pointer); return ResultSuccess; } - Result RegisteredLocationResolverInterface::Refresh() { - this->ClearRedirections(); + Result RegisteredLocationResolverInterface::RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id) { + this->html_docs_redirector.SetRedirection(tid, application_id, *path.pointer); return ResultSuccess; } + Result RegisteredLocationResolverInterface::Refresh() { + return this->RefreshImpl(nullptr, 0); + } + + Result RegisteredLocationResolverInterface::RefreshExcluding(InBuffer tids) { + return this->RefreshImpl(tids.buffer, tids.num_elements); + } + } diff --git a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp index f2e774c31..dfc538303 100644 --- a/stratosphere/ncm/source/lr_registeredlocationresolver.hpp +++ b/stratosphere/ncm/source/lr_registeredlocationresolver.hpp @@ -24,50 +24,69 @@ namespace sts::lr { class RegisteredLocationResolverInterface final : public IServiceObject { + private: + static constexpr size_t MaxRegisteredLocations = 0x20; protected: enum class CommandId { ResolveProgramPath = 0, + RegisterProgramPathDeprecated = 1, RegisterProgramPath = 1, UnregisterProgramPath = 2, + RedirectProgramPathDeprecated = 3, RedirectProgramPath = 3, ResolveHtmlDocumentPath = 4, + RegisterHtmlDocumentPathDeprecated = 5, RegisterHtmlDocumentPath = 5, UnregisterHtmlDocumentPath = 6, + RedirectHtmlDocumentPathDeprecated = 7, RedirectHtmlDocumentPath = 7, Refresh = 8, + RefreshExcluding = 9, }; private: impl::LocationRedirector program_redirector; - impl::RegisteredLocations registered_program_locations; + impl::RegisteredLocations registered_program_locations; impl::LocationRedirector html_docs_redirector; - impl::RegisteredLocations registered_html_docs_locations; + impl::RegisteredLocations registered_html_docs_locations; private: void ClearRedirections(u32 flags = impl::RedirectionFlags_None); - void RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid); - bool ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid); + void RegisterPath(const Path& path, impl::RegisteredLocations* locations, ncm::TitleId tid, ncm::TitleId application_id); + bool ResolvePath(Path* out, impl::LocationRedirector* redirector, impl::RegisteredLocations* locations, ncm::TitleId tid); + Result RefreshImpl(const ncm::TitleId* excluding_tids, size_t num_tids); public: + RegisteredLocationResolverInterface() : registered_program_locations(GetRuntimeFirmwareVersion() < FirmwareVersion_900 ? 0x10 : MaxRegisteredLocations), registered_html_docs_locations(GetRuntimeFirmwareVersion() < FirmwareVersion_900 ? 0x10 : MaxRegisteredLocations) { /* ... */ } ~RegisteredLocationResolverInterface(); Result ResolveProgramPath(OutPointerWithServerSize out, ncm::TitleId tid); - Result RegisterProgramPath(InPointer path, ncm::TitleId tid); + Result RegisterProgramPathDeprecated(InPointer path, ncm::TitleId tid); + Result RegisterProgramPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id); Result UnregisterProgramPath(ncm::TitleId tid); - Result RedirectProgramPath(InPointer path, ncm::TitleId tid); + Result RedirectProgramPathDeprecated(InPointer path, ncm::TitleId tid); + Result RedirectProgramPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id); Result ResolveHtmlDocumentPath(OutPointerWithServerSize out, ncm::TitleId tid); - Result RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid); + Result RegisterHtmlDocumentPathDeprecated(InPointer path, ncm::TitleId tid); + Result RegisterHtmlDocumentPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id); Result UnregisterHtmlDocumentPath(ncm::TitleId tid); - Result RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid); + Result RedirectHtmlDocumentPathDeprecated(InPointer path, ncm::TitleId tid); + Result RedirectHtmlDocumentPath(InPointer path, ncm::TitleId tid, ncm::TitleId application_id); Result Refresh(); + Result RefreshExcluding(InBuffer tids); public: DEFINE_SERVICE_DISPATCH_TABLE { MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, ResolveProgramPath), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterProgramPath), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterProgramPathDeprecated, FirmwareVersion_100, FirmwareVersion_810), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterProgramPath, FirmwareVersion_900), MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, UnregisterProgramPath), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectProgramPath), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, ResolveHtmlDocumentPath, FirmwareVersion_200), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterHtmlDocumentPath, FirmwareVersion_200), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, UnregisterHtmlDocumentPath, FirmwareVersion_200), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectHtmlDocumentPath, FirmwareVersion_200), - MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, Refresh, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectProgramPathDeprecated, FirmwareVersion_100, FirmwareVersion_810), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectProgramPath, FirmwareVersion_900), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, ResolveHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterHtmlDocumentPathDeprecated, FirmwareVersion_200, FirmwareVersion_810), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RegisterHtmlDocumentPath, FirmwareVersion_900), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, UnregisterHtmlDocumentPath, FirmwareVersion_200), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectHtmlDocumentPathDeprecated, FirmwareVersion_200, FirmwareVersion_810), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RedirectHtmlDocumentPathDeprecated, FirmwareVersion_900), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, Refresh, FirmwareVersion_700), + MAKE_SERVICE_COMMAND_META(RegisteredLocationResolverInterface, RefreshExcluding, FirmwareVersion_900), }; };