Debug missing assets + dump gsc scripts
This commit is contained in:
parent
c137827e96
commit
deeae4f9b1
@ -1,12 +1,16 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
#include "fastfiles.hpp"
|
|
||||||
|
|
||||||
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
|
#include "fastfiles.hpp"
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/concurrency.hpp>
|
#include <utils/concurrency.hpp>
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
namespace fastfiles
|
namespace fastfiles
|
||||||
{
|
{
|
||||||
@ -15,6 +19,8 @@ namespace fastfiles
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::hook::detour db_try_load_x_file_internal_hook;
|
utils::hook::detour db_try_load_x_file_internal_hook;
|
||||||
|
utils::hook::detour db_find_xasset_header_hook;
|
||||||
|
game::dvar_t* g_dump_scripts;
|
||||||
|
|
||||||
void db_try_load_x_file_internal(const char* zone_name, const int flags)
|
void db_try_load_x_file_internal(const char* zone_name, const int flags)
|
||||||
{
|
{
|
||||||
@ -25,6 +31,57 @@ namespace fastfiles
|
|||||||
});
|
});
|
||||||
db_try_load_x_file_internal_hook.invoke<void>(zone_name, flags);
|
db_try_load_x_file_internal_hook.invoke<void>(zone_name, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_gsc_script(const std::string& name, game::XAssetHeader header)
|
||||||
|
{
|
||||||
|
if (!g_dump_scripts->current.enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string buffer;
|
||||||
|
buffer.append(header.scriptfile->name, strlen(header.scriptfile->name) + 1);
|
||||||
|
buffer.append(reinterpret_cast<char*>(&header.scriptfile->compressedLen), 4);
|
||||||
|
buffer.append(reinterpret_cast<char*>(&header.scriptfile->len), 4);
|
||||||
|
buffer.append(reinterpret_cast<char*>(&header.scriptfile->bytecodeLen), 4);
|
||||||
|
buffer.append(header.scriptfile->buffer, header.scriptfile->compressedLen);
|
||||||
|
buffer.append(header.scriptfile->bytecode, header.scriptfile->bytecodeLen);
|
||||||
|
|
||||||
|
const auto out_name = utils::string::va("gsc_dump/%s.gscbin", name.data());
|
||||||
|
utils::io::write_file(out_name, buffer);
|
||||||
|
|
||||||
|
console::info("Dumped %s\n", out_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
||||||
|
{
|
||||||
|
const auto start = game::Sys_Milliseconds();
|
||||||
|
const auto result = db_find_xasset_header_hook.invoke<game::XAssetHeader>(type, name, allow_create_default);
|
||||||
|
const auto diff = game::Sys_Milliseconds() - start;
|
||||||
|
|
||||||
|
if (type == game::XAssetType::ASSET_TYPE_SCRIPTFILE)
|
||||||
|
{
|
||||||
|
dump_gsc_script(name, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff > 100)
|
||||||
|
{
|
||||||
|
console::print(
|
||||||
|
result.data == nullptr
|
||||||
|
? console::con_type_error
|
||||||
|
: console::con_type_warning,
|
||||||
|
"Waited %i msec for %sasset \"%s\", of type \"%s\"\n",
|
||||||
|
diff,
|
||||||
|
result.data == nullptr
|
||||||
|
? "missing "
|
||||||
|
: "",
|
||||||
|
name,
|
||||||
|
game::g_assetNames[type]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_current_fastfile()
|
std::string get_current_fastfile()
|
||||||
@ -52,6 +109,10 @@ namespace fastfiles
|
|||||||
{
|
{
|
||||||
db_try_load_x_file_internal_hook.create(
|
db_try_load_x_file_internal_hook.create(
|
||||||
SELECT_VALUE(0x1F5700_b, 0x39A620_b), &db_try_load_x_file_internal);
|
SELECT_VALUE(0x1F5700_b, 0x39A620_b), &db_try_load_x_file_internal);
|
||||||
|
|
||||||
|
db_find_xasset_header_hook.create(game::DB_FindXAssetHeader, db_find_xasset_header_stub);
|
||||||
|
|
||||||
|
g_dump_scripts = dvars::register_bool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ namespace ui_scripting
|
|||||||
utils::hook::detour hks_package_require_hook;
|
utils::hook::detour hks_package_require_hook;
|
||||||
|
|
||||||
utils::hook::detour hks_load_hook;
|
utils::hook::detour hks_load_hook;
|
||||||
utils::hook::detour db_find_xasset_header_hook;
|
|
||||||
|
|
||||||
const auto lui_common = utils::nt::load_resource(LUI_COMMON);
|
const auto lui_common = utils::nt::load_resource(LUI_COMMON);
|
||||||
|
|
||||||
@ -274,9 +273,9 @@ namespace ui_scripting
|
|||||||
|
|
||||||
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
game::XAssetHeader db_find_xasset_header_stub(game::XAssetType type, const char* name, int allow_create_default)
|
||||||
{
|
{
|
||||||
if (type != 0x3D || !is_loaded_script(globals.in_require_script))
|
if (!is_loaded_script(globals.in_require_script))
|
||||||
{
|
{
|
||||||
return db_find_xasset_header_hook.invoke<game::XAssetHeader>(type, name, allow_create_default);
|
return game::DB_FindXAssetHeader(type, name, allow_create_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto folder = globals.in_require_script.substr(0, globals.in_require_script.find_last_of("/\\"));
|
const auto folder = globals.in_require_script.substr(0, globals.in_require_script.find_last_of("/\\"));
|
||||||
@ -291,7 +290,7 @@ namespace ui_scripting
|
|||||||
}
|
}
|
||||||
else if (name_.starts_with("ui/LUI/"))
|
else if (name_.starts_with("ui/LUI/"))
|
||||||
{
|
{
|
||||||
return db_find_xasset_header_hook.invoke<game::XAssetHeader>(type, name, allow_create_default);
|
return game::DB_FindXAssetHeader(type, name, allow_create_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<game::XAssetHeader>(nullptr);
|
return static_cast<game::XAssetHeader>(nullptr);
|
||||||
@ -375,7 +374,47 @@ namespace ui_scripting
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db_find_xasset_header_hook.create(game::DB_FindXAssetHeader, db_find_xasset_header_stub);
|
utils::hook::jump(SELECT_VALUE(0xE7419_b, 0x25E809_b), utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
|
{
|
||||||
|
const auto loc = a.newLabel();
|
||||||
|
|
||||||
|
a.push(rax);
|
||||||
|
a.pushad64();
|
||||||
|
a.call_aligned(db_find_xasset_header_stub);
|
||||||
|
a.mov(qword_ptr(rsp, 0x80), rax);
|
||||||
|
a.popad64();
|
||||||
|
a.pop(rax);
|
||||||
|
|
||||||
|
a.mov(rcx, r13);
|
||||||
|
a.test(rax, rax);
|
||||||
|
a.jnz(loc);
|
||||||
|
|
||||||
|
a.jmp(SELECT_VALUE(0xE7426_b, 0x25E816_b));
|
||||||
|
|
||||||
|
a.bind(loc);
|
||||||
|
a.jmp(SELECT_VALUE(0xE748A_b, 0x25E87A_b));
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
utils::hook::jump(SELECT_VALUE(0xE72CB_b, 0x25E6BB_b), utils::hook::assemble([](utils::hook::assembler& a)
|
||||||
|
{
|
||||||
|
const auto loc = a.newLabel();
|
||||||
|
|
||||||
|
a.push(rax);
|
||||||
|
a.pushad64();
|
||||||
|
a.call_aligned(db_find_xasset_header_stub);
|
||||||
|
a.mov(qword_ptr(rsp, 0x80), rax);
|
||||||
|
a.popad64();
|
||||||
|
a.pop(rax);
|
||||||
|
|
||||||
|
a.test(rax, rax);
|
||||||
|
a.jnz(loc);
|
||||||
|
|
||||||
|
a.jmp(SELECT_VALUE(0xE72D9_b, 0x25E6C9_b));
|
||||||
|
|
||||||
|
a.bind(loc);
|
||||||
|
a.jmp(SELECT_VALUE(0xE73EC_b, 0x25E7DC_b));
|
||||||
|
}), true);
|
||||||
|
|
||||||
hks_load_hook.create(SELECT_VALUE(0xB46F0_b, 0x22C180_b), hks_load_stub);
|
hks_load_hook.create(SELECT_VALUE(0xB46F0_b, 0x22C180_b), hks_load_stub);
|
||||||
|
|
||||||
hks_package_require_hook.create(SELECT_VALUE(0x90070_b, 0x214040_b), hks_package_require_stub);
|
hks_package_require_hook.create(SELECT_VALUE(0x90070_b, 0x214040_b), hks_package_require_stub);
|
||||||
|
@ -48,7 +48,7 @@ namespace game
|
|||||||
WEAK symbol<void()> Com_Quit_f{0x0, 0x1F9280};
|
WEAK symbol<void()> Com_Quit_f{0x0, 0x1F9280};
|
||||||
WEAK symbol<void(char const* finalMessage)> Com_Shutdown{0x0, 0x0};
|
WEAK symbol<void(char const* finalMessage)> Com_Shutdown{0x0, 0x0};
|
||||||
|
|
||||||
WEAK symbol<void()> Quit{0x105FF0, 0x17CF50};
|
WEAK symbol<void()> Quit{0x3A5A20, 0x17CF50};
|
||||||
|
|
||||||
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x0, 0x316210};
|
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessage{0x0, 0x316210};
|
||||||
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessageBold{0x0, 0x3122F0};
|
WEAK symbol<void(int localClientNum, const char* message)> CG_GameMessageBold{0x0, 0x3122F0};
|
||||||
|
Loading…
Reference in New Issue
Block a user