complete gsc loading
This commit is contained in:
parent
29a0877f7a
commit
a3df08538f
@ -79,14 +79,12 @@ namespace gsc
|
||||
{
|
||||
const auto& pos = function.value();
|
||||
unknown_function_error = std::format(
|
||||
"while processing function '{}' in script '{}':\nunknown script '{}' ({})",
|
||||
pos.first, pos.second, scripting::current_file, scripting::current_file_id
|
||||
"while processing function '{}' in script '{}':\nunknown script '{}'", pos.first, pos.second, scripting::current_file
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
unknown_function_error = std::format("unknown script '{}' ({})",
|
||||
scripting::current_file, scripting::current_file_id);
|
||||
unknown_function_error = std::format("unknown script '{}'", scripting::current_file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +94,7 @@ namespace gsc
|
||||
const auto name = scripting::get_token(thread_name);
|
||||
|
||||
unknown_function_error = std::format(
|
||||
"while processing script '{}':\nunknown function '{}::{}'",
|
||||
scripting::current_file, filename, name
|
||||
"while processing script '{}':\nunknown function '{}::{}'", scripting::current_file, filename, name
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -28,22 +28,23 @@ namespace gsc
|
||||
std::unordered_map<std::string, std::uint32_t> init_handles;
|
||||
|
||||
utils::memory::allocator scriptfile_allocator;
|
||||
std::unordered_map<const char*, game::ScriptFile*> loaded_scripts;
|
||||
std::unordered_map<std::string, game::ScriptFile*> loaded_scripts;
|
||||
|
||||
char* script_mem_buf = nullptr;
|
||||
std::uint64_t script_mem_buf_size = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
char* buf = nullptr;
|
||||
char* pos = nullptr;
|
||||
const unsigned int size = 0x100000i64;
|
||||
const std::uint64_t size = 0x100000i64;
|
||||
} script_memory;
|
||||
|
||||
char* allocate_buffer(size_t size)
|
||||
{
|
||||
if (script_memory.buf == nullptr)
|
||||
{
|
||||
game::PMem_BeginAlloc("custom_gsc_script", 1);
|
||||
script_memory.buf = game::PMem_AllocFromSource_NoDebug(script_memory.size, 4, 0, 1); // 3rd paramter unused because of 4th
|
||||
game::PMem_EndAlloc("custom_gsc_script", 1);
|
||||
script_memory.buf = script_mem_buf;
|
||||
script_memory.pos = script_memory.buf;
|
||||
}
|
||||
|
||||
@ -59,10 +60,13 @@ namespace gsc
|
||||
|
||||
void free_script_memory()
|
||||
{
|
||||
game::PMem_Free("custom_gsc_script", 1);
|
||||
if (script_memory.buf != nullptr)
|
||||
{
|
||||
memset(script_memory.buf, 0, reinterpret_cast<size_t>(script_memory.pos) - reinterpret_cast<size_t>(script_memory.buf));
|
||||
script_memory.buf = nullptr;
|
||||
script_memory.pos = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
@ -106,7 +110,7 @@ namespace gsc
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
if (game::Com_FrontEndScene_IsActive())
|
||||
if (game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -117,8 +121,10 @@ namespace gsc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO: check if needed in IW7
|
||||
// filter out "GSC rawfiles" that were used for development usage and are not meant for us.
|
||||
// each "GSC rawfile" has a ScriptFile counterpart to be used instead
|
||||
/*
|
||||
if (game::DB_XAssetExists(game::ASSET_TYPE_SCRIPTFILE, file_name) &&
|
||||
!game::DB_IsXAssetDefault(game::ASSET_TYPE_SCRIPTFILE, file_name))
|
||||
{
|
||||
@ -129,6 +135,7 @@ namespace gsc
|
||||
return game::DB_FindXAssetHeader(game::ASSET_TYPE_SCRIPTFILE, file_name, false).scriptfile;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
console::debug("Loading custom gsc '%s.gsc'", real_name.data());
|
||||
|
||||
@ -225,14 +232,8 @@ namespace gsc
|
||||
return;
|
||||
}
|
||||
|
||||
console::debug("load_script: getting handles for '%s'\n", name.data());
|
||||
|
||||
const auto main_token = gsc_ctx->token_id("main");
|
||||
const auto init_token = gsc_ctx->token_id("init");
|
||||
const auto main_handle = game::Scr_GetFunctionHandle(name.data(), main_token);
|
||||
const auto init_handle = game::Scr_GetFunctionHandle(name.data(), init_token);
|
||||
|
||||
console::debug("main token: %u (%u), init token: %u (%u)\n", main_token, main_handle, init_token, init_handle);
|
||||
const auto main_handle = game::Scr_GetFunctionHandle(name.data(), gsc_ctx->token_id("main"));
|
||||
const auto init_handle = game::Scr_GetFunctionHandle(name.data(), gsc_ctx->token_id("init"));
|
||||
|
||||
if (main_handle)
|
||||
{
|
||||
@ -267,8 +268,6 @@ namespace gsc
|
||||
const auto relative = path.lexically_relative(root_dir).generic_string();
|
||||
const auto base_name = relative.substr(0, relative.size() - 4);
|
||||
|
||||
console::debug("load_script called on %s\n", base_name.data());
|
||||
|
||||
load_script(base_name);
|
||||
}
|
||||
}
|
||||
@ -285,11 +284,12 @@ namespace gsc
|
||||
|
||||
void load_scripts_stub()
|
||||
{
|
||||
if (!game::Com_FrontEndScene_IsActive())
|
||||
if (!game::Com_FrontEnd_IsInFrontEnd())
|
||||
{
|
||||
for (const auto& path : filesystem::get_search_paths())
|
||||
{
|
||||
load_scripts(path, "scripts/");
|
||||
load_scripts(path, "userscripts/");
|
||||
load_scripts(path, "userscripts/"s + game::Com_GameMode_GetActiveGameModeStr() + "/");
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ namespace gsc
|
||||
{
|
||||
for (auto& function_handle : main_handles)
|
||||
{
|
||||
console::info("Executing '%s::main'\n", function_handle.first.data());
|
||||
console::debug("Executing '%s::main'\n", function_handle.first.data());
|
||||
game::RemoveRefToObject(game::Scr_ExecThread(function_handle.second, 0));
|
||||
}
|
||||
|
||||
@ -366,17 +366,46 @@ namespace gsc
|
||||
{
|
||||
for (auto& function_handle : init_handles)
|
||||
{
|
||||
console::info("Executing '%s::init'\n", function_handle.first.data());
|
||||
console::debug("Executing '%s::init'\n", function_handle.first.data());
|
||||
game::RemoveRefToObject(game::Scr_ExecThread(function_handle.second, 0));
|
||||
}
|
||||
scr_load_level_hook.invoke<void>();
|
||||
}
|
||||
|
||||
utils::hook::detour g_shutdown_game_hook;
|
||||
void g_shutdown_game_stub(bool full_clear)
|
||||
void g_shutdown_game_stub(int full_clear, int a2)
|
||||
{
|
||||
if (full_clear && a2)
|
||||
{
|
||||
clear();
|
||||
g_shutdown_game_hook.invoke<void>(full_clear);
|
||||
}
|
||||
g_shutdown_game_hook.invoke<void>(full_clear, a2);
|
||||
}
|
||||
|
||||
// donetsk developers will paste this in days
|
||||
utils::hook::detour db_alloc_x_zone_memory_internal_hook;
|
||||
void db_alloc_x_zone_memory_internal_stub(unsigned __int64* blockSize, const char* filename, game::XZoneMemory* zoneMem, unsigned int type)
|
||||
{
|
||||
bool patch = false; // ugly fix for script memory allocation
|
||||
if (!_stricmp(filename, "code_post_gfx") && type == 2)
|
||||
{
|
||||
patch = true;
|
||||
console::debug("patching memory for '%s'\n", filename);
|
||||
}
|
||||
|
||||
if (patch)
|
||||
{
|
||||
blockSize[game::XFILE_BLOCK_SCRIPT] += script_memory.size;
|
||||
}
|
||||
|
||||
db_alloc_x_zone_memory_internal_hook.invoke<void>(blockSize, filename, zoneMem, type);
|
||||
|
||||
if (patch)
|
||||
{
|
||||
blockSize[game::XFILE_BLOCK_SCRIPT] -= script_memory.size;
|
||||
script_mem_buf = zoneMem->blocks[game::XFILE_BLOCK_SCRIPT].alloc + blockSize[game::XFILE_BLOCK_SCRIPT];
|
||||
script_mem_buf_size = script_memory.size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,6 +432,9 @@ namespace gsc
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
// Allocate script memory (PMem doesn't work)
|
||||
db_alloc_x_zone_memory_internal_hook.create(0xA75450_b, db_alloc_x_zone_memory_internal_stub);
|
||||
|
||||
// Load our scripts with an uncompressed stack
|
||||
utils::hook::call(0xC09DA7_b, db_get_raw_buffer_stub);
|
||||
|
||||
@ -422,10 +454,8 @@ namespace gsc
|
||||
// execute init handle
|
||||
scr_load_level_hook.create(0xB51B40_b, scr_load_level_stub);
|
||||
|
||||
/*
|
||||
// clear memory (G_MainMP_ShutdownGameMemory)
|
||||
g_shutdown_game_hook.create(0xC56C80_b, g_shutdown_game_stub);
|
||||
*/
|
||||
// clear memory (SV_GameMP_ShutdownGameVM)
|
||||
g_shutdown_game_hook.create(0xBB36D86_b, g_shutdown_game_stub);
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
|
@ -27,7 +27,6 @@ namespace scripting
|
||||
utils::concurrency::container<shared_table_t> shared_table;
|
||||
|
||||
std::string current_file;
|
||||
unsigned int current_file_id{};
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -44,11 +43,8 @@ namespace scripting
|
||||
|
||||
utils::hook::detour sl_get_canonical_string_hook;
|
||||
|
||||
utils::hook::detour db_find_xasset_header_hook;
|
||||
|
||||
const char* current_script_file_name;
|
||||
|
||||
game::dvar_t* g_dump_scripts;
|
||||
std::string current_script_file;
|
||||
unsigned int current_file_id{};
|
||||
|
||||
std::vector<std::function<void(bool, bool)>> shutdown_callbacks;
|
||||
|
||||
@ -115,13 +111,12 @@ namespace scripting
|
||||
|
||||
void process_script_stub(const char* filename)
|
||||
{
|
||||
current_script_file_name = filename;
|
||||
current_script_file = filename;
|
||||
|
||||
const auto file_id = atoi(filename);
|
||||
if (file_id)
|
||||
{
|
||||
current_file_id = static_cast<std::uint16_t>(file_id);
|
||||
current_file = scripting::get_token(current_file_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -135,10 +130,14 @@ namespace scripting
|
||||
void add_function_sort(unsigned int id, const char* pos)
|
||||
{
|
||||
std::string filename = current_file;
|
||||
if (current_file_id)
|
||||
{
|
||||
filename = scripting::get_token(current_file_id);
|
||||
}
|
||||
|
||||
if (!script_function_table_sort.contains(filename))
|
||||
{
|
||||
const auto script = gsc::find_script(game::ASSET_TYPE_SCRIPTFILE, current_script_file_name, false);
|
||||
const auto script = gsc::find_script(game::ASSET_TYPE_SCRIPTFILE, current_script_file.data(), false);
|
||||
if (script)
|
||||
{
|
||||
const auto end = &script->bytecode[script->bytecodeLen];
|
||||
@ -162,7 +161,15 @@ namespace scripting
|
||||
{
|
||||
add_function_sort(thread_name, code_pos);
|
||||
|
||||
if (current_file_id)
|
||||
{
|
||||
const auto name = get_token(current_file_id);
|
||||
add_function(name, thread_name, code_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_function(current_file, thread_name, code_pos);
|
||||
}
|
||||
|
||||
scr_set_thread_position_hook.invoke<void>(thread_name, code_pos);
|
||||
}
|
||||
@ -212,9 +219,6 @@ namespace scripting
|
||||
scr_set_thread_position_hook.create(0xBFD190_b, scr_set_thread_position_stub);
|
||||
process_script_hook.create(0xC09D20_b, process_script_stub);
|
||||
sl_get_canonical_string_hook.create(game::SL_GetCanonicalString, sl_get_canonical_string_stub);
|
||||
|
||||
// clear memory (SV_GameMP_ShutdownGameVM)
|
||||
g_shutdown_game_hook.create(0xB21CC0_b, g_shutdown_game_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ namespace scripting
|
||||
extern utils::concurrency::container<shared_table_t> shared_table;
|
||||
|
||||
extern std::string current_file;
|
||||
extern unsigned int current_file_id;
|
||||
|
||||
void on_shutdown(const std::function<void(bool, bool)>& callback);
|
||||
std::optional<std::string> get_canonical_string(const unsigned int id);
|
||||
|
@ -3267,16 +3267,78 @@ namespace game
|
||||
enum PMem_Source
|
||||
{
|
||||
PMEM_SOURCE_EXTERNAL = 0x0,
|
||||
PMEM_SOURCE_DATABASE = 0x1,
|
||||
PMEM_SOURCE_DEFAULT_LOW = 0x2,
|
||||
PMEM_SOURCE_DEFAULT_HIGH = 0x3,
|
||||
PMEM_SOURCE_MOVIE = 0x4,
|
||||
PMEM_SOURCE_SCRIPT = 0x5,
|
||||
PMEM_SOURCE_UNK5 = 0x5,
|
||||
PMEM_SOURCE_UNK6 = 0x6,
|
||||
PMEM_SOURCE_UNK7 = 0x7,
|
||||
PMEM_SOURCE_UNK8 = 0x8,
|
||||
PMEM_SOURCE_CUSTOMIZATION = 0x9,
|
||||
PMEM_SOURCE_SCRIPT = 0x1,
|
||||
};
|
||||
|
||||
enum PMem_Direction : __int32
|
||||
{
|
||||
PHYS_ALLOC_LOW = 0x0,
|
||||
PHYS_ALLOC_HIGH = 0x1,
|
||||
PHYS_ALLOC_COUNT = 0x2,
|
||||
};
|
||||
|
||||
enum Mem_PageID
|
||||
{
|
||||
};
|
||||
|
||||
struct Mem_PageRange
|
||||
{
|
||||
Mem_PageID firstPageID;
|
||||
Mem_PageID lastPageID;
|
||||
};
|
||||
|
||||
struct PhysicalMemoryAllocation
|
||||
{
|
||||
const char* name;
|
||||
char* prev_buffer;
|
||||
char* next_buffer;
|
||||
unsigned __int64 pos;
|
||||
Mem_PageRange pageRange;
|
||||
};
|
||||
|
||||
struct PhysicalMemoryPrim
|
||||
{
|
||||
const char* name;
|
||||
unsigned int allocListCount;
|
||||
char __pad0[4];
|
||||
unsigned __int8* buf;
|
||||
unsigned __int64 unk_pos;
|
||||
int unk1;
|
||||
char __pad2[4];
|
||||
unsigned __int64 pos;
|
||||
PhysicalMemoryAllocation allocList[32];
|
||||
};
|
||||
|
||||
struct PhysicalMemory
|
||||
{
|
||||
PhysicalMemoryPrim prim[2];
|
||||
};
|
||||
|
||||
struct XBlock
|
||||
{
|
||||
char* alloc;
|
||||
unsigned __int64 size;
|
||||
};
|
||||
|
||||
struct XZoneMemory
|
||||
{
|
||||
XBlock blocks[10];
|
||||
char __pad0[200]; // unk size
|
||||
};
|
||||
|
||||
enum XFileBlock
|
||||
{
|
||||
XFILE_BLOCK_TEMP_ADDITIONAL = 0x0,
|
||||
XFILE_BLOCK_TEMP = 0x1,
|
||||
XFILE_BLOCK_TEMP_PRELOAD = 0x2,
|
||||
XFILE_BLOCK_CALLBACK = 0x3,
|
||||
XFILE_BLOCK_RUNTIME = 0x4,
|
||||
XFILE_BLOCK_RUNTIME_VIDEO = 0x5,
|
||||
XFILE_BLOCK_CACHED_VIDEO = 0x6,
|
||||
XFILE_BLOCK_PHYSICAL = 0x7,
|
||||
XFILE_BLOCK_VIRTUAL = 0x8,
|
||||
XFILE_BLOCK_SCRIPT = 0x9,
|
||||
MAX_XFILE_COUNT = 0xA,
|
||||
};
|
||||
|
||||
enum VariableType
|
||||
|
@ -276,9 +276,6 @@ namespace game
|
||||
WEAK game::symbol<unsigned __int64> pmem_size{ 0x7686A28 };
|
||||
WEAK game::symbol<unsigned char*> pmem_buffer{ 0x7686A20 };
|
||||
|
||||
/*
|
||||
WEAK game::symbol<PhysicalMemory> g_mem{ 0xD5F26E0, 0xC92E1E0 };
|
||||
WEAK game::symbol<PhysicalMemory> g_scriptmem{ 0xD5F3140, 0xC92EC40 };
|
||||
WEAK game::symbol<PhysicalMemory> g_physmem{ 0xD5F3BA0, 0xC92F6A0 };
|
||||
*/
|
||||
WEAK game::symbol<PhysicalMemory> g_mem{ 0x7685560 };
|
||||
WEAK game::symbol<PhysicalMemory> g_scriptmem{ 0x7685FC0 };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user