diff --git a/Utilities/File.cpp b/Utilities/File.cpp index 896fda922b..05a3f584f8 100644 --- a/Utilities/File.cpp +++ b/Utilities/File.cpp @@ -2,6 +2,8 @@ #include "StrFmt.h" #include "Macro.h" #include "SharedMutex.h" +#include "BEType.h" +#include "Crypto/sha1.h" #include #include @@ -1207,6 +1209,78 @@ const std::string& fs::get_executable_dir() return s_dir; } +std::string fs::get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix) +{ + static const std::string s_dir = [] + { + const std::string& dir = get_config_dir() + "/data/"; + + if (!is_dir(dir) && !create_path(dir)) + { + return get_config_dir(); + } + + return dir; + }(); + + std::vector buf; + buf.reserve(location.size() + 1); + + // Normalize location + for (char c : location) + { +#ifdef _WIN32 + if (c == '/' || c == '\\') +#else + if (c == '/') +#endif + { + if (buf.empty() || buf.back() != '/') + { + buf.push_back('/'); + } + + continue; + } + + buf.push_back(c); + } + + // Calculate hash + u8 hash[20]; + sha1(buf.data(), buf.size(), hash); + + // Concatenate + std::string&& result = fmt::format("%s%s/%016llx%08x-%s/", s_dir, prefix, reinterpret_cast&>(hash[0]), reinterpret_cast&>(hash[8]), suffix); + + if (!is_dir(result)) + { + // Create dir if necessary + if (create_path(result)) + { + // Acknowledge original location + file(result + ".location", rewrite).write(buf); + } + } + + return result; +} + +std::string fs::get_data_dir(const std::string& prefix, const std::string& path) +{ +#ifdef _WIN32 + const auto& delim = "/\\"; +#else + const auto& delim = "/"; +#endif + + // Extract file name and location + const std::string& location = fs::get_parent_dir(path); + const std::size_t name_pos = path.find_first_not_of(delim, location.size()); + + return fs::get_data_dir(prefix, location, name_pos == -1 ? std::string{} : path.substr(name_pos)); +} + void fs::remove_all(const std::string& path, bool remove_root) { for (const auto& entry : dir(path)) diff --git a/Utilities/File.h b/Utilities/File.h index aaa2c9ee41..25ebe364b2 100644 --- a/Utilities/File.h +++ b/Utilities/File.h @@ -439,6 +439,12 @@ namespace fs // Get executable directory const std::string& get_executable_dir(); + // Get data/cache directory for specified prefix and suffix + std::string get_data_dir(const std::string& prefix, const std::string& location, const std::string& suffix); + + // Get data/cache directory for specified prefix and path (suffix will be filename) + std::string get_data_dir(const std::string& prefix, const std::string& path); + // Delete directory and all its contents recursively void remove_all(const std::string& path, bool remove_root = true); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 0c7e21fd17..8627aad7d9 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -204,6 +204,7 @@ void Emulator::Load() const auto _psf = psf::load_object(fs::file(elf_dir + "/../PARAM.SFO")); m_title = psf::get_string(_psf, "TITLE", m_path); m_title_id = psf::get_string(_psf, "TITLE_ID"); + fs::get_data_dir(m_title_id, m_path); LOG_NOTICE(LOADER, "Title: %s", GetTitle()); LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());