diff --git a/src/client/component/database.cpp b/src/client/component/database.cpp new file mode 100644 index 00000000..bd47c246 --- /dev/null +++ b/src/client/component/database.cpp @@ -0,0 +1,58 @@ +#include +#include "loader/component_loader.hpp" + +#include "game/dvars.hpp" +#include "game/game.hpp" + +#include +#include + +namespace database +{ + namespace + { + game::dvar_t* db_filesysImpl = nullptr; + + utils::hook::detour sub_140272EC0_hook; + + game::DB_FileSysInterface* sub_140272EC0_stub() + { + switch (db_filesysImpl->current.integer) + { + case 0: + return reinterpret_cast(0x140BE82F8); // ptr to vtable of BnetTACTVFSManager (implements DB_FileSysInterface) + case 1: + return reinterpret_cast(0x140BEFDC0); // ptr to vtable of DiskFS (implements DB_FileSysInterface) + default: + return nullptr; // this should not happen + } + } + + + } + + class component final : public component_interface + { + public: + void post_unpack() override + { + static const char* values[] = { + "BnetTACTVFSManager", // (load files from CASC) + "DiskFS", // (load files from disk) + nullptr + }; + + int default_value = utils::flags::has_flag("disk") ? 1 : 0; + db_filesysImpl = dvars::register_enum("db_filesysImpl", values, default_value, game::DVAR_FLAG_READ); + + if (default_value == 1) + { + utils::hook::nop(0x1405A4868, 22); // TACT related stuff that's pointless if we're using DiskFS + } + + sub_140272EC0_hook.create(0x140272EC0, sub_140272EC0_stub); + } + }; +} + +REGISTER_COMPONENT(database::component) diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index f02f8d9f..a76d9cda 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -2238,6 +2238,13 @@ namespace dvars return game::Dvar_RegisterBool(hash, "", value, flags); } + game::dvar_t* register_enum(const std::string& name, const char** valueList, int defaultIndex, game::DvarFlags flags) + { + dvar_list.insert(name); + const auto hash = game::generateHashValue(name.data()); + return game::Dvar_RegisterEnum(hash, "", valueList, defaultIndex, flags); + } + game::dvar_t* register_float(const std::string& name, float value, float min, float max, game::DvarFlags flags) { diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index 6a3a4854..b0ebc2ba 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -31,6 +31,7 @@ namespace dvars game::dvar_t* register_int(const std::string& name, int value, int min, int max, game::DvarFlags flags); game::dvar_t* register_bool(const std::string& name, bool value, game::DvarFlags flags); + game::dvar_t* register_enum(const std::string& name, const char** valueList, int defaultIndex, game::DvarFlags flags); game::dvar_t* register_float(const std::string& name, float value, float min, float max, game::DvarFlags flags); game::dvar_t* register_vec4(const std::string& name, float x, float y, float z, float w, float min, float max, game::DvarFlags flags); } diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 8c3017c2..0d33a298 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1079,6 +1079,45 @@ namespace game bool startsolid; // Confirmed in PM_JitterPoint }; + enum Sys_Folder : std::int32_t + { + SF_ZONE = 0x0, + SF_ZONE_LOC = 0x1, + SF_VIDEO = 0x2, + SF_VIDEO_LOC = 0x3, + SF_PAKFILE = 0x4, + SF_PAKFILE_LOC = 0x5, + SF_ZONE_REGION = 0x6, + SF_COUNT = 0x7, + }; + + enum FileSysResult : std::int32_t + { + FILESYSRESULT_SUCCESS = 0x0, + FILESYSRESULT_EOF = 0x1, + FILESYSRESULT_ERROR = 0x2, + }; + + struct DB_IFileSysFile; + + struct DB_FileSysInterface; + + // this is a best guess, interface doesn't match up exactly w/other games (IW8) + struct DB_FileSysInterface_vtbl + { + DB_IFileSysFile* (__fastcall* OpenFile)(DB_FileSysInterface* _this, Sys_Folder folder, const char* filename); + FileSysResult (__fastcall* StartRead)(DB_FileSysInterface* _this, DB_IFileSysFile* handle, unsigned __int64 /* idk */, unsigned __int64 offset, unsigned __int64 size); + FileSysResult (__fastcall* NumberOfBytesRead)(DB_FileSysInterface* _this, DB_IFileSysFile* handle, unsigned __int64* bytesRead); + __int64 (__fastcall* Size)(DB_FileSysInterface* _this, DB_IFileSysFile* handle); + void (__fastcall* Close)(DB_FileSysInterface* _this, DB_IFileSysFile* handle); + bool (__fastcall* Exists)(DB_FileSysInterface* _this, Sys_Folder folder, const char* filename); + }; + + struct DB_FileSysInterface + { + DB_FileSysInterface_vtbl* vftbl; + }; + namespace hks { struct GenericChunkHeader diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 6a885aa0..4e8a6cc8 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -43,6 +43,7 @@ namespace game WEAK symbol Dvar_FindVar{0x140618F90}; WEAK symbol Dvar_GetCombinedString{0x1405A75D0}; WEAK symbol Dvar_RegisterBool{0x140617BB0}; + WEAK symbol Dvar_RegisterEnum{0x140617E90}; WEAK symbol Dvar_RegisterInt{0x140618090}; WEAK symbol Dvar_RegisterFloat{0x140617F80};