Support loading fastfiles from appdata

This commit is contained in:
Federico Cecchetto 2022-09-10 22:59:55 +02:00
parent 9fcf994b35
commit cfe8713805

View File

@ -6,6 +6,7 @@
#include "fastfiles.hpp" #include "fastfiles.hpp"
#include "command.hpp" #include "command.hpp"
#include "console.hpp" #include "console.hpp"
#include "filesystem.hpp"
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <utils/concurrency.hpp> #include <utils/concurrency.hpp>
@ -148,15 +149,11 @@ namespace fastfiles
if (localized) if (localized)
{ {
const auto language = game::SEH_GetCurrentLanguageCode(); const auto language = game::SEH_GetCurrentLanguageCode();
if (!try_load_zone(language + "_"s + name, false) && language != "eng"s) try_load_zone(language + "_"s + name, false);
{
try_load_zone("eng_" + name, false);
}
} }
if (!fastfiles::exists(name)) if (!fastfiles::exists(name))
{ {
console::debug("fastfile %s doesn't exist\n", name.data());
return false; return false;
} }
@ -168,32 +165,73 @@ namespace fastfiles
return true; return true;
} }
HANDLE find_fastfile(const std::string& filename, bool check_loc_folder)
{
std::string path{};
std::string loc_folder{};
if (check_loc_folder && game::DB_IsLocalized(filename.data()))
{
const auto handle = find_fastfile(filename, false);
if (handle != reinterpret_cast<HANDLE>(-1))
{
return handle;
}
loc_folder = game::SEH_GetCurrentLanguageName() + "/"s;
}
if (!filesystem::find_file(loc_folder + filename, &path))
{
if (!filesystem::find_file("zone/"s + loc_folder + filename, &path))
{
return reinterpret_cast<HANDLE>(-1);
}
}
return CreateFileA(path.data(), 0x80000000, 1u, 0, 3u, 0x60000000u, 0);
}
utils::hook::detour sys_createfile_hook; utils::hook::detour sys_createfile_hook;
HANDLE sys_create_file_stub(game::Sys_Folder folder, const char* base_filename) HANDLE sys_create_file_stub(game::Sys_Folder folder, const char* base_filename)
{ {
const auto* fs_basepath = game::Dvar_FindVar("fs_basepath"); const auto* fs_basepath = game::Dvar_FindVar("fs_basepath");
const auto* fs_game = game::Dvar_FindVar("fs_game"); const auto* fs_game = game::Dvar_FindVar("fs_game");
std::string dir = fs_basepath ? fs_basepath->current.string : ""; const std::string dir = fs_basepath ? fs_basepath->current.string : "";
std::string mod_dir = fs_game ? fs_game->current.string : ""; const std::string mod_dir = fs_game ? fs_game->current.string : "";
const std::string name = base_filename;
if (base_filename == "mod.ff"s) if (name == "mod.ff")
{ {
if (!mod_dir.empty()) if (!mod_dir.empty())
{ {
auto path = utils::string::va("%s\\%s\\%s", dir.data(), mod_dir.data(), base_filename); const auto path = utils::string::va("%s\\%s\\%s",
dir.data(), mod_dir.data(), base_filename);
if (utils::io::file_exists(path)) if (utils::io::file_exists(path))
{ {
return CreateFileA(path, 0x80000000, 1u, 0, 3u, 0x60000000u, 0); return CreateFileA(path, 0x80000000, 1u, 0, 3u, 0x60000000u, 0);
} }
} }
return (HANDLE)-1;
return reinterpret_cast<HANDLE>(-1);
}
if (name.ends_with(".ff"))
{
const auto handle = find_fastfile(name, true);
if (handle != reinterpret_cast<HANDLE>(-1))
{
return handle;
}
} }
return sys_createfile_hook.invoke<HANDLE>(folder, base_filename); return sys_createfile_hook.invoke<HANDLE>(folder, base_filename);
} }
template <typename T> inline void merge(std::vector<T>* target, T* source, size_t length) template <typename T>
inline void merge(std::vector<T>* target, T* source, size_t length)
{ {
if (source) if (source)
{ {
@ -204,7 +242,8 @@ namespace fastfiles
} }
} }
template <typename T> inline void merge(std::vector<T>* target, std::vector<T> source) template <typename T>
inline void merge(std::vector<T>* target, std::vector<T> source)
{ {
for (auto& entry : source) for (auto& entry : source)
{ {
@ -252,8 +291,10 @@ namespace fastfiles
bool exists(const std::string& zone) bool exists(const std::string& zone)
{ {
const auto is_localized = game::DB_IsLocalized(zone.data()); const auto is_localized = game::DB_IsLocalized(zone.data());
const auto handle = game::Sys_CreateFile((is_localized ? game::SF_ZONE_LOC : game::SF_ZONE), utils::string::va("%s.ff", zone.data())); const auto handle = game::Sys_CreateFile((is_localized ? game::SF_ZONE_LOC : game::SF_ZONE),
if (handle != (HANDLE)-1) utils::string::va("%s.ff", zone.data()));
if (handle != reinterpret_cast<HANDLE>(-1))
{ {
CloseHandle(handle); CloseHandle(handle);
return true; return true;