add custom ff loading
This commit is contained in:
parent
7525fea887
commit
b490ed401a
@ -12,6 +12,8 @@
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
//#define XFILE_DEBUG
|
||||
|
||||
namespace fastfiles
|
||||
@ -107,6 +109,155 @@ namespace fastfiles
|
||||
}
|
||||
}
|
||||
|
||||
namespace zone_loading
|
||||
{
|
||||
utils::hook::detour db_is_patch_hook;
|
||||
utils::hook::detour db_read_stream_file_hook;
|
||||
utils::hook::detour db_auth_load_inflate_hook;
|
||||
utils::hook::detour db_auth_load_inflate_init_hook;
|
||||
utils::hook::detour db_auth_load_inflate_end_hook;
|
||||
utils::hook::detour db_patch_mem_fix_stream_alignment_hook;
|
||||
|
||||
game::db_z_stream_s db_zlib_stream;
|
||||
char db_zlib_memory[0x20000];
|
||||
|
||||
bool is_reading_stream_file;
|
||||
|
||||
bool check_missing_content_func(const char* zone_name)
|
||||
{
|
||||
const char* lang_code = game::SEH_GetCurrentLanguageCode();
|
||||
char buffer[0x100]{ 0 };
|
||||
sprintf_s(buffer, "%s_", lang_code);
|
||||
|
||||
if (!strncmp(zone_name, buffer, strlen(buffer)))
|
||||
{
|
||||
printf("Tried to load missing language zone: %s\n", zone_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool db_is_patch_stub(const char* name)
|
||||
{
|
||||
if (db_is_patch_hook.invoke<bool>(name)) return true;
|
||||
if (check_missing_content_func(name)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void skip_extra_zones_stub(utils::hook::assembler& a)
|
||||
{
|
||||
const auto skip = a.newLabel();
|
||||
const auto original = a.newLabel();
|
||||
|
||||
//a.pushad64();
|
||||
a.test(edi, game::DB_ZONE_CUSTOM); // allocFlags
|
||||
a.jnz(skip);
|
||||
|
||||
a.bind(original);
|
||||
//a.popad64();
|
||||
a.call(0x3BC450_b); // strnicmp_ffotd
|
||||
a.mov(r12d, edi);
|
||||
a.mov(rdx, 0x1467970_b); // "patch_"
|
||||
a.jmp(0x3BA9C0_b);
|
||||
|
||||
a.bind(skip);
|
||||
//a.popad64();
|
||||
a.mov(r12d, game::DB_ZONE_CUSTOM);
|
||||
a.not_(r12d);
|
||||
a.and_(edi, r12d);
|
||||
a.jmp(0x3BAC06_b);
|
||||
}
|
||||
|
||||
void db_read_stream_file_stub(int a1, int a2)
|
||||
{
|
||||
if (!game::Sys_IsDatabaseThread()) // sanity check
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
is_reading_stream_file = true;
|
||||
db_read_stream_file_hook.invoke<void>(a1, a2);
|
||||
is_reading_stream_file = false;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
void stream_copy(T1 dest, T2 src)
|
||||
{
|
||||
dest->next_in = static_cast<decltype(dest->next_in)>(src->next_in);
|
||||
dest->avail_in = static_cast<decltype(dest->avail_in)>(src->avail_in);
|
||||
dest->total_in = static_cast<decltype(dest->total_in)>(src->total_in);
|
||||
dest->next_out = static_cast<decltype(dest->next_out)>(src->next_out);
|
||||
dest->avail_out = static_cast<decltype(dest->avail_out)>(src->avail_out);
|
||||
dest->total_out = static_cast<decltype(dest->total_out)>(src->total_out);
|
||||
}
|
||||
|
||||
bool is_custom_zone_read;
|
||||
|
||||
__int64 db_auth_load_inflate_stub(game::DB_ReadStream* stream)
|
||||
{
|
||||
if (!is_custom_zone_read) return db_auth_load_inflate_hook.invoke<__int64>(stream);
|
||||
|
||||
__int64 result{};
|
||||
|
||||
stream_copy(&db_zlib_stream, stream);
|
||||
if (db_zlib_stream.avail_in)
|
||||
{
|
||||
result = game::db_inflate(&db_zlib_stream, Z_SYNC_FLUSH);
|
||||
if (result == 1 && !db_zlib_stream.avail_out) result = 0;
|
||||
}
|
||||
stream_copy(stream, &db_zlib_stream);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void db_auth_load_inflate_init_stub(game::DB_ReadStream* stream, int isSecure, const char* filename)
|
||||
{
|
||||
is_custom_zone_read = false;
|
||||
|
||||
db_auth_load_inflate_init_hook.invoke<void>(stream, isSecure, filename);
|
||||
|
||||
if (stream->avail_in >= 4 &&
|
||||
(stream->next_in[1] == 'I' && stream->next_in[2] == 'W' && stream->next_in[3] == 'C'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_reading_stream_file || game::g_load->file->isSecure) return;
|
||||
|
||||
is_custom_zone_read = true;
|
||||
|
||||
memset(&db_zlib_stream, 0, sizeof(game::db_z_stream_s));
|
||||
stream_copy(&db_zlib_stream, stream);
|
||||
|
||||
game::DB_Zip_InitThreadMemory(&db_zlib_stream, &db_zlib_memory, 0x20000);
|
||||
game::db_inflateInit_(&db_zlib_stream, "1.1.4", 88);
|
||||
|
||||
stream_copy(stream, &db_zlib_stream);
|
||||
}
|
||||
|
||||
void db_auth_load_inflate_end_stub()
|
||||
{
|
||||
db_auth_load_inflate_end_hook.invoke<void>();
|
||||
|
||||
if (!is_custom_zone_read) return;
|
||||
|
||||
game::db_inflateEnd(&db_zlib_stream);
|
||||
game::DB_Zip_ShutdownThreadMemory(&db_zlib_stream);
|
||||
|
||||
is_custom_zone_read = false;
|
||||
}
|
||||
|
||||
unsigned __int64 db_patch_mem_fix_stream_alignment_stub(int alignment) // probably unneeded
|
||||
{
|
||||
if (!is_custom_zone_read) return db_patch_mem_fix_stream_alignment_hook.invoke<unsigned __int64>(alignment);
|
||||
|
||||
*game::g_streamPos = (~alignment & (alignment + *game::g_streamPos));
|
||||
return *game::g_streamPos;
|
||||
}
|
||||
}
|
||||
using namespace zone_loading;
|
||||
|
||||
bool exists(const std::string& zone)
|
||||
{
|
||||
const auto is_localized = game::DB_IsLocalized(zone.data());
|
||||
@ -139,6 +290,44 @@ namespace fastfiles
|
||||
|
||||
g_dump_scripts = game::Dvar_RegisterBool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts");
|
||||
|
||||
// Don't fatal on certain missing zones
|
||||
db_is_patch_hook.create(0x3BC580_b, db_is_patch_stub);
|
||||
// Don't load extra zones with loadzone
|
||||
utils::hook::nop(0x3BA9B1_b, 15);
|
||||
utils::hook::jump(0x3BA9B1_b, utils::hook::assemble(skip_extra_zones_stub), true);
|
||||
|
||||
// Allow loading of unsigned fastfiles
|
||||
utils::hook::set<uint8_t>(0x9E8CAE_b, 0xEB); // DB_InflateInit
|
||||
db_read_stream_file_hook.create(0x0A7F370_b, db_read_stream_file_stub);
|
||||
db_auth_load_inflate_hook.create(0x9E6AE0_b, db_auth_load_inflate_stub);
|
||||
db_auth_load_inflate_init_hook.create(0x9E6970_b, db_auth_load_inflate_init_stub);
|
||||
db_auth_load_inflate_end_hook.create(0x9E8CF0_b, db_auth_load_inflate_end_stub);
|
||||
db_patch_mem_fix_stream_alignment_hook.create(0x0A0A80_b, db_patch_mem_fix_stream_alignment_stub);
|
||||
|
||||
command::add("loadzone", [](const command::params& params)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
{
|
||||
console::info("usage: loadzone <zone>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* name = params.get(1);
|
||||
|
||||
if (!fastfiles::exists(name))
|
||||
{
|
||||
console::warn("loadzone: zone %s could not be found!\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
game::XZoneInfo info{};
|
||||
info.name = name;
|
||||
info.allocFlags = game::DB_ZONE_GAME;
|
||||
info.allocFlags |= game::DB_ZONE_CUSTOM; // skip extra zones with this flag
|
||||
|
||||
game::DB_LoadXAssets(&info, 1, game::DBSyncMode::DB_LOAD_ASYNC);
|
||||
});
|
||||
|
||||
command::add("listassetpool", [](const command::params& params)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
|
@ -256,7 +256,7 @@ namespace stats
|
||||
console::info("%s\n", value.stringPtr);
|
||||
break;
|
||||
case game::DDL_ENUM_TYPE:
|
||||
console::info("%s\n", game::DDL::DDL_Lookup_GetEnumString(state, value.intValue));
|
||||
console::info("%s\n", game::DDL_Lookup_GetEnumString(state, value.intValue));
|
||||
break;
|
||||
default:
|
||||
console::info("Unknown type (%d).\n", type);
|
||||
|
2002
src/client/game/database.hpp
Normal file
2002
src/client/game/database.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,8 @@
|
||||
|
||||
#include "structs.hpp"
|
||||
|
||||
#define PROTOCOL 1
|
||||
|
||||
namespace game
|
||||
{
|
||||
extern uint64_t base_address;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -62,6 +62,14 @@ namespace game
|
||||
WEAK symbol<void(const char* text_in)> Cmd_TokenizeString{ 0xB7D850 };
|
||||
WEAK symbol<void()> Cmd_EndTokenizeString{ 0xB7CC90 };
|
||||
|
||||
WEAK symbol<__int64(void* stream, int flush)> db_inflate{ 0xE77380 };
|
||||
WEAK symbol<__int64(void* stream, const char* version, int stream_size)> db_inflateInit_{ 0xE77980 };
|
||||
WEAK symbol<__int64(void* stream)> db_inflateEnd{ 0xE777F0 };
|
||||
|
||||
WEAK symbol<void(void* stream, void* memory, int size)> DB_Zip_InitThreadMemory{ 0xE78290 };
|
||||
WEAK symbol<void(void* stream)> DB_Zip_ShutdownThreadMemory{ 0xE782D0 };
|
||||
|
||||
WEAK symbol<void(XZoneInfo* zoneInfo, unsigned int zoneCount, char syncMode)> DB_LoadXAssets{ 0xA78630 };
|
||||
WEAK symbol<int(XAssetType type, const char* name)> DB_XAssetExists{ 0xA7C3A0 };
|
||||
WEAK symbol<int(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{ 0xA77AB0 };
|
||||
|
||||
@ -73,11 +81,7 @@ namespace game
|
||||
WEAK symbol<char* (const char* filename, char* buf, int size)> DB_ReadRawFile{ 0xA79E30 };
|
||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{ 0xF20AF0 };
|
||||
|
||||
namespace DDL
|
||||
{
|
||||
WEAK symbol<const char*(const DDLState* state, int enumValue)> DDL_Lookup_GetEnumString{ 0x30430 };
|
||||
}
|
||||
|
||||
WEAK symbol<const char* (const DDLState* state, int enumValue)> DDL_Lookup_GetEnumString{ 0x30430 };
|
||||
WEAK symbol<bool(const DDLState* state)> DDL_StateIsLeaf{ 0x2E3C0 };
|
||||
WEAK symbol<DDLType(const DDLState* state)> DDL_GetType{ 0x2E5A0 };
|
||||
WEAK symbol<DDLValue(const DDLState* state, const DDLContext* ddlContext)> DDL_GetValue{ 0x2F5E0 };
|
||||
@ -183,6 +187,9 @@ namespace game
|
||||
WEAK symbol<int(int length, void const* data, const netadr_s* to)> Sys_SendPacket{ 0xD57DE0 };
|
||||
WEAK symbol<int(netadr_s* net_from, msg_t* net_message)> Sys_GetPacket{ 0xD57D50 };
|
||||
|
||||
WEAK symbol<bool()> Sys_IsDatabaseThread{ 0xBB7B30 };
|
||||
|
||||
WEAK symbol<const char* ()> SEH_GetCurrentLanguageCode{ 0xCBAF50 };
|
||||
WEAK symbol<char* ()> SEH_GetCurrentLanguageName{ 0xCBB090 };
|
||||
WEAK symbol<char* (int code)> SEH_GetLanguageName{ 0xCBB140 };
|
||||
|
||||
@ -286,4 +293,12 @@ namespace game
|
||||
WEAK symbol<PhysicalMemory> g_scriptmem{ 0x7685FC0 };
|
||||
|
||||
WEAK symbol<searchpath_s> fs_searchpaths{ 0x756DEE0 };
|
||||
|
||||
WEAK symbol<DB_LoadData> g_load{ 0x52A8010 };
|
||||
WEAK symbol<int> g_authLoad_isSecure{ 0x529DD90 };
|
||||
WEAK symbol<DB_ReadStream> db_stream{ 0x52A8050 };
|
||||
WEAK symbol<db_z_stream_s> db_zip_stream{ 0x529DD30 };
|
||||
WEAK symbol<char*> db_zip_memory{ 0x525B500 };
|
||||
|
||||
WEAK symbol<unsigned __int64> g_streamPos{ 0x5687E30 };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user