Skip to content

Commit 3cfaec1

Browse files
committed
feat(zones): auto-load patch fastfiles with override priority
also disabled gamepad + xlive for stability
1 parent 58ce067 commit 3cfaec1

5 files changed

Lines changed: 156 additions & 11 deletions

File tree

src/component/engine/zones/fastfiles.cpp

Lines changed: 145 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,151 @@
44
#include "game/game.hpp"
55

66
#include "fastfiles.hpp"
7-
#include "component/engine/console/command.hpp"
8-
#include "component/engine/console/console.hpp"
97

108
#include <utils/hook.hpp>
11-
#include <utils/memory.hpp>
12-
#include <utils/io.hpp>
9+
#include <utils/nt.hpp>
1310

1411
namespace fastfiles
1512
{
13+
namespace
14+
{
15+
utils::hook::detour db_load_xassets_hook;
16+
17+
bool patch_consolation_loaded = false;
18+
bool patch_mp_loaded = false;
19+
bool patch_consolation_attempted = false;
20+
bool patch_mp_attempted = false;
21+
22+
bool zone_name_equals(const char* lhs, const char* rhs)
23+
{
24+
return lhs != nullptr && rhs != nullptr && _stricmp(lhs, rhs) == 0;
25+
}
26+
27+
bool has_zone(const game::XZoneInfo* zone_info, const int zone_count, const char* name)
28+
{
29+
if (zone_info == nullptr || zone_count <= 0 || name == nullptr)
30+
{
31+
return false;
32+
}
33+
34+
for (auto index = 0; index < zone_count; ++index)
35+
{
36+
if (zone_name_equals(zone_info[index].name, name))
37+
{
38+
return true;
39+
}
40+
}
41+
42+
return false;
43+
}
44+
45+
bool zone_file_exists(const char* zone_name)
46+
{
47+
if (zone_name == nullptr || zone_name[0] == '\0')
48+
{
49+
return false;
50+
}
51+
52+
const auto zone_file_name = std::string(zone_name) + ".ff";
53+
const std::array roots
54+
{
55+
std::filesystem::path(utils::nt::get_host_module().get_folder()) / "zone",
56+
std::filesystem::current_path() / "zone",
57+
};
58+
59+
for (const auto& root : roots)
60+
{
61+
std::error_code ec{};
62+
if (!std::filesystem::exists(root, ec))
63+
{
64+
continue;
65+
}
66+
67+
if (std::filesystem::exists(root / zone_file_name, ec))
68+
{
69+
return true;
70+
}
71+
72+
for (std::filesystem::recursive_directory_iterator it(root, ec), end; it != end && !ec; it.increment(ec))
73+
{
74+
if (!it->is_regular_file(ec))
75+
{
76+
continue;
77+
}
78+
79+
const auto filename = it->path().filename().string();
80+
if (_stricmp(filename.c_str(), zone_file_name.c_str()) == 0)
81+
{
82+
return true;
83+
}
84+
}
85+
}
86+
87+
return false;
88+
}
89+
90+
game::XZoneInfo make_override_zone(const char* zone_name)
91+
{
92+
game::XZoneInfo zone_info{};
93+
zone_info.name = zone_name;
94+
zone_info.allocFlags = 2;
95+
zone_info.freeFlags = 0;
96+
97+
return zone_info;
98+
}
99+
100+
int db_load_xassets_stub(game::XZoneInfo* zone_info, const int zone_count, const int sync)
101+
{
102+
patch_consolation_loaded = patch_consolation_loaded || has_zone(zone_info, zone_count, "patch_consolation");
103+
patch_mp_loaded = patch_mp_loaded || has_zone(zone_info, zone_count, "patch_mp");
104+
105+
const auto loading_common_fastfiles = has_zone(zone_info, zone_count, "common_mp");
106+
const auto should_load_patch_consolation = loading_common_fastfiles
107+
&& !patch_consolation_attempted
108+
&& !patch_consolation_loaded;
109+
110+
const auto should_load_patch_mp = loading_common_fastfiles
111+
&& !patch_mp_attempted
112+
&& !patch_mp_loaded;
113+
114+
const auto result = db_load_xassets_hook.invoke<int>(zone_info, zone_count, sync);
115+
if (!result)
116+
{
117+
return result;
118+
}
119+
120+
std::vector<game::XZoneInfo> patch_zones{};
121+
if (should_load_patch_mp)
122+
{
123+
patch_mp_attempted = true;
124+
patch_zones.push_back(make_override_zone("patch_mp"));
125+
patch_mp_loaded = true;
126+
}
127+
128+
if (should_load_patch_consolation)
129+
{
130+
patch_consolation_attempted = true;
131+
if (zone_file_exists("patch_consolation"))
132+
{
133+
patch_zones.push_back(make_override_zone("patch_consolation"));
134+
patch_consolation_loaded = true;
135+
}
136+
else
137+
{
138+
game::Com_Printf(16, "Skipping override fastfile 'patch_consolation' because it was not found\n");
139+
}
140+
}
141+
142+
if (!patch_zones.empty())
143+
{
144+
game::Com_Printf(16, "Loading patch fastfiles with override priority\n");
145+
db_load_xassets_hook.invoke<int>(patch_zones.data(), static_cast<int>(patch_zones.size()), sync);
146+
}
147+
148+
return result;
149+
}
150+
}
151+
16152
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool include_override)
17153
{
18154
game::DB_EnumXAssets_FastFile(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
@@ -24,11 +160,11 @@ namespace fastfiles
24160

25161
class component final : public component_interface
26162
{
27-
/*public:
28-
void post_unpack() override
29-
{
30-
//Placeholder for now, so it builds
31-
}*/
163+
public:
164+
void post_load() override
165+
{
166+
db_load_xassets_hook.create(game::DB_LoadXAssets, db_load_xassets_stub);
167+
}
32168
};
33169
}
34170

src/component/gamepad/sdl_input.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ namespace sdl_input
1616
};
1717
}
1818

19-
REGISTER_COMPONENT(sdl_input::component)
19+
//REGISTER_COMPONENT(sdl_input::component)

src/component/gamepad/xinput.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1449,4 +1449,4 @@ namespace gamepad
14491449
}
14501450
}
14511451

1452-
REGISTER_COMPONENT(xinput::component)
1452+
//REGISTER_COMPONENT(xinput::component)

src/game/structs.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,14 @@ namespace game
640640
XAssetHeader header;
641641
};
642642

643+
struct XZoneInfo
644+
{
645+
const char* name;
646+
int allocFlags;
647+
int freeFlags;
648+
};
649+
static_assert(sizeof(XZoneInfo) == 12);
650+
643651
struct XAssetEntry
644652
{
645653
XAsset asset;

src/game/symbols.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace game
2121
WEAK symbol<void()> ConDrawInput_DrawInput{ game_offset(0x103175D0) };
2222
WEAK symbol<Font_s*> con_font{ game_offset(0x1125C5B4) };
2323

24+
WEAK symbol<int(XZoneInfo* zoneInfo, int zoneCount, int sync)> DB_LoadXAssets{ game_offset(0x103E1CF0) };
2425
WEAK symbol<void(XAssetType type, void(*)(XAssetHeader, void*), const void* userdata, bool overrides)> DB_EnumXAssets_FastFile{ game_offset(0x103DFCA0) };
2526
WEAK symbol<XAssetHeader(XAssetType type, const char* name)> DB_FindXAssetHeader{ game_offset(0x103E2260) };
2627
WEAK symbol<XAssetHeader(XAssetType type, const char* name, int create_default)> DB_FindXAssetHeader_Internal{ game_offset(0x103E1EE0) };

0 commit comments

Comments
 (0)