simplify title cache loading.

This commit is contained in:
ITotalJustice
2025-06-21 15:32:55 +01:00
parent 4d27bf5492
commit 1f7179e941
9 changed files with 714 additions and 1015 deletions

View File

@@ -0,0 +1,96 @@
#pragma once
// #include <optional>
// #include <variant>
// #include <list>
// #include <string>
#include "fs.hpp"
#include <optional>
#include <span>
#include <vector>
#include <memory>
#include <functional>
#include <switch.h>
namespace sphaira::title {
constexpr u32 ContentMetaTypeToContentFlag(u8 meta_type) {
if (meta_type & 0x80) {
return 1 << (meta_type - 0x80);
}
return 0;
}
enum ContentFlag {
ContentFlag_Application = ContentMetaTypeToContentFlag(NcmContentMetaType_Application),
ContentFlag_Patch = ContentMetaTypeToContentFlag(NcmContentMetaType_Patch),
ContentFlag_AddOnContent = ContentMetaTypeToContentFlag(NcmContentMetaType_AddOnContent),
ContentFlag_DataPatch = ContentMetaTypeToContentFlag(NcmContentMetaType_DataPatch),
// nca locations where a control.nacp can exist.
ContentFlag_Nacp = ContentFlag_Application | ContentFlag_Patch,
// all of the above.
ContentFlag_All = ContentFlag_Application | ContentFlag_Patch | ContentFlag_AddOnContent | ContentFlag_DataPatch,
};
enum class NacpLoadStatus {
// not yet attempted to be loaded.
None,
// started loading.
Progress,
// loaded, ready to parse.
Loaded,
// failed to load, do not attempt to load again!
Error,
};
struct ThreadResultData {
u64 id{};
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLanguageEntry lang{};
NacpLoadStatus status{NacpLoadStatus::None};
};
using MetaEntries = std::vector<NsApplicationContentMetaStatus>;
// starts background thread.
Result Init();
void Exit();
// adds new entry to queue.
void Push(u64 app_id);
// adds array of entries to queue.
void Push(std::span<const u64> app_ids);
#if 0
// removes entry from the queue into out.
void Pop(u64 app_id, std::vector<ThreadResultData>& out);
// removes array of entries from the queue into out.
void Pop(std::span<const u64> app_ids, std::vector<ThreadResultData>& out);
// removes all entries from the queue into out.
void Pop(std::vector<ThreadResultData>& out);
#endif
// gets entry without removing it from the queue.
auto Get(u64 app_id) -> std::optional<ThreadResultData>;
// gets array of entries without removing it from the queue.
void Get(std::span<const u64> app_ids, std::vector<ThreadResultData>& out);
auto GetNcmCs(u8 storage_id) -> NcmContentStorage&;
auto GetNcmDb(u8 storage_id) -> NcmContentMetaDatabase&;
// gets all meta entries for an id.
Result GetMetaEntries(u64 id, MetaEntries& out, u32 flags = ContentFlag_All);
// returns the nca path of a control nca.
Result GetControlPathFromStatus(const NsApplicationContentMetaStatus& status, u64* out_program_id, fs::FsPath* out_path);
// single threaded title info fetch.
auto LoadControlEntry(u64 id, bool* cached = nullptr) -> ThreadResultData;
// taken from nxdumptool.
void utilsReplaceIllegalCharacters(char *str, bool ascii_only);
} // namespace sphaira::title

View File

@@ -2,6 +2,7 @@
#include "ui/menus/grid_menu_base.hpp"
#include "ui/list.hpp"
#include "title_info.hpp"
#include "fs.hpp"
#include "option.hpp"
#include <memory>
@@ -10,17 +11,6 @@
namespace sphaira::ui::menu::game {
enum class NacpLoadStatus {
// not yet attempted to be loaded.
None,
// started loading.
Progress,
// loaded, ready to parse.
Loaded,
// failed to load, do not attempt to load again!
Error,
};
struct Entry {
u64 app_id{};
NacpLanguageEntry lang{};
@@ -29,7 +19,7 @@ struct Entry {
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLoadStatus status{NacpLoadStatus::None};
title::NacpLoadStatus status{title::NacpLoadStatus::None};
auto GetName() const -> const char* {
return lang.name;
@@ -40,45 +30,6 @@ struct Entry {
}
};
struct ThreadResultData {
u64 id{};
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLanguageEntry lang{};
NacpLoadStatus status{NacpLoadStatus::None};
};
struct ThreadData {
ThreadData(bool title_cache);
void Run();
void Close();
void Push(u64 id);
void Push(std::span<const Entry> entries);
void Pop(std::vector<ThreadResultData>& out);
auto IsRunning() const -> bool {
return m_running;
}
auto IsTitleCacheEnabled() const {
return m_title_cache;
}
private:
UEvent m_uevent{};
Mutex m_mutex_id{};
Mutex m_mutex_result{};
bool m_title_cache{};
// app_ids pushed to the queue, signal uevent when pushed.
std::vector<u64> m_ids{};
// control data pushed to the queue.
std::vector<ThreadResultData> m_result{};
std::atomic_bool m_running{};
};
enum SortType {
SortType_Updated,
};
@@ -144,9 +95,6 @@ private:
bool m_is_reversed{};
bool m_dirty{};
std::unique_ptr<ThreadData> m_thread_data{};
Thread m_thread{};
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Updated};
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};
option::OptionLong m_layout{INI_SECTION, "layout", LayoutType::LayoutType_Grid};

View File

@@ -151,8 +151,8 @@ struct ApplicationEntry {
u64 app_id{};
u32 version{};
u8 key_gen{};
std::unique_ptr<NsApplicationControlData> control{};
u64 control_size{};
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLanguageEntry lang_entry{};
std::vector<GcCollections> application{};

View File

@@ -2,6 +2,7 @@
#include "ui/menus/grid_menu_base.hpp"
#include "ui/list.hpp"
#include "title_info.hpp"
#include "fs.hpp"
#include "option.hpp"
#include "dumper.hpp"
@@ -11,17 +12,6 @@
namespace sphaira::ui::menu::save {
enum class NacpLoadStatus {
// not yet attempted to be loaded.
None,
// started loading.
Progress,
// loaded, ready to parse.
Loaded,
// failed to load, do not attempt to load again!
Error,
};
struct Entry final : FsSaveDataInfo {
NacpLanguageEntry lang{};
int image{};
@@ -29,7 +19,7 @@ struct Entry final : FsSaveDataInfo {
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLoadStatus status{NacpLoadStatus::None};
title::NacpLoadStatus status{title::NacpLoadStatus::None};
auto GetName() const -> const char* {
return lang.name;
@@ -40,37 +30,6 @@ struct Entry final : FsSaveDataInfo {
}
};
struct ThreadResultData {
u64 id{};
std::shared_ptr<NsApplicationControlData> control{};
u64 jpeg_size{};
NacpLanguageEntry lang{};
NacpLoadStatus status{NacpLoadStatus::None};
};
struct ThreadData {
ThreadData();
auto IsRunning() const -> bool;
void Run();
void Close();
void Push(u64 id);
void Push(std::span<const Entry> entries);
void Pop(std::vector<ThreadResultData>& out);
private:
UEvent m_uevent{};
Mutex m_mutex_id{};
Mutex m_mutex_result{};
// app_ids pushed to the queue, signal uevent when pushed.
std::vector<u64> m_ids{};
// control data pushed to the queue.
std::vector<ThreadResultData> m_result{};
std::atomic_bool m_running{};
};
enum SortType {
SortType_Updated,
};
@@ -145,9 +104,6 @@ private:
s64 m_account_index{};
u8 m_data_type{FsSaveDataType_Account};
ThreadData m_thread_data{};
Thread m_thread{};
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_Updated};
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};
option::OptionLong m_layout{INI_SECTION, "layout", LayoutType::LayoutType_Grid};