mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	game_list: Implement caching for game list
Preserves list of add ons and the icon, which are the two costliest parts of game list population.
This commit is contained in:
		
							parent
							
								
									180f22f17e
								
							
						
					
					
						commit
						f95bdb5088
					
				@ -9,6 +9,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <QDir>
 | 
					#include <QDir>
 | 
				
			||||||
#include <QFileInfo>
 | 
					#include <QFileInfo>
 | 
				
			||||||
 | 
					#include <QSettings>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common/common_paths.h"
 | 
					#include "common/common_paths.h"
 | 
				
			||||||
#include "common/file_util.h"
 | 
					#include "common/file_util.h"
 | 
				
			||||||
@ -30,13 +31,101 @@
 | 
				
			|||||||
#include "yuzu/ui_settings.h"
 | 
					#include "yuzu/ui_settings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					T GetGameListCachedObject(const std::string& filename, const std::string& ext,
 | 
				
			||||||
 | 
					                          const std::function<T()>& generator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					QString GetGameListCachedObject(const std::string& filename, const std::string& ext,
 | 
				
			||||||
 | 
					                                const std::function<QString()>& generator) {
 | 
				
			||||||
 | 
					    if (!UISettings::values.cache_game_list || filename == "0000000000000000")
 | 
				
			||||||
 | 
					        return generator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto& path = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + "game_list" +
 | 
				
			||||||
 | 
					                       DIR_SEP + filename + "." + ext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FileUtil::CreateFullPath(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!FileUtil::Exists(path)) {
 | 
				
			||||||
 | 
					        const auto str = generator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::ofstream stream(path);
 | 
				
			||||||
 | 
					        if (stream)
 | 
				
			||||||
 | 
					            stream << str.toStdString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stream.close();
 | 
				
			||||||
 | 
					        return str;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::ifstream stream(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (stream) {
 | 
				
			||||||
 | 
					        const std::string out(std::istreambuf_iterator<char>{stream},
 | 
				
			||||||
 | 
					                              std::istreambuf_iterator<char>{});
 | 
				
			||||||
 | 
					        stream.close();
 | 
				
			||||||
 | 
					        return QString::fromStdString(out);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return generator();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <>
 | 
				
			||||||
 | 
					std::pair<std::vector<u8>, std::string> GetGameListCachedObject(
 | 
				
			||||||
 | 
					    const std::string& filename, const std::string& ext,
 | 
				
			||||||
 | 
					    const std::function<std::pair<std::vector<u8>, std::string>()>& generator) {
 | 
				
			||||||
 | 
					    if (!UISettings::values.cache_game_list || filename == "0000000000000000")
 | 
				
			||||||
 | 
					        return generator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto& path1 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
 | 
				
			||||||
 | 
					                        "game_list" + DIR_SEP + filename + ".jpeg";
 | 
				
			||||||
 | 
					    const auto& path2 = FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP +
 | 
				
			||||||
 | 
					                        "game_list" + DIR_SEP + filename + ".appname.txt";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FileUtil::CreateFullPath(path1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!FileUtil::Exists(path1) || !FileUtil::Exists(path2)) {
 | 
				
			||||||
 | 
					        const auto [icon, nacp] = generator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        FileUtil::IOFile file1(path1, "wb");
 | 
				
			||||||
 | 
					        file1.Resize(icon.size());
 | 
				
			||||||
 | 
					        file1.WriteBytes(icon.data(), icon.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::ofstream stream2(path2, std::ios::out);
 | 
				
			||||||
 | 
					        if (stream2)
 | 
				
			||||||
 | 
					            stream2 << nacp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        file1.Close();
 | 
				
			||||||
 | 
					        stream2.close();
 | 
				
			||||||
 | 
					        return std::make_pair(icon, nacp);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FileUtil::IOFile file1(path1, "rb");
 | 
				
			||||||
 | 
					    std::ifstream stream2(path2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<u8> vec(file1.GetSize());
 | 
				
			||||||
 | 
					    file1.ReadBytes(vec.data(), vec.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (stream2 && !vec.empty()) {
 | 
				
			||||||
 | 
					        const std::string out(std::istreambuf_iterator<char>{stream2},
 | 
				
			||||||
 | 
					                              std::istreambuf_iterator<char>{});
 | 
				
			||||||
 | 
					        stream2.close();
 | 
				
			||||||
 | 
					        return std::make_pair(vec, out);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return generator();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca,
 | 
					void GetMetadataFromControlNCA(const FileSys::PatchManager& patch_manager, const FileSys::NCA& nca,
 | 
				
			||||||
                               std::vector<u8>& icon, std::string& name) {
 | 
					                               std::vector<u8>& icon, std::string& name) {
 | 
				
			||||||
    auto [nacp, icon_file] = patch_manager.ParseControlNCA(nca);
 | 
					    auto res = GetGameListCachedObject<std::pair<std::vector<u8>, std::string>>(
 | 
				
			||||||
    if (icon_file != nullptr)
 | 
					        fmt::format("{:016X}", patch_manager.GetTitleID()), {}, [&patch_manager, &nca] {
 | 
				
			||||||
        icon = icon_file->ReadAllBytes();
 | 
					            const auto [nacp, icon_f] = patch_manager.ParseControlNCA(nca);
 | 
				
			||||||
    if (nacp != nullptr)
 | 
					            return std::make_pair(icon_f->ReadAllBytes(), nacp->GetApplicationName());
 | 
				
			||||||
        name = nacp->GetApplicationName();
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    icon = std::move(res.first);
 | 
				
			||||||
 | 
					    name = std::move(res.second);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool HasSupportedFileExtension(const std::string& file_name) {
 | 
					bool HasSupportedFileExtension(const std::string& file_name) {
 | 
				
			||||||
@ -114,8 +203,11 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (UISettings::values.show_add_ons) {
 | 
					    if (UISettings::values.show_add_ons) {
 | 
				
			||||||
        list.insert(
 | 
					        const auto patch_versions = GetGameListCachedObject<QString>(
 | 
				
			||||||
            2, new GameListItem(FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable())));
 | 
					            fmt::format("{:016X}", patch.GetTitleID()), "pv.txt", [&patch, &loader] {
 | 
				
			||||||
 | 
					                return FormatPatchNameVersions(patch, loader, loader.IsRomFSUpdatable());
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        list.insert(2, new GameListItem(patch_versions));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return list;
 | 
					    return list;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user