Compare commits

..

No commits in common. "main" and "v0.0.4" have entirely different histories.
main ... v0.0.4

58 changed files with 1555 additions and 2495 deletions

View File

@ -58,7 +58,6 @@ jobs:
name: ${{matrix.configuration}} binaries
path: |
build/bin/${{matrix.configuration}}/t4sp-server-plugin.dll
build/bin/${{matrix.configuration}}/t4sp-server-plugin.pdb
deploy:
name: Deploy release
@ -83,4 +82,3 @@ jobs:
draft: true
files: |
t4sp-server-plugin.dll
t4sp-server-plugin.pdb

3
.gitmodules vendored
View File

@ -29,6 +29,3 @@
[submodule "deps/SQLiteCpp"]
path = deps/SQLiteCpp
url = https://github.com/SRombauts/SQLiteCpp
[submodule "deps/plutonium-sdk"]
path = deps/plutonium-sdk
url = https://github.com/plutoniummod/plutonium-sdk.git

109
README.md
View File

@ -3,112 +3,11 @@ A plugin that has code that hopefully compiles and the game will load it to do t
Requires Git (https://git-scm.com/), Premake5 (https://premake.github.io/), and MSVC 2022 (https://visualstudio.microsoft.com/vs/features/cplusplus/) to build.
# What does it do?
Nothing really right now, just detours and reimplements the entire GSC VM, for research purposes.
# Installation
Move the `t4sp-server-plugin.dll` to `%LOCALAPPDATA%\Plutonium\plugins\`, the plugin will be loaded when you start up a dedicated server for Plutonium T4SP.
# Features
Detours and reimplements the entire GSC VM + compiler.
Adds custom GSC functions.
## FileIO
This plugin provides FileIO interface to GSC for reading and writing files, this is exact to [CoD4x's](https://github.com/callofduty4x/CoD4x_Server/blob/master/scriptdocumentation/script_functions_reference.md#file-operations) interface.
However, all reads and writes will take place strictly and only in the `scriptdata` folder, no up directory traversal allowed.
All files will be closed upon GSC restart (map_restart or fast_restart or missionfailed, etc), only a maximum of 10 files may be opened at once.
* `<bool> FS_TestFile(<filename string>)` Returns `true` if the file exists, `false` otherwise.
* `<bool> FS_Remove(<filename string>, <(optional) use_global bool>)` Deletes the file, return `true` if successful, `false` otherwise. `use_global` will use non mod specific folder.
```gsc
// test to see if "scriptdata/test.txt" file exists
if (FS_TestFile("test.txt")) // not a typo, all file io will take place inside the "scriptdata" folder
{
PrintConsole("Found test.txt!");
// delete it!
if (FS_Remove("test.txt"))
{
PrintConsole("test.txt was deleted!");
}
}
```
* `FS_FCloseAll()` Closes every full file.
```gsc
// open some files
FS_FCloseAll(); // close them all
```
* `<int> FS_FOpen(<filename string>, <mode string>, <(optional) use_global bool>)` Tries to open the file, mode must be one of `read`, `write` (clears the file), `append` (appends to the file), returns the filehandle. Will return `0` if failed to open. `use_global` will use non mod specific folder (only applies to `write` mode).
* `FS_FClose(<filehandle int>)` Closes the file pointed by the filehandle given, which was returned from `FS_FOpen`.
```gsc
// opens "scriptdata/test.txt", all io will take place inside the "scriptdata" folder
f = FS_FOpen("test.txt", "read"); // can be "read" "write", or "append"
if (!f)
{
PrintConsole("test.txt failed to be opened for reading!");
}
else
{
// do stuff with the file
FS_FClose(f); // make sure to close it
}
```
* `<string> FS_ReadLine(<filehandle int>)` Reads a line from the file pointed by the filehandle, removes the newline char. Returns `undefined` when nothing is left to read. Will not read more than 65536 characters at once. Filehandle must be opened for reading.
* `<string> FS_Read(<filehandle int>, <bytes int>(optional))` Reads number of bytes from the file. If bytes is `undefined`, reads the entire file. No more than 65536 characters will be read at once. Returns `undefined` if there are nothing left to read.
```gsc
// open the file for reading
line = FS_ReadLine(f);
while (isDefined(line))
{
// do something with line
line = FS_ReadLine(f);
}
// entire file is read
// close the file
```
* `<bool> FS_WriteLine(<filehandle int>, <contents string>)` Writes to the file pointed by the filehandle. Appends a newline character. Returns `true` if successful, `false` otherwise. Filehandle must be opened for writing.
* `<bool> FS_Write(<filehandle int>, <contents string>)` Same as above, does not add a newline character.
```gsc
// open the file for writing
FS_WriteLine(f, "writing some text with newline added");
FS_Write(f, "no newline here");
FS_Write(f, "i manually add a newline\n");
// close the file
```
* `<array of strings> FS_ListFiles(<folder string>)` Returns a list of files inside of the folder given.
```gsc
folder = "testfolder/";
files = FS_ListFiles(folder);
for (i = 0; i < files.size; i++)
{
filename = files[i];
// do something with the filename
filepath = folder + filename;
}
```
* `<int> FS_Length(<filehandle int>)` Returns the length in bytes of the open'd file.
* `<int> FS_GetSeek(<filehandle int>)` Returns the seek of the open'd file (only for reading).
* `<int> FS_Seek(<filehandle int>, <seek int>)` Sets the seek of the open'd file (only for reading).
Move the `t4sp-server-plugin.dll` to `%LOCALAPPDATA%\Plutonium\storage\t4\plugins\`, the plugin will be loaded when you start up a dedicated server for Plutonium T4SP.
# Credits
- momo5502 (https://github.com/momo5502)

2
deps/GSL vendored

@ -1 +1 @@
Subproject commit e64c97fc2cfc11992098bb38eda932de275e3f4d
Subproject commit 43d60c5e3891dab6491a76d0bac554a4a89d57f6

2
deps/asmjit vendored

@ -1 +1 @@
Subproject commit 416f7356967c1f66784dc1580fe157f9406d8bff
Subproject commit f1ea8a46c3f2bce5c51f290050c9d194668206bf

2
deps/curl vendored

@ -1 +1 @@
Subproject commit 78a1814b331c3535a785aa1c501203ad5a947838
Subproject commit 4528690cd51e5445df74aef8f83470a602683797

2
deps/json vendored

@ -1 +1 @@
Subproject commit a259ecc51e1951e12f757ce17db958e9881e9c6c
Subproject commit 546370c9e778d99e7176641123e5cc1d0b62acab

2
deps/libtomcrypt vendored

@ -1 +1 @@
Subproject commit 7e863d21429f94ed6a720e24499a12a3f852bb31
Subproject commit b96e96cf8b22a931e8e91098ac37bc72f9e2f033

2
deps/libtommath vendored

@ -1 +1 @@
Subproject commit 8314bde5e5c8e5d9331460130a9d1066e324f091
Subproject commit 7f96509df1a6b44867bbda56bbf2cb92524be8ef

2
deps/minhook vendored

@ -1 +1 @@
Subproject commit f5485b8454544c2f034c78f8f127c1d03dea3636
Subproject commit 49d03ad118cf7f6768c79a8f187e14b8f2a07f94

1
deps/plutonium-sdk vendored

@ -1 +0,0 @@
Subproject commit 17e9a0a4d5e1133b50f879e3db07e97d1bf92e10

View File

@ -1,34 +1,34 @@
SQLiteCpp = {
source = path.join(dependencies.basePath, "SQLiteCpp"),
source = path.join(dependencies.basePath, "SQLiteCpp"),
}
function SQLiteCpp.import()
links { "SQLiteCpp" }
SQLiteCpp.includes()
links { "SQLiteCpp" }
SQLiteCpp.includes()
end
function SQLiteCpp.includes()
includedirs {
path.join(SQLiteCpp.source, "include"),
path.join(SQLiteCpp.source, "sqlite3")
}
includedirs {
path.join(SQLiteCpp.source, "include"),
path.join(SQLiteCpp.source, "sqlite3")
}
end
function SQLiteCpp.project()
project "SQLiteCpp"
language "C"
project "SQLiteCpp"
language "C"
SQLiteCpp.includes()
SQLiteCpp.includes()
files {
path.join(path.join(SQLiteCpp.source, "src"), "**.cpp"),
path.join(path.join(SQLiteCpp.source, "include"), "**.h"),
path.join(path.join(SQLiteCpp.source, "sqlite3"), "**.c"),
path.join(path.join(SQLiteCpp.source, "sqlite3"), "**.h")
}
files {
path.join(path.join(SQLiteCpp.source, "src"), "**.cpp"),
path.join(path.join(SQLiteCpp.source, "include"), "**.h"),
path.join(path.join(SQLiteCpp.source, "sqlite3"), "**.c"),
path.join(path.join(SQLiteCpp.source, "sqlite3"), "**.h")
}
warnings "Off"
kind "StaticLib"
warnings "Off"
kind "StaticLib"
end
table.insert(dependencies, SQLiteCpp)

View File

@ -1,16 +1,16 @@
csv_parser = {
source = path.join(dependencies.basePath, "csv-parser"),
source = path.join(dependencies.basePath, "csv-parser"),
}
function csv_parser.import()
dependson "csv-parser"
csv_parser.includes()
dependson "csv-parser"
csv_parser.includes()
end
function csv_parser.includes()
includedirs {
csv_parser.source
}
includedirs {
csv_parser.source
}
end
function csv_parser.project()

View File

@ -1,18 +0,0 @@
plutonium_sdk = {
source = path.join(dependencies.basePath, "plutonium-sdk"),
}
function plutonium_sdk.import()
plutonium_sdk.includes()
end
function plutonium_sdk.includes()
includedirs {
plutonium_sdk.source,
}
end
function plutonium_sdk.project()
end
table.insert(dependencies, plutonium_sdk)

2
deps/zlib vendored

@ -1 +1 @@
Subproject commit 643e17b7498d12ab8d15565662880579692f769d
Subproject commit 04f42ceca40f73e2978b50e93806c2a18c1281fc

View File

@ -108,13 +108,13 @@ workspace "t4sp-server-plugin"
else
filter "configurations:Release"
postbuildcommands {
"if \"%COMPUTERNAME%\" == \"\" ( copy /y \"$(TargetPath)\" \"$(LOCALAPPDATA)\\Plutonium\\plugins\\\" )"
"if \"%COMPUTERNAME%\" == \"NEW-BUILT\" ( copy /y \"$(TargetPath)\" \"$(CODWAW_PATH)\\t4\\plugins\\\" )"
}
filter {}
filter "configurations:Debug"
postbuildcommands {
"if \"%COMPUTERNAME%\" == \"\" ( copy /y \"$(TargetPath)\" \"$(LOCALAPPDATA)\\Plutonium-staging\\plugins\\\" )"
"if \"%COMPUTERNAME%\" == \"NEW-BUILT\" ( copy /y \"$(TargetPath)\" \"$(CODWAW_PATH)\\t4staging\\plugins\\\" )"
}
filter {}
end

View File

@ -2011,6 +2011,14 @@ LABEL_17:
}
// our addition
auto f = gsc::function::get(pName, type);
if (f != nullptr)
{
return f;
}
//
// pluto
if (game::plutonium::scr_get_function_hook != nullptr)
{
@ -2146,6 +2154,14 @@ LABEL_17:
}
}
// our addition
auto f = gsc::method::get(pName, type);
if (f != nullptr)
{
return f;
}
//
// pluto
if (game::plutonium::scr_get_method_hook != nullptr)
{

View File

@ -304,6 +304,7 @@ namespace codsrc
{
game::plutonium::script_preprocess(sourceBuffer, inst, &parseData); // the pluto hook will call ScriptParse, so we dont have to
}
//
else
{

View File

@ -723,20 +723,19 @@ namespace codsrc
{
if (game::Scr_IsInOpcodeMemory(scriptInstance, codepos - 1))
{
const char* s;
// pluto
const char* s;
if (game::plutonium::at_codepose_va != nullptr)
{
s = game::plutonium::at_codepose_va(scriptInstance, codepos - game::gScrVarPub[scriptInstance].programBuffer);
}
//
else
{
s = game::va("@ %d\n", codepos - game::gScrVarPub[scriptInstance].programBuffer);
}
game::Com_PrintMessage(channel, s, 0);
//
return;
}
}

View File

@ -67,18 +67,11 @@ namespace codsrc
{
int len;
if (!refString->u.s.byteLen)
for ( len = refString->u.s.byteLen - 1;
refString->str[len];
len += 256 )
{
len = 256 - 1; //Bugfix for 256 % 256 = 0 or 512 % 256 = 0 or... Just promote it to 256
}
else
{
len = refString->u.s.byteLen - 1;
}
while (refString->str[len])
{
len += 256;
;
}
return len;

View File

@ -1,6 +1,5 @@
#include <stdinc.hpp>
#include "clientscript_public.hpp"
#include <component/scheduler.hpp>
#pragma warning(push)
#pragma warning(disable: 4244)
@ -4882,24 +4881,20 @@ namespace codsrc
return result;
}
result = value->u.anim;
result.u.linkPointer = (const char*)value->u.intValue;
if ( !animTreeInputForValidation )
{
return result;
}
assert(animTreeInputForValidation);
animTreeAnimPtr = animTreeInputForValidation->anims; // XAnimGetAnims(inst, animTreeInputForValidation);
assert(result.u.s.tree > 0 && result.u.s.tree < game::gScrAnimPub[inst].xanim_num[user]);
animPtr = game::gScrAnimPub[inst].xanim_lookup[user][result.u.s.tree].anims; // Scr_GetAnims(inst, user, result.u.s.tree);
animTreeAnimPtr = animTreeInputForValidation->anims;
animPtr = game::gScrAnimPub[inst].xanim_lookup[user][(unsigned int)result.u.linkPointer >> 16].anims;
if ( animPtr == animTreeAnimPtr )
{
return result;
}
debugMsg = game::XAnimGetAnimDebugName(result.u.s.index, animPtr);
debugMsg = game::XAnimGetAnimDebugName(value->u.intValue, animPtr);
game::gScrVarPub[inst].error_message = (char*)game::va("anim '%s' in animtree '%s' does not belong to the entity's animtree '%s'", debugMsg, animTreeAnimPtr->debugName, animTreeAnimPtr->debugName);
game::RemoveRefToValueInternal(game::SCRIPTINSTANCE_SERVER, value->type, value->u);
value->type = game::VAR_UNDEFINED;
@ -5735,11 +5730,5 @@ namespace codsrc
{
game::Scr_NotifyNum_Internal(game::SCRIPTINSTANCE_SERVER, entnum, classnum, stringValue, paramcount);
}
// Restored
unsigned int Scr_GetNumParam(game::scriptInstance_t inst)
{
return game::gScrVmPub[inst].outparamcount;
}
}
#pragma warning(pop)

View File

@ -116,5 +116,4 @@ namespace codsrc
unsigned int GetInternalVariableIndex(game::scriptInstance_t inst, unsigned int unsignedValue);
const char* Scr_ReadData(game::scriptInstance_t inst, const char** pos, unsigned int count);
void Scr_NotifyNum(int entnum, game::classNum_e classnum, unsigned int stringValue, unsigned int paramcount);
unsigned int Scr_GetNumParam(game::scriptInstance_t inst);
}

View File

@ -1,5 +1,4 @@
#include <stdinc.hpp>
#include <utils/flags.hpp>
#include "clientscript_public.hpp"
#pragma warning(push)
@ -2054,13 +2053,6 @@ namespace codsrc
game::yyparse();
*parseData = *game::yaccResult;
// our addition
if (utils::flags::has_flag("dump_asts"))
{
print_ast(inst, *parseData);
}
//
}
}
#pragma warning(pop)

View File

@ -3,7 +3,7 @@
#include "utils/hook.hpp"
//#include "codsrc/clientscript/cscr_animtree.hpp"
#ifndef DISABLE_RE_CSCR_ANIMTREE
#ifndef DISABLE_RE_CSCR_YACC
namespace re_cscr_animtree
{
utils::hook::detour AnimTreeCompileError_hook;
@ -353,29 +353,24 @@ namespace re_cscr_animtree
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_ANIMTREE_USE_WRAPPERS
quick = false;
#endif
AnimTreeCompileError_hook.create(game::AnimTreeCompileError.get(), AnimTreeCompileError_stub, quick);
GetAnimTreeParseProperties_hook.create(game::GetAnimTreeParseProperties.get(), GetAnimTreeParseProperties_stub, quick);
Scr_EmitAnimationInternal_hook.create(game::Scr_EmitAnimationInternal_ADDR(), Scr_EmitAnimationInternal_stub, quick);
AnimTreeParseInternal_hook.create(game::AnimTreeParseInternal.get(), AnimTreeParseInternal_stub, quick);
Scr_AnimTreeParse_hook.create(game::Scr_AnimTreeParse_ADDR(), Scr_AnimTreeParse_stub, quick);
Scr_GetAnimTreeSize_hook.create(game::Scr_GetAnimTreeSize.get(), Scr_GetAnimTreeSize_stub, quick);
ConnectScriptToAnim_hook.create(game::ConnectScriptToAnim_ADDR(), ConnectScriptToAnim_stub, quick);
Scr_GetAnimsIndex_hook.create(game::Scr_GetAnimsIndex_ADDR(), Scr_GetAnimsIndex_stub, quick);
Scr_CreateAnimationTree_hook.create(game::Scr_CreateAnimationTree.get(), Scr_CreateAnimationTree_stub, quick);
Scr_CheckAnimsDefined_hook.create(game::Scr_CheckAnimsDefined_ADDR(), Scr_CheckAnimsDefined_stub, quick);
Scr_PrecacheAnimationTree_hook.create(game::Scr_PrecacheAnimationTree.get(), Scr_PrecacheAnimationTree_stub, quick);
Scr_UsingTreeInternal_hook.create(game::Scr_UsingTreeInternal_ADDR(), Scr_UsingTreeInternal_stub, quick);
Scr_UsingTree_hook.create(game::Scr_UsingTree_ADDR(), Scr_UsingTree_stub, quick);
Scr_SetAnimTreeConfigstring_hook.create(game::Scr_SetAnimTreeConfigstring.get(), Scr_SetAnimTreeConfigstring_stub, quick);
Scr_LoadAnimTreeInternal_hook.create(game::Scr_LoadAnimTreeInternal_ADDR(), Scr_LoadAnimTreeInternal_stub, quick);
Scr_LoadAnimTreeAtIndex_hook.create(game::Scr_LoadAnimTreeAtIndex_ADDR(), Scr_LoadAnimTreeAtIndex_stub, quick);
Scr_FindAnimTree_hook.create(game::Scr_FindAnimTree_ADDR(), Scr_FindAnimTree_stub, quick);
Scr_FindAnim_hook.create(game::Scr_FindAnim_ADDR(), Scr_FindAnim_stub, quick);
AnimTreeCompileError_hook.create(game::AnimTreeCompileError.get(), AnimTreeCompileError_stub);
GetAnimTreeParseProperties_hook.create(game::GetAnimTreeParseProperties.get(), GetAnimTreeParseProperties_stub);
Scr_EmitAnimationInternal_hook.create(game::Scr_EmitAnimationInternal_ADDR(), Scr_EmitAnimationInternal_stub);
AnimTreeParseInternal_hook.create(game::AnimTreeParseInternal.get(), AnimTreeParseInternal_stub);
Scr_AnimTreeParse_hook.create(game::Scr_AnimTreeParse_ADDR(), Scr_AnimTreeParse_stub);
Scr_GetAnimTreeSize_hook.create(game::Scr_GetAnimTreeSize.get(), Scr_GetAnimTreeSize_stub);
ConnectScriptToAnim_hook.create(game::ConnectScriptToAnim_ADDR(), ConnectScriptToAnim_stub);
Scr_GetAnimsIndex_hook.create(game::Scr_GetAnimsIndex_ADDR(), Scr_GetAnimsIndex_stub);
Scr_CreateAnimationTree_hook.create(game::Scr_CreateAnimationTree.get(), Scr_CreateAnimationTree_stub);
Scr_CheckAnimsDefined_hook.create(game::Scr_CheckAnimsDefined_ADDR(), Scr_CheckAnimsDefined_stub);
Scr_PrecacheAnimationTree_hook.create(game::Scr_PrecacheAnimationTree.get(), Scr_PrecacheAnimationTree_stub);
Scr_UsingTreeInternal_hook.create(game::Scr_UsingTreeInternal_ADDR(), Scr_UsingTreeInternal_stub);
Scr_UsingTree_hook.create(game::Scr_UsingTree_ADDR(), Scr_UsingTree_stub);
Scr_SetAnimTreeConfigstring_hook.create(game::Scr_SetAnimTreeConfigstring.get(), Scr_SetAnimTreeConfigstring_stub);
Scr_LoadAnimTreeInternal_hook.create(game::Scr_LoadAnimTreeInternal_ADDR(), Scr_LoadAnimTreeInternal_stub);
Scr_LoadAnimTreeAtIndex_hook.create(game::Scr_LoadAnimTreeAtIndex_ADDR(), Scr_LoadAnimTreeAtIndex_stub);
Scr_FindAnimTree_hook.create(game::Scr_FindAnimTree_ADDR(), Scr_FindAnimTree_stub);
Scr_FindAnim_hook.create(game::Scr_FindAnim_ADDR(), Scr_FindAnim_stub);
//Original hook function addresses
AnimTreeCompileError_original = AnimTreeCompileError_hook.get_original();

View File

@ -3018,161 +3018,156 @@ namespace re_cscr_compiler
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_COMPILER_USE_WRAPPERS
quick = false;
#endif
RemoveRefToValue_hook.create(game::RemoveRefToValue.get(), RemoveRefToValue_stub, quick);
Scr_CompileRemoveRefToString_hook.create(game::Scr_CompileRemoveRefToString_ADDR(), Scr_CompileRemoveRefToString_stub, quick);
EmitCanonicalString_hook.create(game::EmitCanonicalString_ADDR(), EmitCanonicalString_stub, quick);
CompileTransferRefToString_hook.create(game::CompileTransferRefToString_ADDR(), CompileTransferRefToString_stub, quick);
EmitOpcode_hook.create(game::EmitOpcode.get(), EmitOpcode_stub, quick);
EmitEnd_hook.create(game::EmitEnd_ADDR(), EmitEnd_stub, quick);
EmitReturn_hook.create(game::EmitReturn_ADDR(), EmitReturn_stub, quick);
EmitCodepos_hook.create(game::EmitCodepos_ADDR(), EmitCodepos_stub, quick);
EmitShort_hook.create(game::EmitShort_ADDR(), EmitShort_stub, quick);
EmitByte_hook.create(game::EmitByte_ADDR(), EmitByte_stub, quick);
EmitGetInteger_hook.create(game::EmitGetInteger_ADDR(), EmitGetInteger_stub, quick);
EmitGetFloat_hook.create(game::EmitGetFloat_ADDR(), EmitGetFloat_stub, quick);
EmitAnimTree_hook.create(game::EmitAnimTree_ADDR(), EmitAnimTree_stub, quick);
Scr_FindLocalVarIndex_hook.create(game::Scr_FindLocalVarIndex.get(), Scr_FindLocalVarIndex_stub, quick);
EmitCreateLocalVars_hook.create(game::EmitCreateLocalVars.get(), EmitCreateLocalVars_stub, quick);
EmitRemoveLocalVars_hook.create(game::EmitRemoveLocalVars_ADDR(), EmitRemoveLocalVars_stub, quick);
EmitNOP2_hook.create(game::EmitNOP2_ADDR(), EmitNOP2_stub, quick);
Scr_InitFromChildBlocks_hook.create(game::Scr_InitFromChildBlocks.get(), Scr_InitFromChildBlocks_stub, quick);
Scr_AppendChildBlocks_hook.create(game::Scr_AppendChildBlocks_ADDR(), Scr_AppendChildBlocks_stub, quick);
Scr_MergeChildBlocks_hook.create(game::Scr_MergeChildBlocks.get(), Scr_MergeChildBlocks_stub, quick);
Scr_TransferBlock_hook.create(game::Scr_TransferBlock_ADDR(), Scr_TransferBlock_stub, quick);
EmitSafeSetVariableField_hook.create(game::EmitSafeSetVariableField_ADDR(), EmitSafeSetVariableField_stub, quick);
EmitSafeSetWaittillVariableField_hook.create(game::EmitSafeSetWaittillVariableField_ADDR(), EmitSafeSetWaittillVariableField_stub, quick);
EmitGetString_hook.create(game::EmitGetString_ADDR(), EmitGetString_stub, quick);
EmitGetIString_hook.create(game::EmitGetIString_ADDR(), EmitGetIString_stub, quick);
EmitGetVector_hook.create(game::EmitGetVector_ADDR(), EmitGetVector_stub, quick);
EmitValue_hook.create(game::EmitValue.get(), EmitValue_stub, quick);
Scr_PushValue_hook.create(game::Scr_PushValue_ADDR(), Scr_PushValue_stub, quick);
EmitCastBool_hook.create(game::EmitCastBool_ADDR(), EmitCastBool_stub, quick);
EmitBoolNot_hook.create(game::EmitBoolNot_ADDR(), EmitBoolNot_stub, quick);
EmitBoolComplement_hook.create(game::EmitBoolComplement_ADDR(), EmitBoolComplement_stub, quick);
EmitSize_hook.create(game::EmitSize_ADDR(), EmitSize_stub, quick);
EmitSelf_hook.create(game::EmitSelf_ADDR(), EmitSelf_stub, quick);
EmitLevel_hook.create(game::EmitLevel_ADDR(), EmitLevel_stub, quick);
EmitGame_hook.create(game::EmitGame_ADDR(), EmitGame_stub, quick);
EmitAnim_hook.create(game::EmitAnim_ADDR(), EmitAnim_stub, quick);
EmitSelfObject_hook.create(game::EmitSelfObject_ADDR(), EmitSelfObject_stub, quick);
EmitLevelObject_hook.create(game::EmitLevelObject_ADDR(), EmitLevelObject_stub, quick);
EmitAnimObject_hook.create(game::EmitAnimObject_ADDR(), EmitAnimObject_stub, quick);
EmitLocalVariable_hook.create(game::EmitLocalVariable_ADDR(), EmitLocalVariable_stub, quick);
EmitLocalVariableRef_hook.create(game::EmitLocalVariableRef_ADDR(), EmitLocalVariableRef_stub, quick);
Scr_RegisterLocalVar_hook.create(game::Scr_RegisterLocalVar.get(), Scr_RegisterLocalVar_stub, quick);
EmitGameRef_hook.create(game::EmitGameRef_ADDR(), EmitGameRef_stub, quick);
EmitClearArray_hook.create(game::EmitClearArray_ADDR(), EmitClearArray_stub, quick);
EmitEmptyArray_hook.create(game::EmitEmptyArray_ADDR(), EmitEmptyArray_stub, quick);
EmitAnimation_hook.create(game::EmitAnimation_ADDR(), EmitAnimation_stub, quick);
EmitFieldVariable_hook.create(game::EmitFieldVariable_ADDR(), EmitFieldVariable_stub, quick);
EmitClearFieldVariable_hook.create(game::EmitClearFieldVariable_ADDR(), EmitClearFieldVariable_stub, quick);
EmitObject_hook.create(game::EmitObject_ADDR(), EmitObject_stub, quick);
EmitDecTop_hook.create(game::EmitDecTop_ADDR(), EmitDecTop_stub, quick);
EmitCastFieldObject_hook.create(game::EmitCastFieldObject.get(), EmitCastFieldObject_stub, quick);
EmitArrayVariable_hook.create(game::EmitArrayVariable_ADDR(), EmitArrayVariable_stub, quick);
EmitArrayVariableRef_hook.create(game::EmitArrayVariableRef_ADDR(), EmitArrayVariableRef_stub, quick);
EmitClearArrayVariable_hook.create(game::EmitClearArrayVariable_ADDR(), EmitClearArrayVariable_stub, quick);
EmitVariableExpression_hook.create(game::EmitVariableExpression.get(), EmitVariableExpression_stub, quick);
EmitExpressionList_hook.create(game::EmitExpressionList.get(), EmitExpressionList_stub, quick);
AddExpressionListOpcodePos_hook.create(game::AddExpressionListOpcodePos_ADDR(), AddExpressionListOpcodePos_stub, quick);
AddFilePrecache_hook.create(game::AddFilePrecache_ADDR(), AddFilePrecache_stub, quick);
EmitFunction_hook.create(game::EmitFunction_ADDR(), EmitFunction_stub, quick);
EmitGetFunction_hook.create(game::EmitGetFunction_ADDR(), EmitGetFunction_stub, quick);
AddFunction_hook.create(game::AddFunction.get(), AddFunction_stub, quick);
EmitPostScriptFunction_hook.create(game::EmitPostScriptFunction.get(), EmitPostScriptFunction_stub, quick);
EmitPostScriptFunctionPointer_hook.create(game::EmitPostScriptFunctionPointer_ADDR(), EmitPostScriptFunctionPointer_stub, quick);
EmitPostScriptThread_hook.create(game::EmitPostScriptThread_ADDR(), EmitPostScriptThread_stub, quick);
EmitPostScriptThreadPointer_hook.create(game::EmitPostScriptThreadPointer_ADDR(), EmitPostScriptThreadPointer_stub, quick);
EmitPostScriptFunctionCall_hook.create(game::EmitPostScriptFunctionCall_ADDR(), EmitPostScriptFunctionCall_stub, quick);
EmitPostScriptThreadCall_hook.create(game::EmitPostScriptThreadCall_ADDR(), EmitPostScriptThreadCall_stub, quick);
EmitPreFunctionCall_hook.create(game::EmitPreFunctionCall_ADDR(), EmitPreFunctionCall_stub, quick);
EmitPostFunctionCall_hook.create(game::EmitPostFunctionCall_ADDR(), EmitPostFunctionCall_stub, quick);
Scr_BeginDevScript_hook.create(game::Scr_BeginDevScript_ADDR(), Scr_BeginDevScript_stub, quick);
Scr_EndDevScript_hook.create(game::Scr_EndDevScript_ADDR(), Scr_EndDevScript_stub, quick);
EmitCallBuiltinOpcode_hook.create(game::EmitCallBuiltinOpcode_ADDR(), EmitCallBuiltinOpcode_stub, quick);
EmitCallBuiltinMethodOpcode_hook.create(game::EmitCallBuiltinMethodOpcode_ADDR(), EmitCallBuiltinMethodOpcode_stub, quick);
EmitCall_hook.create(game::EmitCall_ADDR(), EmitCall_stub, quick);
EmitMethod_hook.create(game::EmitMethod.get(), EmitMethod_stub, quick);
LinkThread_hook.create(game::LinkThread_ADDR(), LinkThread_stub, quick);
LinkFile_hook.create(game::LinkFile_ADDR(), LinkFile_stub, quick);
CheckThreadPosition_hook.create(game::CheckThreadPosition.get(), CheckThreadPosition_stub, quick);
EmitCallExpression_hook.create(game::EmitCallExpression_ADDR(), EmitCallExpression_stub, quick);
EmitCallExpressionFieldObject_hook.create(game::EmitCallExpressionFieldObject_ADDR(), EmitCallExpressionFieldObject_stub, quick);
Scr_CreateVector_hook.create(game::Scr_CreateVector_ADDR(), Scr_CreateVector_stub, quick);
EvalPrimitiveExpressionList_hook.create(game::EvalPrimitiveExpressionList.get(), EvalPrimitiveExpressionList_stub, quick);
EmitOrEvalPrimitiveExpressionList_hook.create(game::EmitOrEvalPrimitiveExpressionList_ADDR(), EmitOrEvalPrimitiveExpressionList_stub, quick);
EmitExpressionListFieldObject_hook.create(game::EmitExpressionListFieldObject_ADDR(), EmitExpressionListFieldObject_stub, quick);
EvalPrimitiveExpression_hook.create(game::EvalPrimitiveExpression.get(), EvalPrimitiveExpression_stub, quick);
EmitOrEvalPrimitiveExpression_hook.create(game::EmitOrEvalPrimitiveExpression.get(), EmitOrEvalPrimitiveExpression_stub, quick);
EmitBoolOrExpression_hook.create(game::EmitBoolOrExpression_ADDR(), EmitBoolOrExpression_stub, quick);
EmitBoolAndExpression_hook.create(game::EmitBoolAndExpression_ADDR(), EmitBoolAndExpression_stub, quick);
EvalBinaryOperatorExpression_hook.create(game::EvalBinaryOperatorExpression.get(), EvalBinaryOperatorExpression_stub, quick);
EmitOrEvalBinaryOperatorExpression_hook.create(game::EmitOrEvalBinaryOperatorExpression_ADDR(), EmitOrEvalBinaryOperatorExpression_stub, quick);
EmitBinaryEqualsOperatorExpression_hook.create(game::EmitBinaryEqualsOperatorExpression_ADDR(), EmitBinaryEqualsOperatorExpression_stub, quick);
Scr_CalcLocalVarsVariableExpressionRef_hook.create(game::Scr_CalcLocalVarsVariableExpressionRef_ADDR(), Scr_CalcLocalVarsVariableExpressionRef_stub, quick);
EvalExpression_hook.create(game::EvalExpression_ADDR(), EvalExpression_stub, quick);
EmitOrEvalExpression_hook.create(game::EmitOrEvalExpression.get(), EmitOrEvalExpression_stub, quick);
EmitExpression_hook.create(game::EmitExpression.get(), EmitExpression_stub, quick);
EmitVariableExpressionRef_hook.create(game::EmitVariableExpressionRef.get(), EmitVariableExpressionRef_stub, quick);
EmitArrayPrimitiveExpressionRef_hook.create(game::EmitArrayPrimitiveExpressionRef_ADDR(), EmitArrayPrimitiveExpressionRef_stub, quick);
Scr_CalcLocalVarsArrayVariableRef_hook.create(game::Scr_CalcLocalVarsArrayVariableRef.get(), Scr_CalcLocalVarsArrayVariableRef_stub, quick);
EmitPrimitiveExpressionFieldObject_hook.create(game::EmitPrimitiveExpressionFieldObject.get(), EmitPrimitiveExpressionFieldObject_stub, quick);
ConnectBreakStatements_hook.create(game::ConnectBreakStatements_ADDR(), ConnectBreakStatements_stub, quick);
ConnectContinueStatements_hook.create(game::ConnectContinueStatements_ADDR(), ConnectContinueStatements_stub, quick);
EmitClearVariableExpression_hook.create(game::EmitClearVariableExpression_ADDR(), EmitClearVariableExpression_stub, quick);
EmitAssignmentStatement_hook.create(game::EmitAssignmentStatement_ADDR(), EmitAssignmentStatement_stub, quick);
EmitCallExpressionStatement_hook.create(game::EmitCallExpressionStatement_ADDR(), EmitCallExpressionStatement_stub, quick);
EmitReturnStatement_hook.create(game::EmitReturnStatement_ADDR(), EmitReturnStatement_stub, quick);
EmitWaitStatement_hook.create(game::EmitWaitStatement_ADDR(), EmitWaitStatement_stub, quick);
EmitWaittillFrameEnd_hook.create(game::EmitWaittillFrameEnd_ADDR(), EmitWaittillFrameEnd_stub, quick);
EmitIfStatement_hook.create(game::EmitIfStatement_ADDR(), EmitIfStatement_stub, quick);
Scr_CalcLocalVarsIfStatement_hook.create(game::Scr_CalcLocalVarsIfStatement.get(), Scr_CalcLocalVarsIfStatement_stub, quick);
EmitIfElseStatement_hook.create(game::EmitIfElseStatement.get(), EmitIfElseStatement_stub, quick);
Scr_CalcLocalVarsIfElseStatement_hook.create(game::Scr_CalcLocalVarsIfElseStatement.get(), Scr_CalcLocalVarsIfElseStatement_stub, quick);
Scr_AddBreakBlock_hook.create(game::Scr_AddBreakBlock_ADDR(), Scr_AddBreakBlock_stub, quick);
Scr_AddContinueBlock_hook.create(game::Scr_AddContinueBlock_ADDR(), Scr_AddContinueBlock_stub, quick);
EmitWhileStatement_hook.create(game::EmitWhileStatement.get(), EmitWhileStatement_stub, quick);
Scr_CalcLocalVarsWhileStatement_hook.create(game::Scr_CalcLocalVarsWhileStatement.get(), Scr_CalcLocalVarsWhileStatement_stub, quick);
EmitForStatement_hook.create(game::EmitForStatement.get(), EmitForStatement_stub, quick);
Scr_CalcLocalVarsForStatement_hook.create(game::Scr_CalcLocalVarsForStatement.get(), Scr_CalcLocalVarsForStatement_stub, quick);
EmitIncStatement_hook.create(game::EmitIncStatement_ADDR(), EmitIncStatement_stub, quick);
EmitDecStatement_hook.create(game::EmitDecStatement_ADDR(), EmitDecStatement_stub, quick);
Scr_CalcLocalVarsFormalParameterListInternal_hook.create(game::Scr_CalcLocalVarsFormalParameterListInternal_ADDR(), Scr_CalcLocalVarsFormalParameterListInternal_stub, quick);
EmitWaittillStatement_hook.create(game::EmitWaittillStatement_ADDR(), EmitWaittillStatement_stub, quick);
EmitWaittillmatchStatement_hook.create(game::EmitWaittillmatchStatement_ADDR(), EmitWaittillmatchStatement_stub, quick);
EmitNotifyStatement_hook.create(game::EmitNotifyStatement_ADDR(), EmitNotifyStatement_stub, quick);
EmitEndOnStatement_hook.create(game::EmitEndOnStatement_ADDR(), EmitEndOnStatement_stub, quick);
CompareCaseInfo_hook.create(game::CompareCaseInfo.get(), CompareCaseInfo_stub, quick);
EmitCaseStatement_hook.create(game::EmitCaseStatement_ADDR(), EmitCaseStatement_stub, quick);
EmitSwitchStatementList_hook.create(game::EmitSwitchStatementList.get(), EmitSwitchStatementList_stub, quick);
Scr_CalcLocalVarsSwitchStatement_hook.create(game::Scr_CalcLocalVarsSwitchStatement.get(), Scr_CalcLocalVarsSwitchStatement_stub, quick);
EmitSwitchStatement_hook.create(game::EmitSwitchStatement.get(), EmitSwitchStatement_stub, quick);
EmitCaseStatementInfo_hook.create(game::EmitCaseStatementInfo_ADDR(), EmitCaseStatementInfo_stub, quick);
EmitBreakStatement_hook.create(game::EmitBreakStatement_ADDR(), EmitBreakStatement_stub, quick);
EmitContinueStatement_hook.create(game::EmitContinueStatement_ADDR(), EmitContinueStatement_stub, quick);
EmitProfStatement_hook.create(game::EmitProfStatement_ADDR(), EmitProfStatement_stub, quick);
EmitStatement_hook.create(game::EmitStatement.get(), EmitStatement_stub, quick);
Scr_CalcLocalVarsStatement_hook.create(game::Scr_CalcLocalVarsStatement.get(), Scr_CalcLocalVarsStatement_stub, quick);
EmitStatementList_hook.create(game::EmitStatementList.get(), EmitStatementList_stub, quick);
Scr_CalcLocalVarsStatementList_hook.create(game::Scr_CalcLocalVarsStatementList_ADDR(), Scr_CalcLocalVarsStatementList_stub, quick);
Scr_CalcLocalVarsDeveloperStatementList_hook.create(game::Scr_CalcLocalVarsDeveloperStatementList.get(), Scr_CalcLocalVarsDeveloperStatementList_stub, quick);
EmitDeveloperStatementList_hook.create(game::EmitDeveloperStatementList.get(), EmitDeveloperStatementList_stub, quick);
EmitFormalParameterList_hook.create(game::EmitFormalParameterList_ADDR(), EmitFormalParameterList_stub, quick);
SpecifyThread_hook.create(game::SpecifyThread_ADDR(), SpecifyThread_stub, quick);
EmitThreadInternal_hook.create(game::EmitThreadInternal_ADDR(), EmitThreadInternal_stub, quick);
Scr_CalcLocalVarsThread_hook.create(game::Scr_CalcLocalVarsThread_ADDR(), Scr_CalcLocalVarsThread_stub, quick);
InitThread_hook.create(game::InitThread_ADDR(), InitThread_stub, quick);
EmitNormalThread_hook.create(game::EmitNormalThread_ADDR(), EmitNormalThread_stub, quick);
EmitDeveloperThread_hook.create(game::EmitDeveloperThread_ADDR(), EmitDeveloperThread_stub, quick);
EmitThread_hook.create(game::EmitThread_ADDR(), EmitThread_stub, quick);
EmitThreadList_hook.create(game::EmitThreadList.get(), EmitThreadList_stub, quick);
EmitInclude_hook.create(game::EmitInclude_ADDR(), EmitInclude_stub, quick);
ScriptCompile_hook.create(game::ScriptCompile_ADDR(), ScriptCompile_stub, quick);
RemoveRefToValue_hook.create(game::RemoveRefToValue.get(), RemoveRefToValue_stub);
Scr_CompileRemoveRefToString_hook.create(game::Scr_CompileRemoveRefToString_ADDR(), Scr_CompileRemoveRefToString_stub);
EmitCanonicalString_hook.create(game::EmitCanonicalString_ADDR(), EmitCanonicalString_stub);
CompileTransferRefToString_hook.create(game::CompileTransferRefToString_ADDR(), CompileTransferRefToString_stub);
EmitOpcode_hook.create(game::EmitOpcode.get(), EmitOpcode_stub);
EmitEnd_hook.create(game::EmitEnd_ADDR(), EmitEnd_stub);
EmitReturn_hook.create(game::EmitReturn_ADDR(), EmitReturn_stub);
EmitCodepos_hook.create(game::EmitCodepos_ADDR(), EmitCodepos_stub);
EmitShort_hook.create(game::EmitShort_ADDR(), EmitShort_stub);
EmitByte_hook.create(game::EmitByte_ADDR(), EmitByte_stub);
EmitGetInteger_hook.create(game::EmitGetInteger_ADDR(), EmitGetInteger_stub);
EmitGetFloat_hook.create(game::EmitGetFloat_ADDR(), EmitGetFloat_stub);
EmitAnimTree_hook.create(game::EmitAnimTree_ADDR(), EmitAnimTree_stub);
Scr_FindLocalVarIndex_hook.create(game::Scr_FindLocalVarIndex.get(), Scr_FindLocalVarIndex_stub);
EmitCreateLocalVars_hook.create(game::EmitCreateLocalVars.get(), EmitCreateLocalVars_stub);
EmitRemoveLocalVars_hook.create(game::EmitRemoveLocalVars_ADDR(), EmitRemoveLocalVars_stub);
EmitNOP2_hook.create(game::EmitNOP2_ADDR(), EmitNOP2_stub);
Scr_InitFromChildBlocks_hook.create(game::Scr_InitFromChildBlocks.get(), Scr_InitFromChildBlocks_stub);
Scr_AppendChildBlocks_hook.create(game::Scr_AppendChildBlocks_ADDR(), Scr_AppendChildBlocks_stub);
Scr_MergeChildBlocks_hook.create(game::Scr_MergeChildBlocks.get(), Scr_MergeChildBlocks_stub);
Scr_TransferBlock_hook.create(game::Scr_TransferBlock_ADDR(), Scr_TransferBlock_stub);
EmitSafeSetVariableField_hook.create(game::EmitSafeSetVariableField_ADDR(), EmitSafeSetVariableField_stub);
EmitSafeSetWaittillVariableField_hook.create(game::EmitSafeSetWaittillVariableField_ADDR(), EmitSafeSetWaittillVariableField_stub);
EmitGetString_hook.create(game::EmitGetString_ADDR(), EmitGetString_stub);
EmitGetIString_hook.create(game::EmitGetIString_ADDR(), EmitGetIString_stub);
EmitGetVector_hook.create(game::EmitGetVector_ADDR(), EmitGetVector_stub);
EmitValue_hook.create(game::EmitValue.get(), EmitValue_stub);
Scr_PushValue_hook.create(game::Scr_PushValue_ADDR(), Scr_PushValue_stub);
EmitCastBool_hook.create(game::EmitCastBool_ADDR(), EmitCastBool_stub);
EmitBoolNot_hook.create(game::EmitBoolNot_ADDR(), EmitBoolNot_stub);
EmitBoolComplement_hook.create(game::EmitBoolComplement_ADDR(), EmitBoolComplement_stub);
EmitSize_hook.create(game::EmitSize_ADDR(), EmitSize_stub);
EmitSelf_hook.create(game::EmitSelf_ADDR(), EmitSelf_stub);
EmitLevel_hook.create(game::EmitLevel_ADDR(), EmitLevel_stub);
EmitGame_hook.create(game::EmitGame_ADDR(), EmitGame_stub);
EmitAnim_hook.create(game::EmitAnim_ADDR(), EmitAnim_stub);
EmitSelfObject_hook.create(game::EmitSelfObject_ADDR(), EmitSelfObject_stub);
EmitLevelObject_hook.create(game::EmitLevelObject_ADDR(), EmitLevelObject_stub);
EmitAnimObject_hook.create(game::EmitAnimObject_ADDR(), EmitAnimObject_stub);
EmitLocalVariable_hook.create(game::EmitLocalVariable_ADDR(), EmitLocalVariable_stub);
EmitLocalVariableRef_hook.create(game::EmitLocalVariableRef_ADDR(), EmitLocalVariableRef_stub);
Scr_RegisterLocalVar_hook.create(game::Scr_RegisterLocalVar.get(), Scr_RegisterLocalVar_stub);
EmitGameRef_hook.create(game::EmitGameRef_ADDR(), EmitGameRef_stub);
EmitClearArray_hook.create(game::EmitClearArray_ADDR(), EmitClearArray_stub);
EmitEmptyArray_hook.create(game::EmitEmptyArray_ADDR(), EmitEmptyArray_stub);
EmitAnimation_hook.create(game::EmitAnimation_ADDR(), EmitAnimation_stub);
EmitFieldVariable_hook.create(game::EmitFieldVariable_ADDR(), EmitFieldVariable_stub);
EmitClearFieldVariable_hook.create(game::EmitClearFieldVariable_ADDR(), EmitClearFieldVariable_stub);
EmitObject_hook.create(game::EmitObject_ADDR(), EmitObject_stub);
EmitDecTop_hook.create(game::EmitDecTop_ADDR(), EmitDecTop_stub);
EmitCastFieldObject_hook.create(game::EmitCastFieldObject.get(), EmitCastFieldObject_stub);
EmitArrayVariable_hook.create(game::EmitArrayVariable_ADDR(), EmitArrayVariable_stub);
EmitArrayVariableRef_hook.create(game::EmitArrayVariableRef_ADDR(), EmitArrayVariableRef_stub);
EmitClearArrayVariable_hook.create(game::EmitClearArrayVariable_ADDR(), EmitClearArrayVariable_stub);
EmitVariableExpression_hook.create(game::EmitVariableExpression.get(), EmitVariableExpression_stub);
EmitExpressionList_hook.create(game::EmitExpressionList.get(), EmitExpressionList_stub);
AddExpressionListOpcodePos_hook.create(game::AddExpressionListOpcodePos_ADDR(), AddExpressionListOpcodePos_stub);
AddFilePrecache_hook.create(game::AddFilePrecache_ADDR(), AddFilePrecache_stub);
EmitFunction_hook.create(game::EmitFunction_ADDR(), EmitFunction_stub);
EmitGetFunction_hook.create(game::EmitGetFunction_ADDR(), EmitGetFunction_stub);
AddFunction_hook.create(game::AddFunction.get(), AddFunction_stub);
EmitPostScriptFunction_hook.create(game::EmitPostScriptFunction.get(), EmitPostScriptFunction_stub);
EmitPostScriptFunctionPointer_hook.create(game::EmitPostScriptFunctionPointer_ADDR(), EmitPostScriptFunctionPointer_stub);
EmitPostScriptThread_hook.create(game::EmitPostScriptThread_ADDR(), EmitPostScriptThread_stub);
EmitPostScriptThreadPointer_hook.create(game::EmitPostScriptThreadPointer_ADDR(), EmitPostScriptThreadPointer_stub);
EmitPostScriptFunctionCall_hook.create(game::EmitPostScriptFunctionCall_ADDR(), EmitPostScriptFunctionCall_stub);
EmitPostScriptThreadCall_hook.create(game::EmitPostScriptThreadCall_ADDR(), EmitPostScriptThreadCall_stub);
EmitPreFunctionCall_hook.create(game::EmitPreFunctionCall_ADDR(), EmitPreFunctionCall_stub);
EmitPostFunctionCall_hook.create(game::EmitPostFunctionCall_ADDR(), EmitPostFunctionCall_stub);
Scr_BeginDevScript_hook.create(game::Scr_BeginDevScript_ADDR(), Scr_BeginDevScript_stub);
Scr_EndDevScript_hook.create(game::Scr_EndDevScript_ADDR(), Scr_EndDevScript_stub);
EmitCallBuiltinOpcode_hook.create(game::EmitCallBuiltinOpcode_ADDR(), EmitCallBuiltinOpcode_stub);
EmitCallBuiltinMethodOpcode_hook.create(game::EmitCallBuiltinMethodOpcode_ADDR(), EmitCallBuiltinMethodOpcode_stub);
EmitCall_hook.create(game::EmitCall_ADDR(), EmitCall_stub);
EmitMethod_hook.create(game::EmitMethod.get(), EmitMethod_stub);
LinkThread_hook.create(game::LinkThread_ADDR(), LinkThread_stub);
LinkFile_hook.create(game::LinkFile_ADDR(), LinkFile_stub);
CheckThreadPosition_hook.create(game::CheckThreadPosition.get(), CheckThreadPosition_stub);
EmitCallExpression_hook.create(game::EmitCallExpression_ADDR(), EmitCallExpression_stub);
EmitCallExpressionFieldObject_hook.create(game::EmitCallExpressionFieldObject_ADDR(), EmitCallExpressionFieldObject_stub);
Scr_CreateVector_hook.create(game::Scr_CreateVector_ADDR(), Scr_CreateVector_stub);
EvalPrimitiveExpressionList_hook.create(game::EvalPrimitiveExpressionList.get(), EvalPrimitiveExpressionList_stub);
EmitOrEvalPrimitiveExpressionList_hook.create(game::EmitOrEvalPrimitiveExpressionList_ADDR(), EmitOrEvalPrimitiveExpressionList_stub);
EmitExpressionListFieldObject_hook.create(game::EmitExpressionListFieldObject_ADDR(), EmitExpressionListFieldObject_stub);
EvalPrimitiveExpression_hook.create(game::EvalPrimitiveExpression.get(), EvalPrimitiveExpression_stub);
EmitOrEvalPrimitiveExpression_hook.create(game::EmitOrEvalPrimitiveExpression.get(), EmitOrEvalPrimitiveExpression_stub);
EmitBoolOrExpression_hook.create(game::EmitBoolOrExpression_ADDR(), EmitBoolOrExpression_stub);
EmitBoolAndExpression_hook.create(game::EmitBoolAndExpression_ADDR(), EmitBoolAndExpression_stub);
EvalBinaryOperatorExpression_hook.create(game::EvalBinaryOperatorExpression.get(), EvalBinaryOperatorExpression_stub);
EmitOrEvalBinaryOperatorExpression_hook.create(game::EmitOrEvalBinaryOperatorExpression_ADDR(), EmitOrEvalBinaryOperatorExpression_stub);
EmitBinaryEqualsOperatorExpression_hook.create(game::EmitBinaryEqualsOperatorExpression_ADDR(), EmitBinaryEqualsOperatorExpression_stub);
Scr_CalcLocalVarsVariableExpressionRef_hook.create(game::Scr_CalcLocalVarsVariableExpressionRef_ADDR(), Scr_CalcLocalVarsVariableExpressionRef_stub);
EvalExpression_hook.create(game::EvalExpression_ADDR(), EvalExpression_stub);
EmitOrEvalExpression_hook.create(game::EmitOrEvalExpression.get(), EmitOrEvalExpression_stub);
EmitExpression_hook.create(game::EmitExpression.get(), EmitExpression_stub);
EmitVariableExpressionRef_hook.create(game::EmitVariableExpressionRef.get(), EmitVariableExpressionRef_stub);
EmitArrayPrimitiveExpressionRef_hook.create(game::EmitArrayPrimitiveExpressionRef_ADDR(), EmitArrayPrimitiveExpressionRef_stub);
Scr_CalcLocalVarsArrayVariableRef_hook.create(game::Scr_CalcLocalVarsArrayVariableRef.get(), Scr_CalcLocalVarsArrayVariableRef_stub);
EmitPrimitiveExpressionFieldObject_hook.create(game::EmitPrimitiveExpressionFieldObject.get(), EmitPrimitiveExpressionFieldObject_stub);
ConnectBreakStatements_hook.create(game::ConnectBreakStatements_ADDR(), ConnectBreakStatements_stub);
ConnectContinueStatements_hook.create(game::ConnectContinueStatements_ADDR(), ConnectContinueStatements_stub);
EmitClearVariableExpression_hook.create(game::EmitClearVariableExpression_ADDR(), EmitClearVariableExpression_stub);
EmitAssignmentStatement_hook.create(game::EmitAssignmentStatement_ADDR(), EmitAssignmentStatement_stub);
EmitCallExpressionStatement_hook.create(game::EmitCallExpressionStatement_ADDR(), EmitCallExpressionStatement_stub);
EmitReturnStatement_hook.create(game::EmitReturnStatement_ADDR(), EmitReturnStatement_stub);
EmitWaitStatement_hook.create(game::EmitWaitStatement_ADDR(), EmitWaitStatement_stub);
EmitWaittillFrameEnd_hook.create(game::EmitWaittillFrameEnd_ADDR(), EmitWaittillFrameEnd_stub);
EmitIfStatement_hook.create(game::EmitIfStatement_ADDR(), EmitIfStatement_stub);
Scr_CalcLocalVarsIfStatement_hook.create(game::Scr_CalcLocalVarsIfStatement.get(), Scr_CalcLocalVarsIfStatement_stub);
EmitIfElseStatement_hook.create(game::EmitIfElseStatement.get(), EmitIfElseStatement_stub);
Scr_CalcLocalVarsIfElseStatement_hook.create(game::Scr_CalcLocalVarsIfElseStatement.get(), Scr_CalcLocalVarsIfElseStatement_stub);
Scr_AddBreakBlock_hook.create(game::Scr_AddBreakBlock_ADDR(), Scr_AddBreakBlock_stub);
Scr_AddContinueBlock_hook.create(game::Scr_AddContinueBlock_ADDR(), Scr_AddContinueBlock_stub);
EmitWhileStatement_hook.create(game::EmitWhileStatement.get(), EmitWhileStatement_stub);
Scr_CalcLocalVarsWhileStatement_hook.create(game::Scr_CalcLocalVarsWhileStatement.get(), Scr_CalcLocalVarsWhileStatement_stub);
EmitForStatement_hook.create(game::EmitForStatement.get(), EmitForStatement_stub);
Scr_CalcLocalVarsForStatement_hook.create(game::Scr_CalcLocalVarsForStatement.get(), Scr_CalcLocalVarsForStatement_stub);
EmitIncStatement_hook.create(game::EmitIncStatement_ADDR(), EmitIncStatement_stub);
EmitDecStatement_hook.create(game::EmitDecStatement_ADDR(), EmitDecStatement_stub);
Scr_CalcLocalVarsFormalParameterListInternal_hook.create(game::Scr_CalcLocalVarsFormalParameterListInternal_ADDR(), Scr_CalcLocalVarsFormalParameterListInternal_stub);
EmitWaittillStatement_hook.create(game::EmitWaittillStatement_ADDR(), EmitWaittillStatement_stub);
EmitWaittillmatchStatement_hook.create(game::EmitWaittillmatchStatement_ADDR(), EmitWaittillmatchStatement_stub);
EmitNotifyStatement_hook.create(game::EmitNotifyStatement_ADDR(), EmitNotifyStatement_stub);
EmitEndOnStatement_hook.create(game::EmitEndOnStatement_ADDR(), EmitEndOnStatement_stub);
CompareCaseInfo_hook.create(game::CompareCaseInfo.get(), CompareCaseInfo_stub);
EmitCaseStatement_hook.create(game::EmitCaseStatement_ADDR(), EmitCaseStatement_stub);
EmitSwitchStatementList_hook.create(game::EmitSwitchStatementList.get(), EmitSwitchStatementList_stub);
Scr_CalcLocalVarsSwitchStatement_hook.create(game::Scr_CalcLocalVarsSwitchStatement.get(), Scr_CalcLocalVarsSwitchStatement_stub);
EmitSwitchStatement_hook.create(game::EmitSwitchStatement.get(), EmitSwitchStatement_stub);
EmitCaseStatementInfo_hook.create(game::EmitCaseStatementInfo_ADDR(), EmitCaseStatementInfo_stub);
EmitBreakStatement_hook.create(game::EmitBreakStatement_ADDR(), EmitBreakStatement_stub);
EmitContinueStatement_hook.create(game::EmitContinueStatement_ADDR(), EmitContinueStatement_stub);
EmitProfStatement_hook.create(game::EmitProfStatement_ADDR(), EmitProfStatement_stub);
EmitStatement_hook.create(game::EmitStatement.get(), EmitStatement_stub);
Scr_CalcLocalVarsStatement_hook.create(game::Scr_CalcLocalVarsStatement.get(), Scr_CalcLocalVarsStatement_stub);
EmitStatementList_hook.create(game::EmitStatementList.get(), EmitStatementList_stub);
Scr_CalcLocalVarsStatementList_hook.create(game::Scr_CalcLocalVarsStatementList_ADDR(), Scr_CalcLocalVarsStatementList_stub);
Scr_CalcLocalVarsDeveloperStatementList_hook.create(game::Scr_CalcLocalVarsDeveloperStatementList.get(), Scr_CalcLocalVarsDeveloperStatementList_stub);
EmitDeveloperStatementList_hook.create(game::EmitDeveloperStatementList.get(), EmitDeveloperStatementList_stub);
EmitFormalParameterList_hook.create(game::EmitFormalParameterList_ADDR(), EmitFormalParameterList_stub);
SpecifyThread_hook.create(game::SpecifyThread_ADDR(), SpecifyThread_stub);
EmitThreadInternal_hook.create(game::EmitThreadInternal_ADDR(), EmitThreadInternal_stub);
Scr_CalcLocalVarsThread_hook.create(game::Scr_CalcLocalVarsThread_ADDR(), Scr_CalcLocalVarsThread_stub);
InitThread_hook.create(game::InitThread_ADDR(), InitThread_stub);
EmitNormalThread_hook.create(game::EmitNormalThread_ADDR(), EmitNormalThread_stub);
EmitDeveloperThread_hook.create(game::EmitDeveloperThread_ADDR(), EmitDeveloperThread_stub);
EmitThread_hook.create(game::EmitThread_ADDR(), EmitThread_stub);
EmitThreadList_hook.create(game::EmitThreadList.get(), EmitThreadList_stub);
EmitInclude_hook.create(game::EmitInclude_ADDR(), EmitInclude_stub);
ScriptCompile_hook.create(game::ScriptCompile_ADDR(), ScriptCompile_stub);
//Original hook function addresses
RemoveRefToValue_original = RemoveRefToValue_hook.get_original();

View File

@ -272,24 +272,19 @@ namespace re_cscr_main
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_MAIN_USE_WRAPPERS
quick = false;
#endif
Scr_IsIdentifier_hook.create(game::Scr_IsIdentifier_ADDR(), Scr_IsIdentifier_stub, quick);
Scr_GetFunctionHandle_hook.create(game::Scr_GetFunctionHandle_ADDR(), Scr_GetFunctionHandle_stub, quick);
SL_TransferToCanonicalString_hook.create(game::SL_TransferToCanonicalString_ADDR(), SL_TransferToCanonicalString_stub, quick);
SL_GetCanonicalString_hook.create(game::SL_GetCanonicalString_ADDR(), SL_GetCanonicalString_stub, quick);
Scr_BeginLoadScripts_hook.create(game::Scr_BeginLoadScripts_ADDR(), Scr_BeginLoadScripts_stub, quick);
Scr_BeginLoadAnimTrees_hook.create(game::Scr_BeginLoadAnimTrees_ADDR(), Scr_BeginLoadAnimTrees_stub, quick);
Scr_ScanFile_hook.create(game::Scr_ScanFile_ADDR(), Scr_ScanFile_stub, quick);
Scr_LoadScriptInternal_hook.create(game::Scr_LoadScriptInternal.get(), Scr_LoadScriptInternal_stub, quick);
Scr_LoadScript_hook.create(game::Scr_LoadScript_ADDR(), Scr_LoadScript_stub, quick);
Scr_EndLoadScripts_hook.create(game::Scr_EndLoadScripts.get(), Scr_EndLoadScripts_stub, quick);
Scr_PrecacheAnimTrees_hook.create(game::Scr_PrecacheAnimTrees.get(), Scr_PrecacheAnimTrees_stub, quick);
Scr_EndLoadAnimTrees_hook.create(game::Scr_EndLoadAnimTrees.get(), Scr_EndLoadAnimTrees_stub, quick);
Scr_FreeScripts_hook.create(game::Scr_FreeScripts_ADDR(), Scr_FreeScripts_stub, quick);
Scr_IsIdentifier_hook.create(game::Scr_IsIdentifier_ADDR(), Scr_IsIdentifier_stub);
Scr_GetFunctionHandle_hook.create(game::Scr_GetFunctionHandle_ADDR(), Scr_GetFunctionHandle_stub);
SL_TransferToCanonicalString_hook.create(game::SL_TransferToCanonicalString_ADDR(), SL_TransferToCanonicalString_stub);
SL_GetCanonicalString_hook.create(game::SL_GetCanonicalString_ADDR(), SL_GetCanonicalString_stub);
Scr_BeginLoadScripts_hook.create(game::Scr_BeginLoadScripts_ADDR(), Scr_BeginLoadScripts_stub);
Scr_BeginLoadAnimTrees_hook.create(game::Scr_BeginLoadAnimTrees_ADDR(), Scr_BeginLoadAnimTrees_stub);
Scr_ScanFile_hook.create(game::Scr_ScanFile_ADDR(), Scr_ScanFile_stub);
Scr_LoadScriptInternal_hook.create(game::Scr_LoadScriptInternal.get(), Scr_LoadScriptInternal_stub);
Scr_LoadScript_hook.create(game::Scr_LoadScript_ADDR(), Scr_LoadScript_stub);
Scr_EndLoadScripts_hook.create(game::Scr_EndLoadScripts.get(), Scr_EndLoadScripts_stub);
Scr_PrecacheAnimTrees_hook.create(game::Scr_PrecacheAnimTrees.get(), Scr_PrecacheAnimTrees_stub);
Scr_EndLoadAnimTrees_hook.create(game::Scr_EndLoadAnimTrees.get(), Scr_EndLoadAnimTrees_stub);
Scr_FreeScripts_hook.create(game::Scr_FreeScripts_ADDR(), Scr_FreeScripts_stub);
//Original hook function addresses
Scr_IsIdentifier_original = Scr_IsIdentifier_hook.get_original();

View File

@ -269,25 +269,20 @@ namespace re_cscr_memorytree
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_MEMORYTREE_USE_WRAPPERS
quick = false;
#endif
MT_GetSubTreeSize_hook.create(game::MT_GetSubTreeSize.get(), MT_GetSubTreeSize_stub, quick);
MT_DumpTree_hook.create(game::MT_DumpTree.get(), MT_DumpTree_stub, quick);
MT_InitBits_hook.create(game::MT_InitBits_ADDR(), MT_InitBits_stub, quick);
MT_GetScore_hook.create(game::MT_GetScore_ADDR(), MT_GetScore_stub, quick);
MT_AddMemoryNode_hook.create(game::MT_AddMemoryNode.get(), MT_AddMemoryNode_stub, quick);
MT_RemoveMemoryNode_hook.create(game::MT_RemoveMemoryNode.get(), MT_RemoveMemoryNode_stub, quick);
MT_RemoveHeadMemoryNode_hook.create(game::MT_RemoveHeadMemoryNode.get(), MT_RemoveHeadMemoryNode_stub, quick);
MT_Init_hook.create(game::MT_Init_ADDR(), MT_Init_stub, quick);
MT_Error_hook.create(game::MT_Error_ADDR(), MT_Error_stub, quick);
MT_GetSize_hook.create(game::MT_GetSize_ADDR(), MT_GetSize_stub, quick);
MT_AllocIndex_hook.create(game::MT_AllocIndex_ADDR(), MT_AllocIndex_stub, quick);
MT_FreeIndex_hook.create(game::MT_FreeIndex_ADDR(), MT_FreeIndex_stub, quick);
MT_Alloc_hook.create(game::MT_Alloc_ADDR(), MT_Alloc_stub, quick);
MT_Free_hook.create(game::MT_Free.get(), MT_Free_stub, quick);
MT_GetSubTreeSize_hook.create(game::MT_GetSubTreeSize.get(), MT_GetSubTreeSize_stub);
MT_DumpTree_hook.create(game::MT_DumpTree.get(), MT_DumpTree_stub);
MT_InitBits_hook.create(game::MT_InitBits_ADDR(), MT_InitBits_stub);
MT_GetScore_hook.create(game::MT_GetScore_ADDR(), MT_GetScore_stub);
MT_AddMemoryNode_hook.create(game::MT_AddMemoryNode.get(), MT_AddMemoryNode_stub);
MT_RemoveMemoryNode_hook.create(game::MT_RemoveMemoryNode.get(), MT_RemoveMemoryNode_stub);
MT_RemoveHeadMemoryNode_hook.create(game::MT_RemoveHeadMemoryNode.get(), MT_RemoveHeadMemoryNode_stub);
MT_Init_hook.create(game::MT_Init_ADDR(), MT_Init_stub);
MT_Error_hook.create(game::MT_Error_ADDR(), MT_Error_stub);
MT_GetSize_hook.create(game::MT_GetSize_ADDR(), MT_GetSize_stub);
MT_AllocIndex_hook.create(game::MT_AllocIndex_ADDR(), MT_AllocIndex_stub);
MT_FreeIndex_hook.create(game::MT_FreeIndex_ADDR(), MT_FreeIndex_stub);
MT_Alloc_hook.create(game::MT_Alloc_ADDR(), MT_Alloc_stub);
MT_Free_hook.create(game::MT_Free.get(), MT_Free_stub);
//Original hook function addresses
MT_GetSubTreeSize_original = MT_GetSubTreeSize_hook.get_original();

View File

@ -533,34 +533,29 @@ namespace re_cscr_parser
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_PARSER_USE_WRAPPERS
quick = false;
#endif
Scr_InitOpcodeLookup_hook.create(game::Scr_InitOpcodeLookup_ADDR(), Scr_InitOpcodeLookup_stub, quick);
Scr_ShutdownOpcodeLookup_hook.create(game::Scr_ShutdownOpcodeLookup_ADDR(), Scr_ShutdownOpcodeLookup_stub, quick);
AddOpcodePos_hook.create(game::AddOpcodePos_ADDR(), AddOpcodePos_stub, quick);
RemoveOpcodePos_hook.create(game::RemoveOpcodePos_ADDR(), RemoveOpcodePos_stub, quick);
AddThreadStartOpcodePos_hook.create(game::AddThreadStartOpcodePos_ADDR(), AddThreadStartOpcodePos_stub, quick);
Scr_GetSourceBuffer_hook.create(game::Scr_GetSourceBuffer_ADDR(), Scr_GetSourceBuffer_stub, quick);
Scr_GetLineNumInternal_hook.create(game::Scr_GetLineNumInternal_ADDR(), Scr_GetLineNumInternal_stub, quick);
Scr_GetNewSourceBuffer_hook.create(game::Scr_GetNewSourceBuffer_ADDR(), Scr_GetNewSourceBuffer_stub, quick);
Scr_AddSourceBufferInternal_hook.create(game::Scr_AddSourceBufferInternal_ADDR(), Scr_AddSourceBufferInternal_stub, quick);
Scr_ReadFile_FastFile_hook.create(game::Scr_ReadFile_FastFile.get(), Scr_ReadFile_FastFile_stub, quick);
Scr_ReadFile_LoadObj_hook.create(game::Scr_ReadFile_LoadObj.get(), Scr_ReadFile_LoadObj_stub, quick);
Scr_ReadFile_hook.create(game::Scr_ReadFile_ADDR(), Scr_ReadFile_stub, quick);
Scr_AddSourceBuffer_hook.create(game::Scr_AddSourceBuffer_ADDR(), Scr_AddSourceBuffer_stub, quick);
Scr_CopyFormattedLine_hook.create(game::Scr_CopyFormattedLine_ADDR(), Scr_CopyFormattedLine_stub, quick);
Scr_GetLineInfo_hook.create(game::Scr_GetLineInfo_ADDR(), Scr_GetLineInfo_stub, quick);
Scr_PrintSourcePos_hook.create(game::Scr_PrintSourcePos_ADDR(), Scr_PrintSourcePos_stub, quick);
Scr_GetPrevSourcePosOpcodeLookup_hook.create(game::Scr_GetPrevSourcePosOpcodeLookup_ADDR(), Scr_GetPrevSourcePosOpcodeLookup_stub, quick);
Scr_GetTextSourcePos_hook.create(game::Scr_GetTextSourcePos_ADDR(), Scr_GetTextSourcePos_stub, quick);
Scr_PrintPrevCodePos_hook.create(game::Scr_PrintPrevCodePos_ADDR(), Scr_PrintPrevCodePos_stub, quick);
CompileError_hook.create(game::CompileError.get(), CompileError_stub, quick);
CompileError2_hook.create(game::CompileError2_ADDR(), CompileError2_stub, quick);
RuntimeErrorInternal_hook.create(game::RuntimeErrorInternal_ADDR(), RuntimeErrorInternal_stub, quick);
RuntimeError_hook.create(game::RuntimeError_ADDR(), RuntimeError_stub, quick);
Scr_InitOpcodeLookup_hook.create(game::Scr_InitOpcodeLookup_ADDR(), Scr_InitOpcodeLookup_stub);
Scr_ShutdownOpcodeLookup_hook.create(game::Scr_ShutdownOpcodeLookup_ADDR(), Scr_ShutdownOpcodeLookup_stub);
AddOpcodePos_hook.create(game::AddOpcodePos_ADDR(), AddOpcodePos_stub);
RemoveOpcodePos_hook.create(game::RemoveOpcodePos_ADDR(), RemoveOpcodePos_stub);
AddThreadStartOpcodePos_hook.create(game::AddThreadStartOpcodePos_ADDR(), AddThreadStartOpcodePos_stub);
Scr_GetSourceBuffer_hook.create(game::Scr_GetSourceBuffer_ADDR(), Scr_GetSourceBuffer_stub);
Scr_GetLineNumInternal_hook.create(game::Scr_GetLineNumInternal_ADDR(), Scr_GetLineNumInternal_stub);
Scr_GetNewSourceBuffer_hook.create(game::Scr_GetNewSourceBuffer_ADDR(), Scr_GetNewSourceBuffer_stub);
Scr_AddSourceBufferInternal_hook.create(game::Scr_AddSourceBufferInternal_ADDR(), Scr_AddSourceBufferInternal_stub);
Scr_ReadFile_FastFile_hook.create(game::Scr_ReadFile_FastFile.get(), Scr_ReadFile_FastFile_stub);
Scr_ReadFile_LoadObj_hook.create(game::Scr_ReadFile_LoadObj.get(), Scr_ReadFile_LoadObj_stub);
Scr_ReadFile_hook.create(game::Scr_ReadFile_ADDR(), Scr_ReadFile_stub);
Scr_AddSourceBuffer_hook.create(game::Scr_AddSourceBuffer_ADDR(), Scr_AddSourceBuffer_stub);
Scr_CopyFormattedLine_hook.create(game::Scr_CopyFormattedLine_ADDR(), Scr_CopyFormattedLine_stub);
Scr_GetLineInfo_hook.create(game::Scr_GetLineInfo_ADDR(), Scr_GetLineInfo_stub);
Scr_PrintSourcePos_hook.create(game::Scr_PrintSourcePos_ADDR(), Scr_PrintSourcePos_stub);
Scr_GetPrevSourcePosOpcodeLookup_hook.create(game::Scr_GetPrevSourcePosOpcodeLookup_ADDR(), Scr_GetPrevSourcePosOpcodeLookup_stub);
Scr_GetTextSourcePos_hook.create(game::Scr_GetTextSourcePos_ADDR(), Scr_GetTextSourcePos_stub);
Scr_PrintPrevCodePos_hook.create(game::Scr_PrintPrevCodePos_ADDR(), Scr_PrintPrevCodePos_stub);
CompileError_hook.create(game::CompileError.get(), CompileError_stub);
CompileError2_hook.create(game::CompileError2_ADDR(), CompileError2_stub);
RuntimeErrorInternal_hook.create(game::RuntimeErrorInternal_ADDR(), RuntimeErrorInternal_stub);
RuntimeError_hook.create(game::RuntimeError_ADDR(), RuntimeError_stub);
//Original hook function addresses
Scr_InitOpcodeLookup_original = Scr_InitOpcodeLookup_hook.get_original();

View File

@ -160,24 +160,19 @@ namespace re_cscr_parsetree
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_PARSETREE_USE_WRAPPERS
quick = false;
#endif
Scr_InitAllocNode_hook.create(game::Scr_InitAllocNode.get(), Scr_InitAllocNode_stub, quick);
node0_hook.create(game::node0.get(), node0_stub, quick);
node1_hook.create(game::node1.get(), node1_stub, quick);
node2_hook.create(game::node2.get(), node2_stub, quick);
node3_hook.create(game::node3.get(), node3_stub, quick);
node4_hook.create(game::node4.get(), node4_stub, quick);
node5_hook.create(game::node5.get(), node5_stub, quick);
node6_hook.create(game::node6.get(), node6_stub, quick);
node7_hook.create(game::node7.get(), node7_stub, quick);
node8_hook.create(game::node8.get(), node8_stub, quick);
linked_list_end_hook.create(game::linked_list_end.get(), linked_list_end_stub, quick);
prepend_node_hook.create(game::prepend_node.get(), prepend_node_stub, quick);
append_node_hook.create(game::append_node.get(), append_node_stub, quick);
Scr_InitAllocNode_hook.create(game::Scr_InitAllocNode.get(), Scr_InitAllocNode_stub);
node0_hook.create(game::node0.get(), node0_stub);
node1_hook.create(game::node1.get(), node1_stub);
node2_hook.create(game::node2.get(), node2_stub);
node3_hook.create(game::node3.get(), node3_stub);
node4_hook.create(game::node4.get(), node4_stub);
node5_hook.create(game::node5.get(), node5_stub);
node6_hook.create(game::node6.get(), node6_stub);
node7_hook.create(game::node7.get(), node7_stub);
node8_hook.create(game::node8.get(), node8_stub);
linked_list_end_hook.create(game::linked_list_end.get(), linked_list_end_stub);
prepend_node_hook.create(game::prepend_node.get(), prepend_node_stub);
append_node_hook.create(game::append_node.get(), append_node_stub);
//Original hook function addresses
Scr_InitAllocNode_original = Scr_InitAllocNode_hook.get_original();

View File

@ -64,13 +64,8 @@ namespace re_cscr_readwrite
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_READWRITE_USE_WRAPPERS
quick = false;
#endif
FindVariableIndexInternal2_hook.create(game::FindVariableIndexInternal2_ADDR(), FindVariableIndexInternal2_stub, quick);
FindLastSibling_hook.create(game::FindLastSibling_ADDR(), FindLastSibling_stub, quick);
FindVariableIndexInternal2_hook.create(game::FindVariableIndexInternal2_ADDR(), FindVariableIndexInternal2_stub);
FindLastSibling_hook.create(game::FindLastSibling_ADDR(), FindLastSibling_stub);
//Original hook function addresses
FindVariableIndexInternal2_original = FindVariableIndexInternal2_hook.get_original();

View File

@ -585,39 +585,34 @@ namespace re_cscr_stringlist
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_STRINGLIST_USE_WRAPPERS
quick = false;
#endif
SL_ConvertToString_hook.create(game::SL_ConvertToString_ADDR(), SL_ConvertToString_stub, quick);
SL_GetStringLen_hook.create(game::SL_GetStringLen_ADDR(), SL_GetStringLen_stub, quick);
GetHashCode_hook.create(game::GetHashCode_ADDR(), GetHashCode_stub, quick);
SL_Init_hook.create(game::SL_Init_ADDR(), SL_Init_stub, quick);
SL_FindStringOfSize_hook.create(game::SL_FindStringOfSize_ADDR(), SL_FindStringOfSize_stub, quick);
SL_FindString_hook.create(game::SL_FindString_ADDR(), SL_FindString_stub, quick);
SL_FindLowercaseString_hook.create(game::SL_FindLowercaseString.get(), SL_FindLowercaseString_stub, quick);
SL_AddUserInternal_hook.create(game::SL_AddUserInternal_ADDR(), SL_AddUserInternal_stub, quick);
Mark_ScriptStringCustom_hook.create(game::Mark_ScriptStringCustom_ADDR(), Mark_ScriptStringCustom_stub, quick);
SL_GetStringOfSize_hook.create(game::SL_GetStringOfSize.get(), SL_GetStringOfSize_stub, quick);
SL_GetString__hook.create(game::SL_GetString__ADDR(), SL_GetString__stub, quick);
SL_GetString__0_hook.create(game::SL_GetString__0_ADDR(), SL_GetString__0_stub, quick);
SL_GetLowercaseStringOfLen_hook.create(game::SL_GetLowercaseStringOfLen.get(), SL_GetLowercaseStringOfLen_stub, quick);
SL_GetLowercaseString_hook.create(game::SL_GetLowercaseString_ADDR(), SL_GetLowercaseString_stub, quick);
SL_ConvertToLowercase_hook.create(game::SL_ConvertToLowercase.get(), SL_ConvertToLowercase_stub, quick);
SL_TransferRefToUser_hook.create(game::SL_TransferRefToUser_ADDR(), SL_TransferRefToUser_stub, quick);
SL_FreeString_hook.create(game::SL_FreeString.get(), SL_FreeString_stub, quick);
SL_RemoveRefToString_hook.create(game::SL_RemoveRefToString_ADDR(), SL_RemoveRefToString_stub, quick);
Scr_SetString_hook.create(game::Scr_SetString_ADDR(), Scr_SetString_stub, quick);
Scr_SetStringFromCharString_hook.create(game::Scr_SetStringFromCharString_ADDR(), Scr_SetStringFromCharString_stub, quick);
GScr_AllocString_hook.create(game::GScr_AllocString_ADDR(), GScr_AllocString_stub, quick);
SL_GetStringForFloat_hook.create(game::SL_GetStringForFloat_ADDR(), SL_GetStringForFloat_stub, quick);
SL_GetStringForInt_hook.create(game::SL_GetStringForInt_ADDR(), SL_GetStringForInt_stub, quick);
SL_GetStringForVector_hook.create(game::SL_GetStringForVector_ADDR(), SL_GetStringForVector_stub, quick);
SL_ShutdownSystem_hook.create(game::SL_ShutdownSystem_ADDR(), SL_ShutdownSystem_stub, quick);
SL_TransferSystem_hook.create(game::SL_TransferSystem.get(), SL_TransferSystem_stub, quick);
SL_CreateCanonicalFilename_hook.create(game::SL_CreateCanonicalFilename_ADDR(), SL_CreateCanonicalFilename_stub, quick);
Scr_CreateCanonicalFilename_hook.create(game::Scr_CreateCanonicalFilename.get(), Scr_CreateCanonicalFilename_stub, quick);
SL_ConvertToString_hook.create(game::SL_ConvertToString_ADDR(), SL_ConvertToString_stub);
SL_GetStringLen_hook.create(game::SL_GetStringLen_ADDR(), SL_GetStringLen_stub);
GetHashCode_hook.create(game::GetHashCode_ADDR(), GetHashCode_stub);
SL_Init_hook.create(game::SL_Init_ADDR(), SL_Init_stub);
SL_FindStringOfSize_hook.create(game::SL_FindStringOfSize_ADDR(), SL_FindStringOfSize_stub);
SL_FindString_hook.create(game::SL_FindString_ADDR(), SL_FindString_stub);
SL_FindLowercaseString_hook.create(game::SL_FindLowercaseString.get(), SL_FindLowercaseString_stub);
SL_AddUserInternal_hook.create(game::SL_AddUserInternal_ADDR(), SL_AddUserInternal_stub);
Mark_ScriptStringCustom_hook.create(game::Mark_ScriptStringCustom_ADDR(), Mark_ScriptStringCustom_stub);
SL_GetStringOfSize_hook.create(game::SL_GetStringOfSize.get(), SL_GetStringOfSize_stub);
SL_GetString__hook.create(game::SL_GetString__ADDR(), SL_GetString__stub);
SL_GetString__0_hook.create(game::SL_GetString__0_ADDR(), SL_GetString__0_stub);
SL_GetLowercaseStringOfLen_hook.create(game::SL_GetLowercaseStringOfLen.get(), SL_GetLowercaseStringOfLen_stub);
SL_GetLowercaseString_hook.create(game::SL_GetLowercaseString_ADDR(), SL_GetLowercaseString_stub);
SL_ConvertToLowercase_hook.create(game::SL_ConvertToLowercase.get(), SL_ConvertToLowercase_stub);
SL_TransferRefToUser_hook.create(game::SL_TransferRefToUser_ADDR(), SL_TransferRefToUser_stub);
SL_FreeString_hook.create(game::SL_FreeString.get(), SL_FreeString_stub);
SL_RemoveRefToString_hook.create(game::SL_RemoveRefToString_ADDR(), SL_RemoveRefToString_stub);
Scr_SetString_hook.create(game::Scr_SetString_ADDR(), Scr_SetString_stub);
Scr_SetStringFromCharString_hook.create(game::Scr_SetStringFromCharString_ADDR(), Scr_SetStringFromCharString_stub);
GScr_AllocString_hook.create(game::GScr_AllocString_ADDR(), GScr_AllocString_stub);
SL_GetStringForFloat_hook.create(game::SL_GetStringForFloat_ADDR(), SL_GetStringForFloat_stub);
SL_GetStringForInt_hook.create(game::SL_GetStringForInt_ADDR(), SL_GetStringForInt_stub);
SL_GetStringForVector_hook.create(game::SL_GetStringForVector_ADDR(), SL_GetStringForVector_stub);
SL_ShutdownSystem_hook.create(game::SL_ShutdownSystem_ADDR(), SL_ShutdownSystem_stub);
SL_TransferSystem_hook.create(game::SL_TransferSystem.get(), SL_TransferSystem_stub);
SL_CreateCanonicalFilename_hook.create(game::SL_CreateCanonicalFilename_ADDR(), SL_CreateCanonicalFilename_stub);
Scr_CreateCanonicalFilename_hook.create(game::Scr_CreateCanonicalFilename.get(), Scr_CreateCanonicalFilename_stub);
//Original hook function addresses
SL_ConvertToString_original = SL_ConvertToString_hook.get_original();

View File

@ -2288,116 +2288,111 @@ namespace re_cscr_variable
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_VARIABLE_USE_WRAPPERS
quick = false;
#endif
ThreadInfoCompare_hook.create(game::ThreadInfoCompare.get(), ThreadInfoCompare_stub, quick);
Scr_DumpScriptThreads_hook.create(game::Scr_DumpScriptThreads.get(), Scr_DumpScriptThreads_stub, quick);
Scr_InitVariableRange_hook.create(game::Scr_InitVariableRange_ADDR(), Scr_InitVariableRange_stub, quick);
Scr_InitClassMap_hook.create(game::Scr_InitClassMap_ADDR(), Scr_InitClassMap_stub, quick);
GetNewVariableIndexInternal3_hook.create(game::GetNewVariableIndexInternal3.get(), GetNewVariableIndexInternal3_stub, quick);
GetNewVariableIndexInternal2_hook.create(game::GetNewVariableIndexInternal2_ADDR(), GetNewVariableIndexInternal2_stub, quick);
GetNewVariableIndexReverseInternal2_hook.create(game::GetNewVariableIndexReverseInternal2_ADDR(), GetNewVariableIndexReverseInternal2_stub, quick);
MakeVariableExternal_hook.create(game::MakeVariableExternal_ADDR(), MakeVariableExternal_stub, quick);
FreeChildValue_hook.create(game::FreeChildValue_ADDR(), FreeChildValue_stub, quick);
ClearObjectInternal_hook.create(game::ClearObjectInternal.get(), ClearObjectInternal_stub, quick);
ClearObject_hook.create(game::ClearObject_ADDR(), ClearObject_stub, quick);
Scr_StopThread_hook.create(game::Scr_StopThread_ADDR(), Scr_StopThread_stub, quick);
GetSafeParentLocalId_hook.create(game::GetSafeParentLocalId_ADDR(), GetSafeParentLocalId_stub, quick);
GetStartLocalId_hook.create(game::GetStartLocalId_ADDR(), GetStartLocalId_stub, quick);
Scr_KillThread_hook.create(game::Scr_KillThread_ADDR(), Scr_KillThread_stub, quick);
AllocVariable_hook.create(game::AllocVariable_ADDR(), AllocVariable_stub, quick);
FreeVariable_hook.create(game::FreeVariable_ADDR(), FreeVariable_stub, quick);
AllocValue_hook.create(game::AllocValue_ADDR(), AllocValue_stub, quick);
AllocEntity_hook.create(game::AllocEntity_ADDR(), AllocEntity_stub, quick);
Scr_AllocArray_hook.create(game::Scr_AllocArray_ADDR(), Scr_AllocArray_stub, quick);
AllocChildThread_hook.create(game::AllocChildThread_ADDR(), AllocChildThread_stub, quick);
FreeValue_hook.create(game::FreeValue_ADDR(), FreeValue_stub, quick);
RemoveRefToObject_hook.create(game::RemoveRefToObject_ADDR(), RemoveRefToObject_stub, quick);
Scr_AllocVector_hook.create(game::Scr_AllocVector_ADDR(), Scr_AllocVector_stub, quick);
RemoveRefToVector_hook.create(game::RemoveRefToVector_ADDR(), RemoveRefToVector_stub, quick);
AddRefToValue_hook.create(game::AddRefToValue_ADDR(), AddRefToValue_stub, quick);
RemoveRefToValueInternal_hook.create(game::RemoveRefToValueInternal.get(), RemoveRefToValueInternal_stub, quick);
FindArrayVariable_hook.create(game::FindArrayVariable_ADDR(), FindArrayVariable_stub, quick);
FindVariable_hook.create(game::FindVariable_ADDR(), FindVariable_stub, quick);
GetArrayVariableIndex_hook.create(game::GetArrayVariableIndex_ADDR(), GetArrayVariableIndex_stub, quick);
Scr_GetVariableFieldIndex_hook.create(game::Scr_GetVariableFieldIndex_ADDR(), Scr_GetVariableFieldIndex_stub, quick);
Scr_FindVariableField_hook.create(game::Scr_FindVariableField_ADDR(), Scr_FindVariableField_stub, quick);
ClearVariableField_hook.create(game::ClearVariableField_ADDR(), ClearVariableField_stub, quick);
GetVariable_hook.create(game::GetVariable_ADDR(), GetVariable_stub, quick);
GetNewVariable_hook.create(game::GetNewVariable_ADDR(), GetNewVariable_stub, quick);
GetObjectVariable_hook.create(game::GetObjectVariable_ADDR(), GetObjectVariable_stub, quick);
GetNewObjectVariable_hook.create(game::GetNewObjectVariable_ADDR(), GetNewObjectVariable_stub, quick);
RemoveVariable_hook.create(game::RemoveVariable_ADDR(), RemoveVariable_stub, quick);
RemoveNextVariable_hook.create(game::RemoveNextVariable_ADDR(), RemoveNextVariable_stub, quick);
SafeRemoveVariable_hook.create(game::SafeRemoveVariable_ADDR(), SafeRemoveVariable_stub, quick);
CopyArray_hook.create(game::CopyArray.get(), CopyArray_stub, quick);
SetVariableValue_hook.create(game::SetVariableValue_ADDR(), SetVariableValue_stub, quick);
SetVariableEntityFieldValue_hook.create(game::SetVariableEntityFieldValue.get(), SetVariableEntityFieldValue_stub, quick);
Scr_EvalVariable_hook.create(game::Scr_EvalVariable_ADDR(), Scr_EvalVariable_stub, quick);
Scr_EvalVariableObject_hook.create(game::Scr_EvalVariableObject_ADDR(), Scr_EvalVariableObject_stub, quick);
Scr_EvalVariableEntityField_hook.create(game::Scr_EvalVariableEntityField_ADDR(), Scr_EvalVariableEntityField_stub, quick);
Scr_EvalVariableField_hook.create(game::Scr_EvalVariableField_ADDR(), Scr_EvalVariableField_stub, quick);
Scr_EvalSizeValue_hook.create(game::Scr_EvalSizeValue_ADDR(), Scr_EvalSizeValue_stub, quick);
GetObject_hook.create(game::GetObject_ADDR(), GetObject_stub, quick);
GetArray_hook.create(game::GetArray_ADDR(), GetArray_stub, quick);
Scr_EvalBoolComplement_hook.create(game::Scr_EvalBoolComplement_ADDR(), Scr_EvalBoolComplement_stub, quick);
Scr_CastBool_hook.create(game::Scr_CastBool_ADDR(), Scr_CastBool_stub, quick);
Scr_CastString_hook.create(game::Scr_CastString_ADDR(), Scr_CastString_stub, quick);
Scr_CastDebugString_hook.create(game::Scr_CastDebugString_ADDR(), Scr_CastDebugString_stub, quick);
Scr_ClearVector_hook.create(game::Scr_ClearVector.get(), Scr_ClearVector_stub, quick);
Scr_CastVector_hook.create(game::Scr_CastVector_ADDR(), Scr_CastVector_stub, quick);
Scr_EvalFieldObject_hook.create(game::Scr_EvalFieldObject_ADDR(), Scr_EvalFieldObject_stub, quick);
Scr_UnmatchingTypesError_hook.create(game::Scr_UnmatchingTypesError_ADDR(), Scr_UnmatchingTypesError_stub, quick);
Scr_CastWeakerPair_hook.create(game::Scr_CastWeakerPair_ADDR(), Scr_CastWeakerPair_stub, quick);
Scr_CastWeakerStringPair_hook.create(game::Scr_CastWeakerStringPair_ADDR(), Scr_CastWeakerStringPair_stub, quick);
Scr_EvalOr_hook.create(game::Scr_EvalOr_ADDR(), Scr_EvalOr_stub, quick);
Scr_EvalExOr_hook.create(game::Scr_EvalExOr_ADDR(), Scr_EvalExOr_stub, quick);
Scr_EvalAnd_hook.create(game::Scr_EvalAnd_ADDR(), Scr_EvalAnd_stub, quick);
Scr_EvalEquality_hook.create(game::Scr_EvalEquality_ADDR(), Scr_EvalEquality_stub, quick);
Scr_EvalLess_hook.create(game::Scr_EvalLess_ADDR(), Scr_EvalLess_stub, quick);
Scr_EvalGreaterEqual_hook.create(game::Scr_EvalGreaterEqual_ADDR(), Scr_EvalGreaterEqual_stub, quick);
Scr_EvalGreater_hook.create(game::Scr_EvalGreater_ADDR(), Scr_EvalGreater_stub, quick);
Scr_EvalLessEqual_hook.create(game::Scr_EvalLessEqual_ADDR(), Scr_EvalLessEqual_stub, quick);
Scr_EvalShiftLeft_hook.create(game::Scr_EvalShiftLeft_ADDR(), Scr_EvalShiftLeft_stub, quick);
Scr_EvalShiftRight_hook.create(game::Scr_EvalShiftRight_ADDR(), Scr_EvalShiftRight_stub, quick);
Scr_EvalPlus_hook.create(game::Scr_EvalPlus_ADDR(), Scr_EvalPlus_stub, quick);
Scr_EvalMinus_hook.create(game::Scr_EvalMinus_ADDR(), Scr_EvalMinus_stub, quick);
Scr_EvalMultiply_hook.create(game::Scr_EvalMultiply_ADDR(), Scr_EvalMultiply_stub, quick);
Scr_EvalDivide_hook.create(game::Scr_EvalDivide_ADDR(), Scr_EvalDivide_stub, quick);
Scr_EvalMod_hook.create(game::Scr_EvalMod_ADDR(), Scr_EvalMod_stub, quick);
Scr_EvalBinaryOperator_hook.create(game::Scr_EvalBinaryOperator_ADDR(), Scr_EvalBinaryOperator_stub, quick);
Scr_FreeEntityNum_hook.create(game::Scr_FreeEntityNum_ADDR(), Scr_FreeEntityNum_stub, quick);
Scr_FreeEntityList_hook.create(game::Scr_FreeEntityList.get(), Scr_FreeEntityList_stub, quick);
Scr_FreeObjects_hook.create(game::Scr_FreeObjects.get(), Scr_FreeObjects_stub, quick);
Scr_SetClassMap_hook.create(game::Scr_SetClassMap_ADDR(), Scr_SetClassMap_stub, quick);
Scr_RemoveClassMap_hook.create(game::Scr_RemoveClassMap_ADDR(), Scr_RemoveClassMap_stub, quick);
Scr_AddClassField_hook.create(game::Scr_AddClassField_ADDR(), Scr_AddClassField_stub, quick);
Scr_GetOffset_hook.create(game::Scr_GetOffset_ADDR(), Scr_GetOffset_stub, quick);
FindEntityId_hook.create(game::FindEntityId_ADDR(), FindEntityId_stub, quick);
Scr_GetEntityId_hook.create(game::Scr_GetEntityId_ADDR(), Scr_GetEntityId_stub, quick);
Scr_FindArrayIndex_hook.create(game::Scr_FindArrayIndex_ADDR(), Scr_FindArrayIndex_stub, quick);
Scr_EvalArray_hook.create(game::Scr_EvalArray_ADDR(), Scr_EvalArray_stub, quick);
Scr_EvalArrayRef_hook.create(game::Scr_EvalArrayRef_ADDR(), Scr_EvalArrayRef_stub, quick);
ClearArray_hook.create(game::ClearArray_ADDR(), ClearArray_stub, quick);
SetEmptyArray_hook.create(game::SetEmptyArray_ADDR(), SetEmptyArray_stub, quick);
Scr_AddArrayKeys_hook.create(game::Scr_AddArrayKeys.get(), Scr_AddArrayKeys_stub, quick);
Scr_GetEntityIdRef_hook.create(game::Scr_GetEntityIdRef_ADDR(), Scr_GetEntityIdRef_stub, quick);
CopyEntity_hook.create(game::CopyEntity_ADDR(), CopyEntity_stub, quick);
Scr_GetEndonUsage_hook.create(game::Scr_GetEndonUsage_ADDR(), Scr_GetEndonUsage_stub, quick);
Scr_GetObjectUsage_hook.create(game::Scr_GetObjectUsage.get(), Scr_GetObjectUsage_stub, quick);
Scr_GetThreadUsage_hook.create(game::Scr_GetThreadUsage_ADDR(), Scr_GetThreadUsage_stub, quick);
Scr_FindField_hook.create(game::Scr_FindField_ADDR(), Scr_FindField_stub, quick);
Scr_GetSourceFile_LoadObj_hook.create(game::Scr_GetSourceFile_LoadObj.get(), Scr_GetSourceFile_LoadObj_stub, quick);
Scr_GetSourceFile_FastFile_hook.create(game::Scr_GetSourceFile_FastFile.get(), Scr_GetSourceFile_FastFile_stub, quick);
Scr_AddFieldsForFile_hook.create(game::Scr_AddFieldsForFile.get(), Scr_AddFieldsForFile_stub, quick);
Scr_AddFields_LoadObj_hook.create(game::Scr_AddFields_LoadObj.get(), Scr_AddFields_LoadObj_stub, quick);
Scr_AddFields_FastFile_hook.create(game::Scr_AddFields_FastFile.get(), Scr_AddFields_FastFile_stub, quick);
Scr_MakeValuePrimitive_hook.create(game::Scr_MakeValuePrimitive.get(), Scr_MakeValuePrimitive_stub, quick);
Scr_FreeGameVariable_hook.create(game::Scr_FreeGameVariable_ADDR(), Scr_FreeGameVariable_stub, quick);
Scr_SLHasLowercaseString_hook.create(game::Scr_SLHasLowercaseString_ADDR(), Scr_SLHasLowercaseString_stub, quick);
ThreadInfoCompare_hook.create(game::ThreadInfoCompare.get(), ThreadInfoCompare_stub);
Scr_DumpScriptThreads_hook.create(game::Scr_DumpScriptThreads.get(), Scr_DumpScriptThreads_stub);
Scr_InitVariableRange_hook.create(game::Scr_InitVariableRange_ADDR(), Scr_InitVariableRange_stub);
Scr_InitClassMap_hook.create(game::Scr_InitClassMap_ADDR(), Scr_InitClassMap_stub);
GetNewVariableIndexInternal3_hook.create(game::GetNewVariableIndexInternal3.get(), GetNewVariableIndexInternal3_stub);
GetNewVariableIndexInternal2_hook.create(game::GetNewVariableIndexInternal2_ADDR(), GetNewVariableIndexInternal2_stub);
GetNewVariableIndexReverseInternal2_hook.create(game::GetNewVariableIndexReverseInternal2_ADDR(), GetNewVariableIndexReverseInternal2_stub);
MakeVariableExternal_hook.create(game::MakeVariableExternal_ADDR(), MakeVariableExternal_stub);
FreeChildValue_hook.create(game::FreeChildValue_ADDR(), FreeChildValue_stub);
ClearObjectInternal_hook.create(game::ClearObjectInternal.get(), ClearObjectInternal_stub);
ClearObject_hook.create(game::ClearObject_ADDR(), ClearObject_stub);
Scr_StopThread_hook.create(game::Scr_StopThread_ADDR(), Scr_StopThread_stub);
GetSafeParentLocalId_hook.create(game::GetSafeParentLocalId_ADDR(), GetSafeParentLocalId_stub);
GetStartLocalId_hook.create(game::GetStartLocalId_ADDR(), GetStartLocalId_stub);
Scr_KillThread_hook.create(game::Scr_KillThread_ADDR(), Scr_KillThread_stub);
AllocVariable_hook.create(game::AllocVariable_ADDR(), AllocVariable_stub);
FreeVariable_hook.create(game::FreeVariable_ADDR(), FreeVariable_stub);
AllocValue_hook.create(game::AllocValue_ADDR(), AllocValue_stub);
AllocEntity_hook.create(game::AllocEntity_ADDR(), AllocEntity_stub);
Scr_AllocArray_hook.create(game::Scr_AllocArray_ADDR(), Scr_AllocArray_stub);
AllocChildThread_hook.create(game::AllocChildThread_ADDR(), AllocChildThread_stub);
FreeValue_hook.create(game::FreeValue_ADDR(), FreeValue_stub);
RemoveRefToObject_hook.create(game::RemoveRefToObject_ADDR(), RemoveRefToObject_stub);
Scr_AllocVector_hook.create(game::Scr_AllocVector_ADDR(), Scr_AllocVector_stub);
RemoveRefToVector_hook.create(game::RemoveRefToVector_ADDR(), RemoveRefToVector_stub);
AddRefToValue_hook.create(game::AddRefToValue_ADDR(), AddRefToValue_stub);
RemoveRefToValueInternal_hook.create(game::RemoveRefToValueInternal.get(), RemoveRefToValueInternal_stub);
FindArrayVariable_hook.create(game::FindArrayVariable_ADDR(), FindArrayVariable_stub);
FindVariable_hook.create(game::FindVariable_ADDR(), FindVariable_stub);
GetArrayVariableIndex_hook.create(game::GetArrayVariableIndex_ADDR(), GetArrayVariableIndex_stub);
Scr_GetVariableFieldIndex_hook.create(game::Scr_GetVariableFieldIndex_ADDR(), Scr_GetVariableFieldIndex_stub);
Scr_FindVariableField_hook.create(game::Scr_FindVariableField_ADDR(), Scr_FindVariableField_stub);
ClearVariableField_hook.create(game::ClearVariableField_ADDR(), ClearVariableField_stub);
GetVariable_hook.create(game::GetVariable_ADDR(), GetVariable_stub);
GetNewVariable_hook.create(game::GetNewVariable_ADDR(), GetNewVariable_stub);
GetObjectVariable_hook.create(game::GetObjectVariable_ADDR(), GetObjectVariable_stub);
GetNewObjectVariable_hook.create(game::GetNewObjectVariable_ADDR(), GetNewObjectVariable_stub);
RemoveVariable_hook.create(game::RemoveVariable_ADDR(), RemoveVariable_stub);
RemoveNextVariable_hook.create(game::RemoveNextVariable_ADDR(), RemoveNextVariable_stub);
SafeRemoveVariable_hook.create(game::SafeRemoveVariable_ADDR(), SafeRemoveVariable_stub);
CopyArray_hook.create(game::CopyArray.get(), CopyArray_stub);
SetVariableValue_hook.create(game::SetVariableValue_ADDR(), SetVariableValue_stub);
SetVariableEntityFieldValue_hook.create(game::SetVariableEntityFieldValue.get(), SetVariableEntityFieldValue_stub);
Scr_EvalVariable_hook.create(game::Scr_EvalVariable_ADDR(), Scr_EvalVariable_stub);
Scr_EvalVariableObject_hook.create(game::Scr_EvalVariableObject_ADDR(), Scr_EvalVariableObject_stub);
Scr_EvalVariableEntityField_hook.create(game::Scr_EvalVariableEntityField_ADDR(), Scr_EvalVariableEntityField_stub);
Scr_EvalVariableField_hook.create(game::Scr_EvalVariableField_ADDR(), Scr_EvalVariableField_stub);
Scr_EvalSizeValue_hook.create(game::Scr_EvalSizeValue_ADDR(), Scr_EvalSizeValue_stub);
GetObject_hook.create(game::GetObject_ADDR(), GetObject_stub);
GetArray_hook.create(game::GetArray_ADDR(), GetArray_stub);
Scr_EvalBoolComplement_hook.create(game::Scr_EvalBoolComplement_ADDR(), Scr_EvalBoolComplement_stub);
Scr_CastBool_hook.create(game::Scr_CastBool_ADDR(), Scr_CastBool_stub);
Scr_CastString_hook.create(game::Scr_CastString_ADDR(), Scr_CastString_stub);
Scr_CastDebugString_hook.create(game::Scr_CastDebugString_ADDR(), Scr_CastDebugString_stub);
Scr_ClearVector_hook.create(game::Scr_ClearVector.get(), Scr_ClearVector_stub);
Scr_CastVector_hook.create(game::Scr_CastVector_ADDR(), Scr_CastVector_stub);
Scr_EvalFieldObject_hook.create(game::Scr_EvalFieldObject_ADDR(), Scr_EvalFieldObject_stub);
Scr_UnmatchingTypesError_hook.create(game::Scr_UnmatchingTypesError_ADDR(), Scr_UnmatchingTypesError_stub);
Scr_CastWeakerPair_hook.create(game::Scr_CastWeakerPair_ADDR(), Scr_CastWeakerPair_stub);
Scr_CastWeakerStringPair_hook.create(game::Scr_CastWeakerStringPair_ADDR(), Scr_CastWeakerStringPair_stub);
Scr_EvalOr_hook.create(game::Scr_EvalOr_ADDR(), Scr_EvalOr_stub);
Scr_EvalExOr_hook.create(game::Scr_EvalExOr_ADDR(), Scr_EvalExOr_stub);
Scr_EvalAnd_hook.create(game::Scr_EvalAnd_ADDR(), Scr_EvalAnd_stub);
Scr_EvalEquality_hook.create(game::Scr_EvalEquality_ADDR(), Scr_EvalEquality_stub);
Scr_EvalLess_hook.create(game::Scr_EvalLess_ADDR(), Scr_EvalLess_stub);
Scr_EvalGreaterEqual_hook.create(game::Scr_EvalGreaterEqual_ADDR(), Scr_EvalGreaterEqual_stub);
Scr_EvalGreater_hook.create(game::Scr_EvalGreater_ADDR(), Scr_EvalGreater_stub);
Scr_EvalLessEqual_hook.create(game::Scr_EvalLessEqual_ADDR(), Scr_EvalLessEqual_stub);
Scr_EvalShiftLeft_hook.create(game::Scr_EvalShiftLeft_ADDR(), Scr_EvalShiftLeft_stub);
Scr_EvalShiftRight_hook.create(game::Scr_EvalShiftRight_ADDR(), Scr_EvalShiftRight_stub);
Scr_EvalPlus_hook.create(game::Scr_EvalPlus_ADDR(), Scr_EvalPlus_stub);
Scr_EvalMinus_hook.create(game::Scr_EvalMinus_ADDR(), Scr_EvalMinus_stub);
Scr_EvalMultiply_hook.create(game::Scr_EvalMultiply_ADDR(), Scr_EvalMultiply_stub);
Scr_EvalDivide_hook.create(game::Scr_EvalDivide_ADDR(), Scr_EvalDivide_stub);
Scr_EvalMod_hook.create(game::Scr_EvalMod_ADDR(), Scr_EvalMod_stub);
Scr_EvalBinaryOperator_hook.create(game::Scr_EvalBinaryOperator_ADDR(), Scr_EvalBinaryOperator_stub);
Scr_FreeEntityNum_hook.create(game::Scr_FreeEntityNum_ADDR(), Scr_FreeEntityNum_stub);
Scr_FreeEntityList_hook.create(game::Scr_FreeEntityList.get(), Scr_FreeEntityList_stub);
Scr_FreeObjects_hook.create(game::Scr_FreeObjects.get(), Scr_FreeObjects_stub);
Scr_SetClassMap_hook.create(game::Scr_SetClassMap_ADDR(), Scr_SetClassMap_stub);
Scr_RemoveClassMap_hook.create(game::Scr_RemoveClassMap_ADDR(), Scr_RemoveClassMap_stub);
Scr_AddClassField_hook.create(game::Scr_AddClassField_ADDR(), Scr_AddClassField_stub);
Scr_GetOffset_hook.create(game::Scr_GetOffset_ADDR(), Scr_GetOffset_stub);
FindEntityId_hook.create(game::FindEntityId_ADDR(), FindEntityId_stub);
Scr_GetEntityId_hook.create(game::Scr_GetEntityId_ADDR(), Scr_GetEntityId_stub);
Scr_FindArrayIndex_hook.create(game::Scr_FindArrayIndex_ADDR(), Scr_FindArrayIndex_stub);
Scr_EvalArray_hook.create(game::Scr_EvalArray_ADDR(), Scr_EvalArray_stub);
Scr_EvalArrayRef_hook.create(game::Scr_EvalArrayRef_ADDR(), Scr_EvalArrayRef_stub);
ClearArray_hook.create(game::ClearArray_ADDR(), ClearArray_stub);
SetEmptyArray_hook.create(game::SetEmptyArray_ADDR(), SetEmptyArray_stub);
Scr_AddArrayKeys_hook.create(game::Scr_AddArrayKeys.get(), Scr_AddArrayKeys_stub);
Scr_GetEntityIdRef_hook.create(game::Scr_GetEntityIdRef_ADDR(), Scr_GetEntityIdRef_stub);
CopyEntity_hook.create(game::CopyEntity_ADDR(), CopyEntity_stub);
Scr_GetEndonUsage_hook.create(game::Scr_GetEndonUsage_ADDR(), Scr_GetEndonUsage_stub);
Scr_GetObjectUsage_hook.create(game::Scr_GetObjectUsage.get(), Scr_GetObjectUsage_stub);
Scr_GetThreadUsage_hook.create(game::Scr_GetThreadUsage_ADDR(), Scr_GetThreadUsage_stub);
Scr_FindField_hook.create(game::Scr_FindField_ADDR(), Scr_FindField_stub);
Scr_GetSourceFile_LoadObj_hook.create(game::Scr_GetSourceFile_LoadObj.get(), Scr_GetSourceFile_LoadObj_stub);
Scr_GetSourceFile_FastFile_hook.create(game::Scr_GetSourceFile_FastFile.get(), Scr_GetSourceFile_FastFile_stub);
Scr_AddFieldsForFile_hook.create(game::Scr_AddFieldsForFile.get(), Scr_AddFieldsForFile_stub);
Scr_AddFields_LoadObj_hook.create(game::Scr_AddFields_LoadObj.get(), Scr_AddFields_LoadObj_stub);
Scr_AddFields_FastFile_hook.create(game::Scr_AddFields_FastFile.get(), Scr_AddFields_FastFile_stub);
Scr_MakeValuePrimitive_hook.create(game::Scr_MakeValuePrimitive.get(), Scr_MakeValuePrimitive_stub);
Scr_FreeGameVariable_hook.create(game::Scr_FreeGameVariable_ADDR(), Scr_FreeGameVariable_stub);
Scr_SLHasLowercaseString_hook.create(game::Scr_SLHasLowercaseString_ADDR(), Scr_SLHasLowercaseString_stub);
//Original hook function addresses
ThreadInfoCompare_original = ThreadInfoCompare_hook.get_original();

View File

@ -1524,83 +1524,78 @@ namespace re_cscr_vm
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_VM_USE_WRAPPERS
quick = false;
#endif
Scr_VM_Init_hook.create(game::Scr_VM_Init.get(), Scr_VM_Init_stub, quick);
Scr_Init_hook.create(game::Scr_Init_ADDR(), Scr_Init_stub, quick);
Scr_Shutdown_hook.create(game::Scr_Shutdown_ADDR(), Scr_Shutdown_stub, quick);
Scr_ErrorInternal_hook.create(game::Scr_ErrorInternal_ADDR(), Scr_ErrorInternal_stub, quick);
Scr_ClearOutParams_hook.create(game::Scr_ClearOutParams_ADDR(), Scr_ClearOutParams_stub, quick);
GetDummyObject_hook.create(game::GetDummyObject_ADDR(), GetDummyObject_stub, quick);
GetDummyFieldValue_hook.create(game::GetDummyFieldValue_ADDR(), GetDummyFieldValue_stub, quick);
VM_ExecuteInternal_hook.create(game::VM_ExecuteInternal.get(), VM_ExecuteInternal_stub, quick);
VM_CancelNotifyInternal_hook.create(game::VM_CancelNotifyInternal_ADDR(), VM_CancelNotifyInternal_stub, quick);
VM_CancelNotify_hook.create(game::VM_CancelNotify_ADDR(), VM_CancelNotify_stub, quick);
VM_ArchiveStack_hook.create(game::VM_ArchiveStack_ADDR(), VM_ArchiveStack_stub, quick);
Scr_AddLocalVars_hook.create(game::Scr_AddLocalVars_ADDR(), Scr_AddLocalVars_stub, quick);
VM_UnarchiveStack_hook.create(game::VM_UnarchiveStack.get(), VM_UnarchiveStack_stub, quick);
VM_TerminateStack_hook.create(game::VM_TerminateStack_ADDR(), VM_TerminateStack_stub, quick);
VM_TrimStack_hook.create(game::VM_TrimStack_ADDR(), VM_TrimStack_stub, quick);
Scr_TerminateRunningThread_hook.create(game::Scr_TerminateRunningThread_ADDR(), Scr_TerminateRunningThread_stub, quick);
Scr_TerminateWaitThread_hook.create(game::Scr_TerminateWaitThread_ADDR(), Scr_TerminateWaitThread_stub, quick);
Scr_CancelWaittill_hook.create(game::Scr_CancelWaittill_ADDR(), Scr_CancelWaittill_stub, quick);
Scr_TerminateWaittillThread_hook.create(game::Scr_TerminateWaittillThread_ADDR(), Scr_TerminateWaittillThread_stub, quick);
Scr_TerminateThread_hook.create(game::Scr_TerminateThread_ADDR(), Scr_TerminateThread_stub, quick);
VM_Notify_hook.create(game::VM_Notify_ADDR(), VM_Notify_stub, quick);
Scr_NotifyNum_Internal_hook.create(game::Scr_NotifyNum_Internal_ADDR(), Scr_NotifyNum_Internal_stub, quick);
Scr_CancelNotifyList_hook.create(game::Scr_CancelNotifyList_ADDR(), Scr_CancelNotifyList_stub, quick);
VM_TerminateTime_hook.create(game::VM_TerminateTime_ADDR(), VM_TerminateTime_stub, quick);
VM_Resume_hook.create(game::VM_Resume_ADDR(), VM_Resume_stub, quick);
VM_Execute_hook.create(game::VM_Execute.get(), VM_Execute_stub, quick);
Scr_ExecThread_hook.create(game::Scr_ExecThread_ADDR(), Scr_ExecThread_stub, quick);
Scr_ExecEntThread_hook.create(game::Scr_ExecEntThread_ADDR(), Scr_ExecEntThread_stub, quick);
Scr_AddExecThread_hook.create(game::Scr_AddExecThread_ADDR(), Scr_AddExecThread_stub, quick);
VM_SetTime_hook.create(game::VM_SetTime_ADDR(), VM_SetTime_stub, quick);
Scr_InitSystem_hook.create(game::Scr_InitSystem_ADDR(), Scr_InitSystem_stub, quick);
Scr_ShutdownSystem_hook.create(game::Scr_ShutdownSystem.get(), Scr_ShutdownSystem_stub, quick);
Scr_IsSystemActive_hook.create(game::Scr_IsSystemActive.get(), Scr_IsSystemActive_stub, quick);
Scr_GetInt_hook.create(game::Scr_GetInt_ADDR(), Scr_GetInt_stub, quick);
Scr_GetAnim_hook.create(game::Scr_GetAnim_ADDR(), Scr_GetAnim_stub, quick);
Scr_GetAnimTree_hook.create(game::Scr_GetAnimTree.get(), Scr_GetAnimTree_stub, quick);
Scr_GetFloat_hook.create(game::Scr_GetFloat_ADDR(), Scr_GetFloat_stub, quick);
Scr_GetConstString_hook.create(game::Scr_GetConstString_ADDR(), Scr_GetConstString_stub, quick);
Scr_GetConstLowercaseString_hook.create(game::Scr_GetConstLowercaseString_ADDR(), Scr_GetConstLowercaseString_stub, quick);
Scr_GetString_hook.create(game::Scr_GetString_ADDR(), Scr_GetString_stub, quick);
Scr_GetConstStringIncludeNull_hook.create(game::Scr_GetConstStringIncludeNull_ADDR(), Scr_GetConstStringIncludeNull_stub, quick);
Scr_GetDebugString_hook.create(game::Scr_GetDebugString_ADDR(), Scr_GetDebugString_stub, quick);
Scr_GetConstIString_hook.create(game::Scr_GetConstIString_ADDR(), Scr_GetConstIString_stub, quick);
Scr_GetVector_hook.create(game::Scr_GetVector_ADDR(), Scr_GetVector_stub, quick);
Scr_GetFunc_hook.create(game::Scr_GetFunc.get(), Scr_GetFunc_stub, quick);
Scr_GetEntityRef_hook.create(game::Scr_GetEntityRef_ADDR(), Scr_GetEntityRef_stub, quick);
Scr_GetObject_hook.create(game::Scr_GetObject_ADDR(), Scr_GetObject_stub, quick);
Scr_GetType_hook.create(game::Scr_GetType_ADDR(), Scr_GetType_stub, quick);
Scr_GetTypeName_hook.create(game::Scr_GetTypeName_ADDR(), Scr_GetTypeName_stub, quick);
Scr_GetPointerType_hook.create(game::Scr_GetPointerType_ADDR(), Scr_GetPointerType_stub, quick);
Scr_AddInt_hook.create(game::Scr_AddInt_ADDR(), Scr_AddInt_stub, quick);
Scr_AddFloat_hook.create(game::Scr_AddFloat_ADDR(), Scr_AddFloat_stub, quick);
Scr_AddAnim_hook.create(game::Scr_AddAnim.get(), Scr_AddAnim_stub, quick);
Scr_AddUndefined_hook.create(game::Scr_AddUndefined_ADDR(), Scr_AddUndefined_stub, quick);
Scr_AddObject_hook.create(game::Scr_AddObject_ADDR(), Scr_AddObject_stub, quick);
Scr_AddString_hook.create(game::Scr_AddString_ADDR(), Scr_AddString_stub, quick);
Scr_AddIString_hook.create(game::Scr_AddIString_ADDR(), Scr_AddIString_stub, quick);
Scr_AddConstString_hook.create(game::Scr_AddConstString_ADDR(), Scr_AddConstString_stub, quick);
Scr_AddVector_hook.create(game::Scr_AddVector_ADDR(), Scr_AddVector_stub, quick);
Scr_MakeArray_hook.create(game::Scr_MakeArray_ADDR(), Scr_MakeArray_stub, quick);
Scr_AddArray_hook.create(game::Scr_AddArray.get(), Scr_AddArray_stub, quick);
Scr_AddArrayStringIndexed_hook.create(game::Scr_AddArrayStringIndexed_ADDR(), Scr_AddArrayStringIndexed_stub, quick);
Scr_Error_hook.create(game::Scr_Error_ADDR(), Scr_Error_stub, quick);
Scr_TerminalError_hook.create(game::Scr_TerminalError_ADDR(), Scr_TerminalError_stub, quick);
Scr_ParamError_hook.create(game::Scr_ParamError_ADDR(), Scr_ParamError_stub, quick);
Scr_ObjectError_hook.create(game::Scr_ObjectError_ADDR(), Scr_ObjectError_stub, quick);
SetEntityFieldValue_hook.create(game::SetEntityFieldValue_ADDR(), SetEntityFieldValue_stub, quick);
GetEntityFieldValue_hook.create(game::GetEntityFieldValue_ADDR(), GetEntityFieldValue_stub, quick);
Scr_SetStructField_hook.create(game::Scr_SetStructField_ADDR(), Scr_SetStructField_stub, quick);
Scr_IncTime_hook.create(game::Scr_IncTime_ADDR(), Scr_IncTime_stub, quick);
Scr_RunCurrentThreads_hook.create(game::Scr_RunCurrentThreads_ADDR(), Scr_RunCurrentThreads_stub, quick);
Scr_ResetTimeout_hook.create(game::Scr_ResetTimeout_ADDR(), Scr_ResetTimeout_stub, quick);
Scr_VM_Init_hook.create(game::Scr_VM_Init.get(), Scr_VM_Init_stub);
Scr_Init_hook.create(game::Scr_Init_ADDR(), Scr_Init_stub);
Scr_Shutdown_hook.create(game::Scr_Shutdown_ADDR(), Scr_Shutdown_stub);
Scr_ErrorInternal_hook.create(game::Scr_ErrorInternal_ADDR(), Scr_ErrorInternal_stub);
Scr_ClearOutParams_hook.create(game::Scr_ClearOutParams_ADDR(), Scr_ClearOutParams_stub);
GetDummyObject_hook.create(game::GetDummyObject_ADDR(), GetDummyObject_stub);
GetDummyFieldValue_hook.create(game::GetDummyFieldValue_ADDR(), GetDummyFieldValue_stub);
VM_ExecuteInternal_hook.create(game::VM_ExecuteInternal.get(), VM_ExecuteInternal_stub);
VM_CancelNotifyInternal_hook.create(game::VM_CancelNotifyInternal_ADDR(), VM_CancelNotifyInternal_stub);
VM_CancelNotify_hook.create(game::VM_CancelNotify_ADDR(), VM_CancelNotify_stub);
VM_ArchiveStack_hook.create(game::VM_ArchiveStack_ADDR(), VM_ArchiveStack_stub);
Scr_AddLocalVars_hook.create(game::Scr_AddLocalVars_ADDR(), Scr_AddLocalVars_stub);
VM_UnarchiveStack_hook.create(game::VM_UnarchiveStack.get(), VM_UnarchiveStack_stub);
VM_TerminateStack_hook.create(game::VM_TerminateStack_ADDR(), VM_TerminateStack_stub);
VM_TrimStack_hook.create(game::VM_TrimStack_ADDR(), VM_TrimStack_stub);
Scr_TerminateRunningThread_hook.create(game::Scr_TerminateRunningThread_ADDR(), Scr_TerminateRunningThread_stub);
Scr_TerminateWaitThread_hook.create(game::Scr_TerminateWaitThread_ADDR(), Scr_TerminateWaitThread_stub);
Scr_CancelWaittill_hook.create(game::Scr_CancelWaittill_ADDR(), Scr_CancelWaittill_stub);
Scr_TerminateWaittillThread_hook.create(game::Scr_TerminateWaittillThread_ADDR(), Scr_TerminateWaittillThread_stub);
Scr_TerminateThread_hook.create(game::Scr_TerminateThread_ADDR(), Scr_TerminateThread_stub);
VM_Notify_hook.create(game::VM_Notify_ADDR(), VM_Notify_stub);
Scr_NotifyNum_Internal_hook.create(game::Scr_NotifyNum_Internal_ADDR(), Scr_NotifyNum_Internal_stub);
Scr_CancelNotifyList_hook.create(game::Scr_CancelNotifyList_ADDR(), Scr_CancelNotifyList_stub);
VM_TerminateTime_hook.create(game::VM_TerminateTime_ADDR(), VM_TerminateTime_stub);
VM_Resume_hook.create(game::VM_Resume_ADDR(), VM_Resume_stub);
VM_Execute_hook.create(game::VM_Execute.get(), VM_Execute_stub);
Scr_ExecThread_hook.create(game::Scr_ExecThread_ADDR(), Scr_ExecThread_stub);
Scr_ExecEntThread_hook.create(game::Scr_ExecEntThread_ADDR(), Scr_ExecEntThread_stub);
Scr_AddExecThread_hook.create(game::Scr_AddExecThread_ADDR(), Scr_AddExecThread_stub);
VM_SetTime_hook.create(game::VM_SetTime_ADDR(), VM_SetTime_stub);
Scr_InitSystem_hook.create(game::Scr_InitSystem_ADDR(), Scr_InitSystem_stub);
Scr_ShutdownSystem_hook.create(game::Scr_ShutdownSystem.get(), Scr_ShutdownSystem_stub);
Scr_IsSystemActive_hook.create(game::Scr_IsSystemActive.get(), Scr_IsSystemActive_stub);
Scr_GetInt_hook.create(game::Scr_GetInt_ADDR(), Scr_GetInt_stub);
Scr_GetAnim_hook.create(game::Scr_GetAnim_ADDR(), Scr_GetAnim_stub);
Scr_GetAnimTree_hook.create(game::Scr_GetAnimTree.get(), Scr_GetAnimTree_stub);
Scr_GetFloat_hook.create(game::Scr_GetFloat_ADDR(), Scr_GetFloat_stub);
Scr_GetConstString_hook.create(game::Scr_GetConstString_ADDR(), Scr_GetConstString_stub);
Scr_GetConstLowercaseString_hook.create(game::Scr_GetConstLowercaseString_ADDR(), Scr_GetConstLowercaseString_stub);
Scr_GetString_hook.create(game::Scr_GetString_ADDR(), Scr_GetString_stub);
Scr_GetConstStringIncludeNull_hook.create(game::Scr_GetConstStringIncludeNull_ADDR(), Scr_GetConstStringIncludeNull_stub);
Scr_GetDebugString_hook.create(game::Scr_GetDebugString_ADDR(), Scr_GetDebugString_stub);
Scr_GetConstIString_hook.create(game::Scr_GetConstIString_ADDR(), Scr_GetConstIString_stub);
Scr_GetVector_hook.create(game::Scr_GetVector_ADDR(), Scr_GetVector_stub);
Scr_GetFunc_hook.create(game::Scr_GetFunc.get(), Scr_GetFunc_stub);
Scr_GetEntityRef_hook.create(game::Scr_GetEntityRef_ADDR(), Scr_GetEntityRef_stub);
Scr_GetObject_hook.create(game::Scr_GetObject_ADDR(), Scr_GetObject_stub);
Scr_GetType_hook.create(game::Scr_GetType_ADDR(), Scr_GetType_stub);
Scr_GetTypeName_hook.create(game::Scr_GetTypeName_ADDR(), Scr_GetTypeName_stub);
Scr_GetPointerType_hook.create(game::Scr_GetPointerType_ADDR(), Scr_GetPointerType_stub);
Scr_AddInt_hook.create(game::Scr_AddInt_ADDR(), Scr_AddInt_stub);
Scr_AddFloat_hook.create(game::Scr_AddFloat_ADDR(), Scr_AddFloat_stub);
Scr_AddAnim_hook.create(game::Scr_AddAnim.get(), Scr_AddAnim_stub);
Scr_AddUndefined_hook.create(game::Scr_AddUndefined_ADDR(), Scr_AddUndefined_stub);
Scr_AddObject_hook.create(game::Scr_AddObject_ADDR(), Scr_AddObject_stub);
Scr_AddString_hook.create(game::Scr_AddString_ADDR(), Scr_AddString_stub);
Scr_AddIString_hook.create(game::Scr_AddIString_ADDR(), Scr_AddIString_stub);
Scr_AddConstString_hook.create(game::Scr_AddConstString_ADDR(), Scr_AddConstString_stub);
Scr_AddVector_hook.create(game::Scr_AddVector_ADDR(), Scr_AddVector_stub);
Scr_MakeArray_hook.create(game::Scr_MakeArray_ADDR(), Scr_MakeArray_stub);
Scr_AddArray_hook.create(game::Scr_AddArray.get(), Scr_AddArray_stub);
Scr_AddArrayStringIndexed_hook.create(game::Scr_AddArrayStringIndexed_ADDR(), Scr_AddArrayStringIndexed_stub);
Scr_Error_hook.create(game::Scr_Error_ADDR(), Scr_Error_stub);
Scr_TerminalError_hook.create(game::Scr_TerminalError_ADDR(), Scr_TerminalError_stub);
Scr_ParamError_hook.create(game::Scr_ParamError_ADDR(), Scr_ParamError_stub);
Scr_ObjectError_hook.create(game::Scr_ObjectError_ADDR(), Scr_ObjectError_stub);
SetEntityFieldValue_hook.create(game::SetEntityFieldValue_ADDR(), SetEntityFieldValue_stub);
GetEntityFieldValue_hook.create(game::GetEntityFieldValue_ADDR(), GetEntityFieldValue_stub);
Scr_SetStructField_hook.create(game::Scr_SetStructField_ADDR(), Scr_SetStructField_stub);
Scr_IncTime_hook.create(game::Scr_IncTime_ADDR(), Scr_IncTime_stub);
Scr_RunCurrentThreads_hook.create(game::Scr_RunCurrentThreads_ADDR(), Scr_RunCurrentThreads_stub);
Scr_ResetTimeout_hook.create(game::Scr_ResetTimeout_ADDR(), Scr_ResetTimeout_stub);
//Original hook function addresses
Scr_VM_Init_original = Scr_VM_Init_hook.get_original();

View File

@ -199,22 +199,17 @@ namespace re_cscr_yacc
public:
void post_unpack() override
{
bool quick = true;
#ifdef RE_CSCR_YACC_USE_WRAPPERS
quick = false;
#endif
LowerCase_hook.create(game::LowerCase_ADDR(), LowerCase_stub, quick);
yyparse_hook.create(game::yyparse.get(), yyparse_stub, quick);
StringValue_hook.create(game::StringValue_ADDR(), StringValue_stub, quick);
yylex_hook.create(game::yylex.get(), yylex_stub, quick);
yy_get_next_buffer_hook.create(game::yy_get_next_buffer.get(), yy_get_next_buffer_stub, quick);
yy_get_previous_state_hook.create(game::yy_get_previous_state.get(), yy_get_previous_state_stub, quick);
yy_try_NUL_trans_hook.create(game::yy_try_NUL_trans_ADDR(), yy_try_NUL_trans_stub, quick);
yyrestart_hook.create(game::yyrestart.get(), yyrestart_stub, quick);
yy_create_buffer_hook.create(game::yy_create_buffer.get(), yy_create_buffer_stub, quick);
yy_flush_buffer_hook.create(game::yy_flush_buffer_ADDR(), yy_flush_buffer_stub, quick);
ScriptParse_hook.create(game::ScriptParse_ADDR(), ScriptParse_stub, quick);
LowerCase_hook.create(game::LowerCase(), LowerCase_stub);
yyparse_hook.create(game::yyparse.get(), yyparse_stub);
StringValue_hook.create(game::StringValue(), StringValue_stub);
yylex_hook.create(game::yylex.get(), yylex_stub);
yy_get_next_buffer_hook.create(game::yy_get_next_buffer.get(), yy_get_next_buffer_stub);
yy_get_previous_state_hook.create(game::yy_get_previous_state.get(), yy_get_previous_state_stub);
yy_try_NUL_trans_hook.create(game::yy_try_NUL_trans(), yy_try_NUL_trans_stub);
yyrestart_hook.create(game::yyrestart.get(), yyrestart_stub);
yy_create_buffer_hook.create(game::yy_create_buffer.get(), yy_create_buffer_stub);
yy_flush_buffer_hook.create(game::yy_flush_buffer(), yy_flush_buffer_stub);
ScriptParse_hook.create(game::ScriptParse(), ScriptParse_stub);
//Original hook function addresses
LowerCase_original = LowerCase_hook.get_original();

View File

@ -1,467 +0,0 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "gsc.hpp"
#include "scheduler.hpp"
#include <utils/memory.hpp>
#include <utils/string.hpp>
namespace fileio
{
namespace
{
static constexpr size_t max_fhs = 10;
static constexpr size_t max_gsc_string = 0x10000 - 1;
enum class scr_fh_type_e
{
UNUSED,
READ,
WRITE,
APPEND
};
struct scr_fh_t
{
scr_fh_type_e type;
std::unique_ptr<char[]> file_buff;
int file_length;
int seek;
std::filesystem::path full_path;
std::string base_path;
};
std::array<scr_fh_t, max_fhs> scr_fhs = {};
bool validate_scr_path(const std::string& fpath)
{
auto toks = utils::string::split(fpath, '/');
for (const auto& tok : toks)
{
if (tok == "." || tok == "..")
{
return false;
}
if (tok.find(":") != std::string::npos)
{
return false;
}
}
return true;
}
std::string build_base_path(const std::string& path_)
{
auto path = path_;
std::replace(path.begin(), path.end(), '\\', '/');
if (!validate_scr_path(path))
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, utils::string::va("Invalid path: %s", path_.c_str()));
}
// its sandboxed, but what about symlinks?
return path.starts_with("scriptdata/") ? path : "scriptdata/" + path;
}
std::filesystem::path build_full_path(const std::string& path, bool use_global)
{
static game::dvar_s* fs_localAppData = nullptr;
static game::dvar_s* fs_gamedir = nullptr;
if (!fs_localAppData)
{
fs_localAppData = game::Dvar_FindVar("fs_localAppData");
}
if (!fs_gamedir)
{
fs_gamedir = game::Dvar_FindVar("fs_game");
}
return std::filesystem::path(fs_localAppData->current.string) / (!use_global && *fs_gamedir->current.string ? fs_gamedir->current.string : "raw") / path;
}
void free_scr_fh(scr_fh_t& scr_fh)
{
#ifdef DEBUG
plugin::get()->get_interface()->logging()->info(utils::string::va("free_scr_fh: closing %s\n", scr_fh.base_path.c_str()));
#endif
scr_fh = {};
scr_fh.type = scr_fh_type_e::UNUSED;
}
void close_all_scr_fh()
{
for (auto& fh : scr_fhs)
{
if (fh.type == scr_fh_type_e::UNUSED)
{
continue;
}
free_scr_fh(fh);
}
}
int scr_get_fh()
{
auto fh = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 0) - 1;
if (fh < 0 || fh >= max_fhs)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "fs_fwrite: invalid filehandle");
}
return fh;
}
void fwrite_to_file(bool append_newline)
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type != scr_fh_type_e::WRITE && scr_fhs[fh].type != scr_fh_type_e::APPEND)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for writing");
}
std::string to_write = game::Scr_GetString(1, game::SCRIPTINSTANCE_SERVER);
if (append_newline)
{
to_write += '\n';
}
if (!utils::io::write_file(scr_fhs[fh].full_path.string(), to_write, true))
{
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Failed to write file: %s\n", scr_fhs[fh].base_path.c_str());
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
}
void add_file_io()
{
scheduler::on_scr_execute([]()
{
close_all_scr_fh();
});
gsc::function::add("fs_testfile", []()
{
auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER));
auto fd = 0;
auto file_length = game::FS_FOpenFileRead(fpath.c_str(), &fd);
if (!fd || file_length < 0)
{
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
game::FS_FCloseFile(fd);
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
});
gsc::function::add("fs_fopen", []()
{
auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER));
// check for dupes
for (const auto& scr_fd : scr_fhs)
{
if (scr_fd.type != scr_fh_type_e::UNUSED && scr_fd.base_path == fpath)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File already opened");
}
}
// check for avail slot
auto i = 0;
for (; i < max_fhs; i++)
{
if (scr_fhs[i].type == scr_fh_type_e::UNUSED)
{
break;
}
}
if (i >= max_fhs)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "Too many files opened");
}
// check mode
auto mode = game::Scr_GetString(1, game::SCRIPTINSTANCE_SERVER);
if (mode == "read"s)
{
auto fd = 0;
auto file_length = game::FS_FOpenFileRead(fpath.c_str(), &fd);
if (!fd || file_length < 0)
{
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Failed to open file for reading: %s\n", fpath.c_str());
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
scr_fhs[i].file_buff = std::make_unique<char[]>(file_length + 1);
auto bytes_read = game::FS_Read(scr_fhs[i].file_buff.get(), file_length, fd);
scr_fhs[i].file_buff[file_length] = '\0';
game::FS_FCloseFile(fd);
assert(bytes_read == file_length);
if (bytes_read < 0)
{
scr_fhs[i].file_buff = {};
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Failed to read file: %s\n", fpath.c_str());
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
scr_fhs[i].type = scr_fh_type_e::READ;
scr_fhs[i].file_length = bytes_read;
scr_fhs[i].seek = 0;
scr_fhs[i].base_path = fpath;
}
else if (mode == "write"s || mode == "append"s)
{
auto full_path = build_full_path(fpath, game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 3 && game::Scr_GetType(game::SCRIPTINSTANCE_SERVER, 2) == game::VAR_INTEGER && game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 2));
if (!utils::io::write_file(full_path.string(), "", (mode == "append"s)))
{
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Failed to open file for writing: %s\n", fpath.c_str());
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
scr_fhs[i].type = scr_fh_type_e::WRITE;
scr_fhs[i].base_path = fpath;
scr_fhs[i].full_path = full_path;
}
else
{
game::Scr_ParamError(1, game::SCRIPTINSTANCE_SERVER, utils::string::va("Invalid mode: %s", mode));
}
#ifdef DEBUG
plugin::get()->get_interface()->logging()->info(utils::string::va("gscr_fs_fopen: opening %s, mode %s\n", fpath.c_str(), mode));
#endif
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, i + 1);
});
gsc::function::add("fs_write", []()
{
fwrite_to_file(false);
});
gsc::function::add("fs_writeline", []()
{
fwrite_to_file(true);
});
gsc::function::add("fs_readline", []()
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type != scr_fh_type_e::READ)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading");
}
// file is completed being read
if (scr_fhs[fh].seek >= scr_fhs[fh].file_length)
{
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
return;
}
// count how many bytes until the newline
auto bytes_to_read = 0;
auto found_nl = false;
for (auto i = scr_fhs[fh].seek; i < scr_fhs[fh].file_length; bytes_to_read++, i++)
{
if (scr_fhs[fh].file_buff[i] == '\n')
{
bytes_to_read++;
found_nl = true;
break;
}
}
if (bytes_to_read > max_gsc_string)
{
found_nl = false;
bytes_to_read = max_gsc_string;
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Line was too long in file %s, truncating\n", scr_fhs[fh].base_path.c_str());
}
auto scr_str = std::string(&scr_fhs[fh].file_buff[scr_fhs[fh].seek], bytes_to_read);
scr_fhs[fh].seek += bytes_to_read;
// remove all '\r'
scr_str.erase(std::remove(scr_str.begin(), scr_str.end(), '\r'), scr_str.end());
// chop the newline char off
if (found_nl)
{
scr_str.pop_back();
}
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, scr_str.c_str());
});
gsc::function::add("fs_read", []()
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type != scr_fh_type_e::READ)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading");
}
// file is completed being read
if (scr_fhs[fh].seek >= scr_fhs[fh].file_length)
{
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
return;
}
auto bytes_to_read = scr_fhs[fh].file_length - scr_fhs[fh].seek;
if (game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 2)
{
bytes_to_read = std::clamp(game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 1), 0, bytes_to_read);
if (bytes_to_read <= 0)
{
game::Scr_ParamError(1, game::SCRIPTINSTANCE_SERVER, "Trying to read <1 bytes");
}
}
if (bytes_to_read > max_gsc_string)
{
bytes_to_read = max_gsc_string;
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Line was too long in file %s, truncating\n", scr_fhs[fh].base_path.c_str());
}
auto scr_str = std::string(&scr_fhs[fh].file_buff[scr_fhs[fh].seek], bytes_to_read);
scr_fhs[fh].seek += bytes_to_read;
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, scr_str.c_str());
});
gsc::function::add("fs_fcloseall", []()
{
close_all_scr_fh();
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
});
gsc::function::add("fs_fclose", []()
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type == scr_fh_type_e::UNUSED)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened");
}
free_scr_fh(scr_fhs[fh]);
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
});
gsc::function::add("fs_length", []()
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type == scr_fh_type_e::UNUSED)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened");
}
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, scr_fhs[fh].file_length);
});
gsc::function::add("fs_getseek", []()
{
auto fh = scr_get_fh();
// write seek would require completely redoing how we write files...
if (scr_fhs[fh].type != scr_fh_type_e::READ)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading");
}
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, scr_fhs[fh].seek);
});
gsc::function::add("fs_seek", []()
{
auto fh = scr_get_fh();
if (scr_fhs[fh].type != scr_fh_type_e::READ)
{
game::Scr_ParamError(0, game::SCRIPTINSTANCE_SERVER, "File not opened for reading");
}
scr_fhs[fh].seek = std::clamp(game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 1), 0, scr_fhs[fh].file_length);
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
});
gsc::function::add("fs_remove", []()
{
auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER));
auto full_path = build_full_path(fpath, game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 2 && game::Scr_GetType(game::SCRIPTINSTANCE_SERVER, 1) == game::VAR_INTEGER && game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 1));
if (!utils::io::remove_file(full_path.string()))
{
game::Com_PrintWarning(game::CON_CHANNEL_SCRIPT, "Failed to delete file: %s\n", fpath.c_str());
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 0);
return;
}
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
});
gsc::function::add("fs_listfiles", []()
{
auto fpath = build_base_path(game::Scr_GetString(0, game::SCRIPTINSTANCE_SERVER));
int numfiles;
auto* files = game::FS_ListFiles(fpath.c_str(), "", game::FS_LIST_ALL, &numfiles);
game::Scr_MakeArray(game::SCRIPTINSTANCE_SERVER);
for (int i = 0; i < numfiles; i++)
{
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, files[i]);
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
}
game::FS_FreeFileList(files);
});
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
add_file_io();
}
private:
};
}
REGISTER_COMPONENT(fileio::component)

View File

@ -1,14 +1,125 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "gsc.hpp"
#include "scheduler.hpp"
#include <json.hpp>
#include <utils/io.hpp>
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace gsc
{
std::unordered_map<std::string, game::BuiltinFunction> functions;
std::unordered_map<std::string, game::BuiltinMethod> methods;
utils::hook::detour scr_getmethod_hook;
void* scr_getfunction_stub_ret_loc;
namespace
{
game::BuiltinFunction scr_getfunction_call(const char** pName, int* pType)
{
auto itr = functions.find(*pName);
if (itr == functions.end())
{
return nullptr;
}
*pType = 0;
return itr->second;
}
game::BuiltinFunction NAKED scr_getfunction_stub()
{
__asm
{
push eax;
pushad;
lea eax, [esp + 0x24 + 0x2C - 0x1C];
push eax;
push edx;
call scr_getfunction_call;
add esp, 8;
mov [esp + 0x20], eax;
popad;
pop eax;
test eax, eax;
jnz just_ret;
// go do original code
push scr_getfunction_stub_ret_loc;
ret;
just_ret:
add esp, 4;
push 0x682DC8;
ret;
}
}
game::BuiltinMethod scr_getmethod_call(const char** pName, int* pType)
{
auto itr = methods.find(*pName);
if (itr == methods.end())
{
// call og
const auto og_addr = scr_getmethod_hook.get_original();
game::BuiltinMethod answer;
__asm
{
mov edi, pType;
mov esi, pName;
call og_addr;
mov answer, eax;
}
return answer;
}
*pType = 0;
return itr->second;
}
game::BuiltinMethod NAKED scr_getmethod_stub()
{
__asm
{
push edi;
push esi;
call scr_getmethod_call;
add esp, 8;
ret;
}
}
}
namespace function
{
void add(const std::string& name, const game::BuiltinFunction function)
{
plugin::get()->get_interface()->gsc()->register_function(name, function);
functions.insert_or_assign(name, function);
}
game::BuiltinFunction get(const char** name, int* type)
{
auto got = functions.find(*name);
if (got == functions.end())
{
return nullptr;
}
*type = 0;
return got->second;
}
}
@ -16,8 +127,46 @@ namespace gsc
{
void add(const std::string& name, const game::BuiltinMethod method)
{
plugin::get()->get_interface()->gsc()->register_method(name, (plutonium::sdk::v1::interfaces::gsc::method_callback)method);
methods.insert_or_assign(name, method);
}
game::BuiltinMethod get(const char** name, int* type)
{
auto got = methods.find(*name);
if (got == methods.end())
{
return nullptr;
}
*type = 0;
return got->second;
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
// for when we dont use the decomp
// custom gsc methods
if (game::plutonium::scr_get_method_stub != nullptr)
{
scr_getmethod_hook.create(game::plutonium::scr_get_method_stub.get(), scr_getmethod_stub);
}
// custom gsc funcs
if (game::plutonium::scr_get_function_stub != nullptr)
{
scr_getfunction_stub_ret_loc = game::plutonium::scr_get_function_stub.get();
utils::hook::jump(SELECT(0x0, 0x682D99), scr_getfunction_stub);
}
}
private:
};
}
REGISTER_COMPONENT(gsc::component)

View File

@ -5,10 +5,12 @@ namespace gsc
namespace function
{
void add(const std::string& name, const game::BuiltinFunction function);
game::BuiltinFunction get(const char** name, int* type);
}
namespace method
{
void add(const std::string& name, const game::BuiltinMethod method);
game::BuiltinMethod get(const char** name, int* type);
}
}

View File

@ -1,11 +1,195 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "scheduler.hpp"
#include <utils/concurrency.hpp>
#include <utils/hook.hpp>
namespace scheduler
{
void on_scr_execute(void(*callback)())
namespace
{
plugin::get()->get_interface()->callbacks()->on_scripts_execute(callback);
struct task
{
std::function<bool()> handler{};
std::chrono::milliseconds interval{};
std::chrono::high_resolution_clock::time_point last_call{};
};
using task_list = std::vector<task>;
class task_pipeline
{
public:
void add(task&& task)
{
new_callbacks_.access([&task](task_list& tasks)
{
tasks.emplace_back(std::move(task));
});
}
void execute()
{
callbacks_.access([&](task_list& tasks)
{
this->merge_callbacks();
for (auto i = tasks.begin(); i != tasks.end();)
{
const auto now = std::chrono::high_resolution_clock::now();
const auto diff = now - i->last_call;
if (diff < i->interval)
{
++i;
continue;
}
i->last_call = now;
const auto res = i->handler();
if (res == cond_end)
{
i = tasks.erase(i);
}
else
{
++i;
}
}
});
}
private:
utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;
void merge_callbacks()
{
callbacks_.access([&](task_list& tasks)
{
new_callbacks_.access([&](task_list& new_tasks)
{
tasks.insert(tasks.end(), std::move_iterator<task_list::iterator>(new_tasks.begin()), std::move_iterator<task_list::iterator>(new_tasks.end()));
new_tasks = {};
});
});
}
};
std::thread thread;
task_pipeline pipelines[pipeline::count];
void execute(const pipeline type)
{
assert(type >= 0 && type < pipeline::count);
pipelines[type].execute();
}
void execute_server()
{
execute(pipeline::server);
}
void execute_main()
{
execute(pipeline::main);
}
utils::hook::detour com_init_hook;
utils::hook::detour gscr_postloadscripts_hook;
std::vector<std::function<void()>> post_init_funcs;
bool com_inited = false;
void on_post_init_hook()
{
if (com_inited)
{
return;
}
com_inited = true;
for (const auto& func : post_init_funcs)
{
func();
}
post_init_funcs.clear();
}
void com_init_stub()
{
com_init_hook.invoke<void>();
on_post_init_hook();
}
}
void schedule(const std::function<bool()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
assert(type >= 0 && type < pipeline::count);
task task;
task.handler = callback;
task.interval = delay;
task.last_call = std::chrono::high_resolution_clock::now();
pipelines[type].add(std::move(task));
}
void loop(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
schedule([callback]()
{
callback();
return cond_continue;
}, type, delay);
}
void once(const std::function<void()>& callback, const pipeline type,
const std::chrono::milliseconds delay)
{
schedule([callback]()
{
callback();
return cond_end;
}, type, delay);
}
void on_init(const std::function<void()>& callback)
{
if (com_inited)
{
once(callback, pipeline::main);
}
else
{
post_init_funcs.push_back(callback);
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
thread = std::thread([]()
{
while (true)
{
execute(pipeline::async);
std::this_thread::sleep_for(10ms);
}
});
com_init_hook.create(SELECT(0x0, 0x59D710), com_init_stub);
utils::hook::call(SELECT(0x0, 0x503B5D), execute_server);
utils::hook::call(SELECT(0x0, 0x59DCFD), execute_main);
}
};
}
REGISTER_COMPONENT(scheduler::component)

View File

@ -2,5 +2,23 @@
namespace scheduler
{
void on_scr_execute(void(*callback)());
enum pipeline
{
server,
async,
main,
count,
};
static const bool cond_continue = false;
static const bool cond_end = true;
void schedule(const std::function<bool()>& callback, pipeline type = pipeline::main,
std::chrono::milliseconds delay = 0ms);
void loop(const std::function<void()>& callback, pipeline type = pipeline::main,
std::chrono::milliseconds delay = 0ms);
void once(const std::function<void()>& callback, pipeline type = pipeline::main,
std::chrono::milliseconds delay = 0ms);
void on_init(const std::function<void()>& callback);
}

View File

@ -9,32 +9,174 @@
namespace signatures
{
bool addr_is_in_image_space_of_pluto(size_t wheree)
std::string read_sigs_file()
{
return utils::compression::zlib::decompress(utils::cryptography::des::decrypt(utils::io::read_file("t4sp-server-plugin/sigs")));
}
bool write_sigs_file(const std::string& f)
{
return utils::io::write_file("t4sp-server-plugin/sigs", utils::cryptography::des::encrypt(utils::compression::zlib::compress(f)));
}
const char* get_current_version()
{
return *reinterpret_cast<const char**>(0x4FF72D + 4);
}
std::unordered_map<std::string, std::string> get_cache_info_for_our_version()
{
std::unordered_map<std::string, std::string> answer;
auto* version = get_current_version();
nlohmann::json cache_json = nlohmann::json::parse(read_sigs_file(), nullptr, false, true);
if (!cache_json.is_discarded() && cache_json.is_object())
{
for (const auto& [key, value] : cache_json.items())
{
if (key != version)
{
continue;
}
if (!value.is_object())
{
continue;
}
answer = value.get<std::unordered_map<std::string, std::string>>();
break;
}
}
return answer;
}
bool save_cache_info_for_our_version(const std::unordered_map<std::string, std::string>& cache_info)
{
auto* version = get_current_version();
nlohmann::json cache_json = nlohmann::json::parse(read_sigs_file(), nullptr, false, true);
if (cache_json.is_discarded() || !cache_json.is_object())
{
cache_json = nlohmann::json::parse("{}", nullptr, false, true);
if (cache_json.is_discarded() || !cache_json.is_object())
{
return false; // can't happen?
}
}
cache_json[version] = cache_info;
return write_sigs_file(cache_json.dump());
}
size_t load_image_size()
{
MODULEINFO info{};
GetModuleInformation(GetCurrentProcess(),
GetModuleHandle("plutonium-bootstrapper-win32.exe"), &info, sizeof(MODULEINFO));
return info.SizeOfImage;
}
static const auto image_base = reinterpret_cast<size_t>(GetModuleHandle("plutonium-bootstrapper-win32.exe"));
size_t get_image_size()
{
static const auto image_size = load_image_size();
return image_size;
}
return wheree >= image_base && wheree < image_base + info.SizeOfImage;
size_t load_iamge_base()
{
return reinterpret_cast<size_t>(GetModuleHandle("plutonium-bootstrapper-win32.exe"));
}
size_t get_image_base()
{
static const auto image_base = load_iamge_base();
return image_base;
}
bool addr_is_in_image_space(size_t wheree)
{
static const auto image_base = load_iamge_base();
return wheree >= image_base && wheree < image_base + get_image_size();
}
size_t find_string_ptr(const std::string& string)
{
const char* string_ptr = nullptr;
std::string mask(string.size(), 'x');
const auto base = get_image_base();
utils::hook::signature signature(base, get_image_size() - base);
signature.add({
string,
mask,
[&](char* address)
{
string_ptr = address;
}
});
signature.process();
return reinterpret_cast<size_t>(string_ptr);
}
size_t find_string_ref(const std::string& string)
{
char bytes[4] = {0};
const auto string_ptr = find_string_ptr(string);
if (!string_ptr)
{
return 0;
}
std::memcpy(bytes, &string_ptr, sizeof(bytes));
return find_string_ptr({bytes, 4});
}
std::string err_reason;
const std::string& get_err_reason()
{
return err_reason;
}
bool process_printf(std::unordered_map<std::string, std::string> &cache_info)
{
if (cache_info.contains("printf"))
{
game::plutonium::printf.set(std::atoi(cache_info.at("printf").c_str()));
return true;
}
const auto string_ref = find_string_ref("A critical exception occured!\n");
if (!string_ref)
{
err_reason = "printf";
return false;
}
const auto offset = *reinterpret_cast<size_t*>(string_ref + 5);
game::plutonium::printf.set(string_ref + 4 + 5 + offset);
cache_info.insert_or_assign("printf", std::to_string(string_ref + 4 + 5 + offset));
return true;
}
#define SAFE_SET_PLUTO_SYMBOL_DOUBLE(name, addr, off) \
addr2 = reinterpret_cast<size_t>(utils::hook::get_displacement_addr(addr)); \
if (!addr_is_in_image_space_of_pluto(addr2)) \
if (!addr_is_in_image_space(addr2)) \
{ \
err_reason = #name " 1"; \
return false; \
} \
addr1 = reinterpret_cast<size_t>(utils::hook::get_displacement_addr(addr2 + off)); \
if (!addr_is_in_image_space_of_pluto(addr1)) \
if (!addr_is_in_image_space(addr1)) \
{ \
err_reason = #name " 2"; \
return false; \
@ -44,7 +186,7 @@ namespace signatures
#define SAFE_SET_PLUTO_SYMBOL(name, addr) \
addr1 = reinterpret_cast<size_t>(utils::hook::get_displacement_addr(addr)); \
if (!addr_is_in_image_space_of_pluto(addr1)) \
if (!addr_is_in_image_space(addr1)) \
{ \
err_reason = #name; \
return false; \
@ -56,6 +198,12 @@ namespace signatures
{
size_t addr1;
size_t addr2;
auto cache_info = get_cache_info_for_our_version();
if (!process_printf(cache_info))
{
return false;
}
SAFE_SET_PLUTO_SYMBOL_DOUBLE(load_custom_script_func, 0x689C80, 0x6);
SAFE_SET_PLUTO_SYMBOL_DOUBLE(script_preprocess, 0x689BCF, 0x2);
@ -68,15 +216,21 @@ namespace signatures
SAFE_SET_PLUTO_SYMBOL_DOUBLE(store_func_codepos, 0x688909, 0x3);
SAFE_SET_PLUTO_SYMBOL(cscr_get_function_hook, 0x682DC0);
SAFE_SET_PLUTO_SYMBOL(scr_get_function_stub, 0x682D99);
SAFE_SET_PLUTO_SYMBOL(scr_get_method_stub, 0x683043);
SAFE_SET_PLUTO_SYMBOL(cscr_get_method_hook, 0x68305C);
SAFE_SET_PLUTO_SYMBOL_DOUBLE(scr_get_method_hook, 0x683043, 0x4);
SAFE_SET_PLUTO_SYMBOL_DOUBLE(scr_get_function_hook, 0x682D99, 0x8);
save_cache_info_for_our_version(cache_info);
return true;
}
bool process()
{
utils::cryptography::des::set_key("694201337");
return handle_funcs();
}
}

View File

@ -1,11 +1,40 @@
#include <stdinc.hpp>
#include "loader/component_loader.hpp"
#include "component/signatures.hpp"
PLUTONIUM_API plutonium::sdk::plugin* PLUTONIUM_CALLBACK on_initialize()
{
return plugin::get();
}
#include <utils/hook.hpp>
BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD /*ul_reason_for_call*/, LPVOID /*reserved_*/)
BOOL APIENTRY DllMain(HMODULE /*module_*/, DWORD ul_reason_for_call, LPVOID /*reserved_*/)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if (game::environment::t4sp())
{
if (!signatures::process())
{
MessageBoxA(NULL,
std::format("This version of t4sp-server-plugin is outdated.\n" \
"Download the latest dll from here: https://github.com/JezuzLizard/T4SP-Server-Plugin/releases\n" \
"'{}' failed", signatures::get_err_reason()).c_str(),
"ERROR", MB_ICONERROR);
return FALSE;
}
if (game::plutonium::printf.get() != nullptr)
{
utils::hook::jump(reinterpret_cast<uintptr_t>(&printf), game::plutonium::printf);
}
component_loader::post_unpack();
}
else
{
MessageBoxA(nullptr, "Unsupported game executable. (t4sp is only supported)", "ERROR, BRO!", 0);
return FALSE;
}
}
return TRUE;
}

View File

@ -384,44 +384,6 @@ namespace game
VAR_ENDON_LIST = 0x18,
};
enum scr_builtin_type_t
{
BUILTIN_ANY = 0x0,
BUILTIN_DEVELOPER_ONLY = 0x1,
};
enum Scr_SourceType_t
{
SOURCE_TYPE_NONE = 0x0,
SOURCE_TYPE_BREAKPOINT = 0x1,
SOURCE_TYPE_CALL = 0x2,
};
enum scr_abort_t
{
SCR_ABORT_NONE = 0x0,
SCR_ABORT_CONTINUE = 0x1,
SCR_ABORT_BREAK = 0x2,
SCR_ABORT_RETURN = 0x3,
SCR_ABORT_MAX = 0x3,
};
enum scr_call_type_t
{
CALL_NONE = 0x0,
CALL_BUILTIN = 0x1,
CALL_THREAD = 0x2,
CALL_FUNCTION = 0x3,
};
enum sl_user_type_e
{
SL_USER_GAME = 0x1,
SL_USER_TEMP = 0x2,
SL_USER_XZONE = 0x4,
SL_USER_XZONE_TEMP = 0x8,
};
#pragma endregion
#pragma region "structs"

View File

@ -178,5 +178,4 @@ namespace game
void Scr_EvalBoolNot(scriptInstance_t inst, VariableValue* value);
unsigned int GetInternalVariableIndex(scriptInstance_t inst, unsigned int unsignedValue);
const char* Scr_ReadData(scriptInstance_t inst, const char** pos, unsigned int count);
unsigned int Scr_GetNumParam(game::scriptInstance_t inst);
}

View File

@ -981,9 +981,4 @@ namespace game
{
return codsrc::Scr_ReadData(inst, pos, count);
}
unsigned int Scr_GetNumParam(game::scriptInstance_t inst)
{
return codsrc::Scr_GetNumParam(inst);
}
}

View File

@ -9,16 +9,16 @@ namespace game
WEAK symbol<void()>yyrestart{ 0x0, 0x69D5C0 };
WEAK symbol<yy_buffer_state* ()>yy_create_buffer{ 0x0, 0x69D620 };
inline void* LowerCase_ADDR() { return CALL_ADDR(0x0, 0x69AEA0); }
unsigned int LowerCase(unsigned int strVal, void* call_addr = LowerCase_ADDR());
inline void* StringValue_ADDR() { return CALL_ADDR(0x0, 0x69BFF0); }
int StringValue(int len, const char* str_, void* call_addr = StringValue_ADDR());
inline void* yy_try_NUL_trans_ADDR() { return CALL_ADDR(0x0, 0x69D520); }
int yy_try_NUL_trans(int yy_current_state, void* call_addr = yy_try_NUL_trans_ADDR());
inline void* yy_flush_buffer_ADDR() { return CALL_ADDR(0x0, 0x69D690); }
void yy_flush_buffer(yy_buffer_state* result, void* call_addr = yy_flush_buffer_ADDR());
inline void* ScriptParse_ADDR() { return CALL_ADDR(0x0, 0x69D710); }
void ScriptParse(scriptInstance_t a1, sval_u* parseData, void* call_addr = ScriptParse_ADDR());
inline void* LowerCase() { return CALL_ADDR(0x0, 0x69AEA0); }
unsigned int LowerCase(unsigned int strVal, void* call_addr = LowerCase());
inline void* StringValue() { return CALL_ADDR(0x0, 0x69BFF0); }
int StringValue(int len, const char* str_, void* call_addr = StringValue());
inline void* yy_try_NUL_trans() { return CALL_ADDR(0x0, 0x69D520); }
int yy_try_NUL_trans(int yy_current_state, void* call_addr = yy_try_NUL_trans());
inline void* yy_flush_buffer() { return CALL_ADDR(0x0, 0x69D690); }
void yy_flush_buffer(yy_buffer_state* result, void* call_addr = yy_flush_buffer());
inline void* ScriptParse() { return CALL_ADDR(0x0, 0x69D710); }
void ScriptParse(scriptInstance_t a1, sval_u* parseData, void* call_addr = ScriptParse());
FILE* yy_load_buffer_state();
void yy_fatal_error(const char* err);

View File

@ -3763,9 +3763,6 @@ namespace game
CRITSECT_SCRIPT_STRING = 0xB,
CRITSECT_MEMORY_TREE = 0xC,
CRITSECT_SYS_EVENT_QUEUE = 0xE,
CRITSECT_DXDEVICE = 0x11,
CRITSECT_DXDEVICE_GLOB = 0x12,
CRITSECT_MISSING_ASSET = 0x13,
CRITSECT_PHYSICS_UPDATE = 0x15,
CRITSECT_CINEMATIC = 0x19,
CRITSECT_CINEMATIC_TARGET_CHANGE = 0x1A,
@ -3900,6 +3897,15 @@ namespace game
HUDELEM_UPDATE_ARCHIVAL_AND_CURRENT = 0x3,
};
enum sourceType_e
{
SOURCE_TYPE_BREAKPOINT = 0x1,
SOURCE_TYPE_CALL = 0x2,
SOURCE_TYPE_THREAD_START = 0x4,
SOURCE_TYPE_BUILTIN_CALL = 0x8,
SOURCE_TYPE_NOTIFY = 0x10,
};
enum animBodyPart_t
{
ANIM_BP_UNUSED = 0x0,
@ -3909,51 +3915,6 @@ namespace game
NUM_ANIM_BODYPARTS = 0x4,
};
enum zone_flags_e
{
ZONE_FLAG_none = 0x0,
DB_ZONE_COMMON_LOC = 0x1,
DB_ZONE_LEVEL_LOC = 0x2,
DB_ZONE_CODE = 0x4,
DB_ZONE_COMMON = 0x8,
DB_ZONE_LEVEL = 0x10,
DB_ZONE_LOAD = 0x20,
DB_ZONE_MYCHANGES = 0x40,
ZONE_FLAG_unk3 = 0x80,
DB_ZONE_LEVELOVERLAY = 0x100, // patch, not 'so'
DB_ZONE_PATCH = 0x200,
ZONE_FLAG_unk5 = 0x400,
DB_ZONE_MOD = 0x800,
};
enum xfile_block_type_e
{
XFILE_BLOCK_TEMP = 0x0,
XFILE_BLOCK_RUNTIME = 0x1,
XFILE_BLOCK_RUNTIME_BEGIN = 0x1,
XFILE_BLOCK_LARGE_RUNTIME = 0x2,
XFILE_BLOCK_PHYSICAL_RUNTIME = 0x3,
XFILE_BLOCK_VIRTUAL = 0x4,
XFILE_BLOCK_RUNTIME_END = 0x4,
XFILE_BLOCK_LARGE = 0x5,
XFILE_BLOCK_PHYSICAL = 0x6,
MAX_XFILE_COUNT = 0x7,
};
enum dm_memory_tyep_e
{
DM_MEMORY_TEMP = 0x0,
DM_MEMORY_VIRTUAL = 0x1,
DM_MEMORY_PHYSICAL = 0x2,
};
enum phys_alloc_type_e
{
PHYS_ALLOC_LOW = 0x0,
PHYS_ALLOC_HIGH = 0x1,
PHYS_ALLOC_COUNT = 0x2,
};
#ifdef __cplusplus
}
#endif

View File

@ -231,21 +231,6 @@ namespace game
*cmd_functions = newCmd;
}
// restored
const char** FS_ListFiles(const char* path, const char* extension, FsListBehavior_e behavior, int* numfiles)
{
return FS_ListFilteredFiles(*fs_searchpaths, path, extension, nullptr, behavior, numfiles);
}
// restored
void FS_FreeFileList(const char** list)
{
if ( list )
{
Hunk_UserDestroy((HunkUser*)*(list - 1));
}
}
// restored
void Sys_EnterCriticalSection(CriticalSection critSect)
{

View File

@ -41,7 +41,6 @@
//#define DISABLE_RE_CSCR_PARSETREE
//#define DISABLE_RE_CSCR_READWRITE
//#define DISABLE_RE_CSCR_STRINGLIST
//#define DISABLE_RE_CSCR_VARIABLE
//#define DISABLE_RE_CSCR_VM
//#define DISABLE_RE_CSCR_YACC

View File

@ -3604,6 +3604,17 @@ namespace game
ASSERT_STRUCT_OFFSET(TLSData_t, field_38, 0x38);
ASSERT_STRUCT_OFFSET(TLSData_t, field_3C, 0x3C);
struct XZoneInfo
{
char * name; //OFS: 0x0 SIZE: 0x4
int allocFlags; //OFS: 0x4 SIZE: 0x4
int freeFlags; //OFS: 0x8 SIZE: 0x4
};
ASSERT_STRUCT_SIZE(XZoneInfo, 0xC);
ASSERT_STRUCT_OFFSET(XZoneInfo, name, 0x0);
ASSERT_STRUCT_OFFSET(XZoneInfo, allocFlags, 0x4);
ASSERT_STRUCT_OFFSET(XZoneInfo, freeFlags, 0x8);
union DvarValue
{
bool enabled; //OFS: 0x0 SIZE: 0x1
@ -11396,6 +11407,17 @@ namespace game
ASSERT_STRUCT_OFFSET(LargeLocal, startPos, 0x0);
ASSERT_STRUCT_OFFSET(LargeLocal, size, 0x4);
struct XFile
{
unsigned int size; //OFS: 0x0 SIZE: 0x4
unsigned int externalSize; //OFS: 0x4 SIZE: 0x4
unsigned int blockSize[8]; //OFS: 0x8 SIZE: 0x20
};
ASSERT_STRUCT_SIZE(XFile, 0x28);
ASSERT_STRUCT_OFFSET(XFile, size, 0x0);
ASSERT_STRUCT_OFFSET(XFile, externalSize, 0x4);
ASSERT_STRUCT_OFFSET(XFile, blockSize, 0x8);
union pointtrace_or_moveclip_u
{
pointtrace_t point; //OFS: 0x0 SIZE: 0x40
@ -12755,6 +12777,21 @@ namespace game
ASSERT_STRUCT_OFFSET(GfxCmdStretchPicRotateXY, color, 0x28);
ASSERT_STRUCT_OFFSET(GfxCmdStretchPicRotateXY, rotation, 0x2C);
struct XZoneMemory
{
XBlock blocks[9]; //OFS: 0x0 SIZE: 0x48
char * lockedVertexData; //OFS: 0x48 SIZE: 0x4
char * lockedIndexData; //OFS: 0x4C SIZE: 0x4
void * vertexBuffer; //OFS: 0x50 SIZE: 0x4
void * indexBuffer; //OFS: 0x54 SIZE: 0x4
};
ASSERT_STRUCT_SIZE(XZoneMemory, 0x58);
ASSERT_STRUCT_OFFSET(XZoneMemory, blocks, 0x0);
ASSERT_STRUCT_OFFSET(XZoneMemory, lockedVertexData, 0x48);
ASSERT_STRUCT_OFFSET(XZoneMemory, lockedIndexData, 0x4C);
ASSERT_STRUCT_OFFSET(XZoneMemory, vertexBuffer, 0x50);
ASSERT_STRUCT_OFFSET(XZoneMemory, indexBuffer, 0x54);
struct SaveMemoryGlob
{
SaveGame * committedGameSave; //OFS: 0x0 SIZE: 0x4
@ -13287,64 +13324,7 @@ namespace game
ASSERT_STRUCT_OFFSET(DynEnt_FadeData, id, 0x0);
ASSERT_STRUCT_OFFSET(DynEnt_FadeData, startTime, 0x4);
struct __declspec(align(2)) GfxMetrics
{
unsigned __int16 cubemapShotRes;
unsigned __int16 cubemapShotPixelBorder;
bool hasAnisotropicMinFilter;
bool hasAnisotropicMagFilter;
int maxAnisotropy;
int maxClipPlanes;
unsigned __int8 shadowmapSamplerState;
bool slopeScaleDepthBias;
bool canMipCubemaps;
};
// cCurve
struct CommonFastFileLoad
{
int code_post_gfx_flags;
int patch_flags;
int ui_flags;
int common_flags;
int flags5;
int localized_common_flags;
const char *code_post_gfx;
const char *patch;
const char *ui;
const char *common;
int filename4;
const char *localized_common;
const char *mod;
};
struct GfxWindowParms
{
HWND__ *hwnd;
int hz;
bool fullscreen;
int x;
int y;
int sceneWidth;
int sceneHeight;
int displayWidth;
int displayHeight;
int aaSamples;
};
struct stream_source_info_t
{
char Stream;
char Offset;
char Type;
};
struct stream_dest_info_t
{
char Usage;
char UsageIndex;
};
#ifdef __cplusplus
}

View File

@ -78,9 +78,6 @@ namespace game
void Sys_EnterCriticalSection(CriticalSection critSect);
void Sys_LeaveCriticalSection(CriticalSection critSect);
const char** FS_ListFiles(const char* path, const char* extension, FsListBehavior_e behavior, int* numfiles);
void FS_FreeFileList(const char** list);
// Variables
WEAK symbol<CRITICAL_SECTION> s_criticalSection{ 0x0, 0x2298D08 };
WEAK symbol<HunkUser*> g_DebugHunkUser{ 0x0, 0x212B2EC };
@ -96,6 +93,8 @@ namespace game
namespace plutonium
{
WEAK symbol<int(const char* fmt, ...)> printf{0x0, 0x0};
WEAK symbol<void(scriptInstance_t)> load_custom_script_func{0x0, 0x0};
WEAK symbol<void(char*, game::scriptInstance_t, sval_u*)> script_preprocess{0x0, 0x0};
WEAK symbol<void(game::scriptInstance_t)> vm_execute_update_codepos{0x0, 0x0};
@ -105,6 +104,9 @@ namespace game
WEAK symbol<const char*(game::scriptInstance_t, unsigned int)> at_codepose_va{ 0x0, 0x0 };
WEAK symbol<void()> scr_get_method_stub{ 0x0, 0x0 };
WEAK symbol<void()> scr_get_function_stub{ 0x0, 0x0 };
WEAK symbol<game::BuiltinMethod(const char** name, int* type)> scr_get_method_hook{ 0x0, 0x0 };
WEAK symbol<game::BuiltinFunction(const char** name, int* type)> scr_get_function_hook{ 0x0, 0x0 };
WEAK symbol<game::BuiltinMethod(const char** name, int* type)> cscr_get_method_hook{ 0x0, 0x0 };

View File

@ -5318,8 +5318,7 @@ namespace game
RawFile* rawfile; //OFS: 0x1A SIZE: 0x4
StringTable* stringTable; //OFS: 0x1B SIZE: 0x4
PackIndex* packIndex; //OFS: 0x1C SIZE: 0x4
snd_alias_list_t* sound; //OFS: 0x1D SIZE: 0x4
void* data; //OFS: 0x1E SIZE: 0x4
void* data; //OFS: 0x1D SIZE: 0x4
};
struct XAsset
@ -5418,28 +5417,6 @@ namespace game
ASSERT_STRUCT_OFFSET(XZone, allocType, 0x8);
ASSERT_STRUCT_OFFSET(XZone, blocks, 0xC);
struct XFile
{
unsigned int size; //OFS: 0x0 SIZE: 0x4
unsigned int externalSize; //OFS: 0x4 SIZE: 0x4
unsigned int blockSize[7]; //OFS: 0x8 SIZE: 0x1C
};
ASSERT_STRUCT_SIZE(XFile, 0x24);
ASSERT_STRUCT_OFFSET(XFile, size, 0x0);
ASSERT_STRUCT_OFFSET(XFile, externalSize, 0x4);
ASSERT_STRUCT_OFFSET(XFile, blockSize, 0x8);
struct XZoneInfo
{
char * name; //OFS: 0x0 SIZE: 0x4
int allocFlags; //OFS: 0x4 SIZE: 0x4
int freeFlags; //OFS: 0x8 SIZE: 0x4
};
ASSERT_STRUCT_SIZE(XZoneInfo, 0xC);
ASSERT_STRUCT_OFFSET(XZoneInfo, name, 0x0);
ASSERT_STRUCT_OFFSET(XZoneInfo, allocFlags, 0x4);
ASSERT_STRUCT_OFFSET(XZoneInfo, freeFlags, 0x8);
#ifdef __cplusplus
WEAK symbol<XAssetHeader(XAssetType type, const char* name, bool errorIfMissing, int waitTime)>DB_FindXAssetHeader{ 0x0, 0x48DA30 };
}

View File

@ -1,68 +0,0 @@
#include <stdinc.hpp>
#include "component/signatures.hpp"
#include <utils/hook.hpp>
#include "loader/component_loader.hpp"
namespace plugin
{
std::uint32_t plugin::plugin_version()
{
return 1;
}
const char* plugin::plugin_name()
{
return "t4sp-server-plugin";
}
bool plugin::is_game_supported(plutonium::sdk::game game)
{
return game == plutonium::sdk::game::t4;
}
void plugin::on_startup(plutonium::sdk::iinterface* interface_ptr, plutonium::sdk::game game)
{
this->interface_ = interface_ptr;
this->game_ = game;
if (!game::environment::t4sp())
{
MessageBoxA(nullptr, "Unsupported game executable. (t4sp is only supported)", "ERROR, BRO!", 0);
return;
}
if (!signatures::process())
{
MessageBoxA(NULL,
std::format("This version of t4sp-server-plugin is outdated.\n" \
"Download the latest dll from here: https://github.com/JezuzLizard/T4SP-Server-Plugin/releases\n" \
"'{}' failed", signatures::get_err_reason()).c_str(),
"ERROR", MB_ICONERROR);
return;
}
component_loader::post_unpack();
}
void plugin::on_shutdown()
{
}
plutonium::sdk::iinterface* plugin::get_interface()
{
return this->interface_;
}
plutonium::sdk::game plugin::get_game()
{
return this->game_;
}
plugin* get()
{
static plugin instance;
return &instance;
}
}

View File

@ -1,30 +0,0 @@
#pragma once
#include <plutonium_sdk.hpp>
namespace plugin
{
class plugin : public plutonium::sdk::plugin
{
public:
~plugin() = default;
std::uint32_t plugin_version() override;
const char* plugin_name() override;
bool is_game_supported(plutonium::sdk::game game) override;
void on_startup(plutonium::sdk::iinterface* interface_ptr, plutonium::sdk::game game) override;
void on_shutdown() override;
plutonium::sdk::iinterface* get_interface();
plutonium::sdk::game get_game();
private:
plutonium::sdk::iinterface* interface_{};
plutonium::sdk::game game_{};
};
plugin* get();
}

View File

@ -1 +1,418 @@
#include <stdinc.hpp>
#include "codsrc/clientscript/clientscript_public.hpp"
#include <dbghelp.h>
namespace game
{
#define QUICK_TO_JSON_FIELD(j, v, membername) j[#membername] = v.membername
#define QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, membername) \
if (v.membername) \
j[#membername] = v.membername; \
else \
j[#membername] = "(NULL)"
#define QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, membername) j[#membername] = reinterpret_cast<size_t>(&v.membername)
#define QUICK_TO_JSON_FIELD_ARRAY(j, v, membername) \
for (auto i = 0; i < ARRAY_COUNT(v.membername); i++) \
{ \
j[#membername][i] = v.membername[i]; \
}
#define QUICK_TO_JSON_FIELD_SL_STRING(j, v, membername) j[#membername "Str"] = SL_ConvertToStringSafe(v.membername, *gInst)
void to_json(nlohmann::json& j, const scrVarPub_t& v)
{
QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, fieldBuffer);
QUICK_TO_JSON_FIELD(j, v, canonicalStrCount);
QUICK_TO_JSON_FIELD(j, v, developer);
QUICK_TO_JSON_FIELD(j, v, developer_script);
QUICK_TO_JSON_FIELD(j, v, evaluate);
QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, error_message);
QUICK_TO_JSON_FIELD(j, v, error_index);
QUICK_TO_JSON_FIELD(j, v, time);
QUICK_TO_JSON_FIELD(j, v, timeArrayId);
QUICK_TO_JSON_FIELD(j, v, pauseArrayId);
QUICK_TO_JSON_FIELD(j, v, levelId);
QUICK_TO_JSON_FIELD(j, v, gameId);
QUICK_TO_JSON_FIELD(j, v, animId);
QUICK_TO_JSON_FIELD(j, v, freeEntList);
QUICK_TO_JSON_FIELD(j, v, tempVariable);
QUICK_TO_JSON_FIELD(j, v, bInited);
QUICK_TO_JSON_FIELD(j, v, savecount);
QUICK_TO_JSON_FIELD(j, v, checksum);
QUICK_TO_JSON_FIELD(j, v, entId);
QUICK_TO_JSON_FIELD(j, v, entFieldName);
QUICK_TO_JSON_FIELD_SL_STRING(j, v, entFieldName);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, programHunkUser);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, programBuffer);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, endScriptBuffer);
QUICK_TO_JSON_FIELD_ARRAY(j, v, saveIdMap);
QUICK_TO_JSON_FIELD_ARRAY(j, v, saveIdMapRev);
}
}
// https://stackoverflow.com/questions/5693192/win32-backtrace-from-c-code
std::string build_code_stack()
{
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
std::string answer{};
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
for( i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
answer += std::format("{}: {} - 0x{:06x}\n", frames - i - 1, symbol->Name, symbol->Address);
}
free( symbol );
return answer;
}
int op_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool op_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
game::OpcodeVM op_history[game::SCRIPT_INSTANCE_MAX][128] = {};
int builtin_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool builtin_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
int builtin_history[game::SCRIPT_INSTANCE_MAX][128] = {};
int codepos_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool codepos_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
const char* codepos_history[game::SCRIPT_INSTANCE_MAX][128] = {};
std::string build_builtin_history(game::scriptInstance_t inst)
{
std::string answer{};
int count = builtin_idx_rolled_over[inst] ? ARRAY_COUNT(builtin_history[inst]) : builtin_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = builtin_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(builtin_history[inst]);
}
// todo, convert to builtin name
answer += std::format("{}\n", builtin_history[inst][idx]);
}
return answer;
}
std::string build_codepos_history(game::scriptInstance_t inst)
{
std::string answer{};
int bufferIndex;
int prevSourcePos;
int col;
char line[1024];
int lineNum;
const char* fileName;
int count = codepos_idx_rolled_over[inst] ? ARRAY_COUNT(codepos_history[inst]) : codepos_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = codepos_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(codepos_history[inst]);
}
bufferIndex = game::Scr_GetSourceBuffer(inst, codepos_history[inst][idx]);
prevSourcePos = game::Scr_GetPrevSourcePos(inst, codepos_history[inst][idx], 0);
lineNum = game::Scr_GetLineInfo(&col, game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].sourceBuf, prevSourcePos, line);
fileName = game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].buf;
answer += std::format("{}({}, {}): '{}'\n", fileName, lineNum, col, line);
}
return answer;
}
std::string build_op_history(game::scriptInstance_t inst)
{
static const char* OpcodeVMToString[] = {
"OP_End",
"OP_Return",
"OP_GetUndefined",
"OP_GetZero",
"OP_GetByte",
"OP_GetNegByte",
"OP_GetUnsignedShort",
"OP_GetNegUnsignedShort",
"OP_GetInteger",
"OP_GetFloat",
"OP_GetString",
"OP_GetIString",
"OP_GetVector",
"OP_GetLevelObject",
"OP_GetAnimObject",
"OP_GetSelf",
"OP_GetLevel",
"OP_GetGame",
"OP_GetAnim",
"OP_GetAnimation",
"OP_GetGameRef",
"OP_GetFunction",
"OP_CreateLocalVariable",
"OP_RemoveLocalVariables",
"OP_EvalLocalVariableCached0",
"OP_EvalLocalVariableCached1",
"OP_EvalLocalVariableCached2",
"OP_EvalLocalVariableCached3",
"OP_EvalLocalVariableCached4",
"OP_EvalLocalVariableCached5",
"OP_EvalLocalVariableCached",
"OP_EvalLocalArrayCached",
"OP_EvalArray",
"OP_EvalLocalArrayRefCached0",
"OP_EvalLocalArrayRefCached",
"OP_EvalArrayRef",
"OP_ClearArray",
"OP_EmptyArray",
"OP_GetSelfObject",
"OP_EvalLevelFieldVariable",
"OP_EvalAnimFieldVariable",
"OP_EvalSelfFieldVariable",
"OP_EvalFieldVariable",
"OP_EvalLevelFieldVariableRef",
"OP_EvalAnimFieldVariableRef",
"OP_EvalSelfFieldVariableRef",
"OP_EvalFieldVariableRef",
"OP_ClearFieldVariable",
"OP_SafeCreateVariableFieldCached",
"OP_SafeSetVariableFieldCached0",
"OP_SafeSetVariableFieldCached",
"OP_SafeSetWaittillVariableFieldCached",
"OP_clearparams",
"OP_checkclearparams",
"OP_EvalLocalVariableRefCached0",
"OP_EvalLocalVariableRefCached",
"OP_SetLevelFieldVariableField",
"OP_SetVariableField",
"OP_SetAnimFieldVariableField",
"OP_SetSelfFieldVariableField",
"OP_SetLocalVariableFieldCached0",
"OP_SetLocalVariableFieldCached",
"OP_CallBuiltin0",
"OP_CallBuiltin1",
"OP_CallBuiltin2",
"OP_CallBuiltin3",
"OP_CallBuiltin4",
"OP_CallBuiltin5",
"OP_CallBuiltin",
"OP_CallBuiltinMethod0",
"OP_CallBuiltinMethod1",
"OP_CallBuiltinMethod2",
"OP_CallBuiltinMethod3",
"OP_CallBuiltinMethod4",
"OP_CallBuiltinMethod5",
"OP_CallBuiltinMethod",
"OP_wait",
"OP_waittillFrameEnd",
"OP_PreScriptCall",
"OP_ScriptFunctionCall2",
"OP_ScriptFunctionCall",
"OP_ScriptFunctionCallPointer",
"OP_ScriptMethodCall",
"OP_ScriptMethodCallPointer",
"OP_ScriptThreadCall",
"OP_ScriptThreadCallPointer",
"OP_ScriptMethodThreadCall",
"OP_ScriptMethodThreadCallPointer",
"OP_DecTop",
"OP_CastFieldObject",
"OP_EvalLocalVariableObjectCached",
"OP_CastBool",
"OP_BoolNot",
"OP_BoolComplement",
"OP_JumpOnFalse",
"OP_JumpOnTrue",
"OP_JumpOnFalseExpr",
"OP_JumpOnTrueExpr",
"OP_jump",
"OP_jumpback",
"OP_inc",
"OP_dec",
"OP_bit_or",
"OP_bit_ex_or",
"OP_bit_and",
"OP_equality",
"OP_inequality",
"OP_less",
"OP_greater",
"OP_less_equal",
"OP_greater_equal",
"OP_shift_left",
"OP_shift_right",
"OP_plus",
"OP_minus",
"OP_multiply",
"OP_divide",
"OP_mod",
"OP_size",
"OP_waittillmatch",
"OP_waittill",
"OP_notify",
"OP_endon",
"OP_voidCodepos",
"OP_switch",
"OP_endswitch",
"OP_vector",
"OP_NOP",
"OP_abort",
"OP_object",
"OP_thread_object",
"OP_EvalLocalVariable",
"OP_EvalLocalVariableRef",
"OP_prof_begin",
"OP_prof_end",
"OP_breakpoint",
"OP_assignmentBreakpoint",
"OP_manualAndAssignmentBreakpoint",
"OP_count"
};
std::string answer{};
int count = op_idx_rolled_over[inst] ? ARRAY_COUNT(op_history[inst]) : op_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = op_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(op_history[inst]);
}
if ((int)op_history[inst][idx] >= 0 && op_history[inst][idx] < game::OP_count)
{
answer += std::format("{}\n", OpcodeVMToString[op_history[inst][idx]]);
}
else
{
answer += std::format("0x{:02x}\n", (int)op_history[inst][idx]);
}
}
return answer;
}
std::string build_gsc_stack(game::scriptInstance_t inst)
{
std::string answer{};
int bufferIndex;
int prevSourcePos;
int col;
char line[1024];
int lineNum;
const char* fileName;
if (!game::gFs[inst].pos || !game::Scr_IsInOpcodeMemory(inst, game::gFs[inst].pos))
{
return answer;
}
for (auto frame = game::gScrVmPub[inst].function_frame_start;; frame++)
{
if (!frame->fs.pos || !game::Scr_IsInOpcodeMemory(inst, frame->fs.pos))
{
break;
}
bufferIndex = game::Scr_GetSourceBuffer(inst, frame->fs.pos - 1);
prevSourcePos = game::Scr_GetPrevSourcePos(inst, frame->fs.pos - 1, 0);
lineNum = game::Scr_GetLineInfo(&col, game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].sourceBuf, prevSourcePos, line);
fileName = game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].buf;
answer += std::format("{}({}, {}): '{}'\n", fileName, lineNum, col, line);
if (frame == game::gScrVmPub[inst].function_frame)
{
break;
}
}
return answer;
}
std::string build_gsc_dump(game::scriptInstance_t inst)
{
nlohmann::json answer{};
auto t = *game::gInst;
*game::gInst = inst;
answer["inst"] = inst;
answer["gScrVarPub"] = game::gScrVarPub[inst];
answer["codeCallStack"] = build_code_stack();
answer["gscCallStack"] = build_gsc_stack(inst);
answer["opHistory"] = build_op_history(inst);
answer["builtinHistory"] = build_builtin_history(inst);
answer["codeposHistory"] = build_codepos_history(inst);
*game::gInst = t;
return answer.dump(2);
}
void push_opcode_history(game::scriptInstance_t inst, game::OpcodeVM op)
{
assert(inst == 0 || inst == 1);
//assert((int)op >= 0 && op < game::OP_count);
op_history[inst][op_idx[inst]++] = op;
if (op_idx[inst] >= ARRAY_COUNT(op_history[inst]))
{
op_idx_rolled_over[inst] = true;
op_idx[inst] = 0;
}
}
void push_builtin_history(game::scriptInstance_t inst, int idx)
{
assert(inst == 0 || inst == 1);
assert(idx >= 0 && idx < 1024);
builtin_history[inst][builtin_idx[inst]++] = idx;
if (builtin_idx[inst] >= ARRAY_COUNT(builtin_history[inst]))
{
builtin_idx_rolled_over[inst] = true;
builtin_idx[inst] = 0;
}
}
void push_codepos_history(game::scriptInstance_t inst, const char* pos)
{
assert(inst == 0 || inst == 1);
assert(game::Scr_IsInOpcodeMemory(inst, pos));
codepos_history[inst][codepos_idx[inst]++] = pos;
if (codepos_idx[inst] >= ARRAY_COUNT(codepos_history[inst]))
{
codepos_idx_rolled_over[inst] = true;
codepos_idx[inst] = 0;
}
}

View File

@ -10,7 +10,6 @@
#pragma warning(disable: 4324)
#pragma warning(disable: 4459)
#pragma warning(disable: 4611)
#pragma warning(disable: 4359)
#pragma warning(error: 4409)
#define DLL_EXPORT extern "C" __declspec(dllexport)
@ -71,12 +70,9 @@
#include "game/structs.hpp"
#include "game/symbols.hpp"
#include "plugin.hpp"
std::string build_gsc_dump(game::scriptInstance_t inst);
void push_opcode_history(game::scriptInstance_t inst, game::OpcodeVM op);
void push_builtin_history(game::scriptInstance_t inst, int idx);
void push_codepos_history(game::scriptInstance_t inst, const char* pos);
void print_ast(game::scriptInstance_t inst, game::sval_u node);
using namespace std::literals;

View File

@ -97,15 +97,8 @@ namespace utils::hook
MH_DisableHook(this->place_);
}
void detour::create(void* place, void* target, bool quick)
void detour::create(void* place, void* target)
{
// each detour is ~30ms to install, quick is for instances where we will NEVER need to invoke the original
if (quick)
{
jump(reinterpret_cast<std::uintptr_t>(place), target);
return;
}
this->clear();
this->place_ = place;
@ -117,9 +110,9 @@ namespace utils::hook
this->enable();
}
void detour::create(const size_t place, void* target, bool quick)
void detour::create(const size_t place, void* target)
{
this->create(reinterpret_cast<void*>(place), target, quick);
this->create(reinterpret_cast<void*>(place), target);
}
void detour::clear()

View File

@ -86,8 +86,8 @@ namespace utils::hook
void enable() const;
void disable() const;
void create(void* place, void* target, bool quick = false);
void create(size_t place, void* target, bool quick = false);
void create(void* place, void* target);
void create(size_t place, void* target);
void clear();
template <typename T>

View File

@ -1,986 +0,0 @@
#include <stdinc.hpp>
#include "codsrc/clientscript/clientscript_public.hpp"
#include <dbghelp.h>
#define QUICK_TO_JSON_FIELD(j, v, membername) j[#membername] = v.membername
#define QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, membername) \
if (v.membername) \
j[#membername] = v.membername; \
else \
j[#membername] = "(NULL)"
#define QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, membername) j[#membername] = reinterpret_cast<size_t>(&v.membername)
#define QUICK_TO_JSON_FIELD_ARRAY(j, v, membername) \
for (auto i = 0; i < ARRAY_COUNT(v.membername); i++) \
{ \
j[#membername][i] = v.membername[i]; \
}
#define QUICK_TO_JSON_FIELD_SL_STRING(j, v, membername) j[#membername "Str"] = SL_ConvertToStringSafe(v.membername, *gInst)
namespace game
{
void to_json(nlohmann::json& j, const scrVarPub_t& v)
{
QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, fieldBuffer);
QUICK_TO_JSON_FIELD(j, v, canonicalStrCount);
QUICK_TO_JSON_FIELD(j, v, developer);
QUICK_TO_JSON_FIELD(j, v, developer_script);
QUICK_TO_JSON_FIELD(j, v, evaluate);
QUICK_TO_JSON_FIELD_SAFE_CSTR(j, v, error_message);
QUICK_TO_JSON_FIELD(j, v, error_index);
QUICK_TO_JSON_FIELD(j, v, time);
QUICK_TO_JSON_FIELD(j, v, timeArrayId);
QUICK_TO_JSON_FIELD(j, v, pauseArrayId);
QUICK_TO_JSON_FIELD(j, v, levelId);
QUICK_TO_JSON_FIELD(j, v, gameId);
QUICK_TO_JSON_FIELD(j, v, animId);
QUICK_TO_JSON_FIELD(j, v, freeEntList);
QUICK_TO_JSON_FIELD(j, v, tempVariable);
QUICK_TO_JSON_FIELD(j, v, bInited);
QUICK_TO_JSON_FIELD(j, v, savecount);
QUICK_TO_JSON_FIELD(j, v, checksum);
QUICK_TO_JSON_FIELD(j, v, entId);
QUICK_TO_JSON_FIELD(j, v, entFieldName);
QUICK_TO_JSON_FIELD_SL_STRING(j, v, entFieldName);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, programHunkUser);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, programBuffer);
QUICK_TO_JSON_FIELD_PTR_ADDR(j, v, endScriptBuffer);
QUICK_TO_JSON_FIELD_ARRAY(j, v, saveIdMap);
QUICK_TO_JSON_FIELD_ARRAY(j, v, saveIdMapRev);
}
}
int op_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool op_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
game::OpcodeVM op_history[game::SCRIPT_INSTANCE_MAX][128] = {};
int builtin_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool builtin_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
int builtin_history[game::SCRIPT_INSTANCE_MAX][128] = {};
int codepos_idx[game::SCRIPT_INSTANCE_MAX] = { 0, 0 };
bool codepos_idx_rolled_over[game::SCRIPT_INSTANCE_MAX] = { false, false };
const char* codepos_history[game::SCRIPT_INSTANCE_MAX][128] = {};
const char* scr_enum_t_to_string[] =
{
"ENUM_NOP",
"ENUM_program",
"ENUM_assignment",
"ENUM_unknown_variable",
"ENUM_duplicate_variable",
"ENUM_local_variable",
"ENUM_local_variable_frozen",
"ENUM_duplicate_expression",
"ENUM_primitive_expression",
"ENUM_integer",
"ENUM_float",
"ENUM_minus_integer",
"ENUM_minus_float",
"ENUM_string",
"ENUM_istring",
"ENUM_array_variable",
"ENUM_unknown_field",
"ENUM_field_variable",
"ENUM_field_variable_frozen",
"ENUM_variable",
"ENUM_function",
"ENUM_call_expression",
"ENUM_local_function",
"ENUM_far_function",
"ENUM_function_pointer",
"ENUM_call",
"ENUM_method",
"ENUM_call_expression_statement",
"ENUM_script_call",
"ENUM_return",
"ENUM_return2",
"ENUM_wait",
"ENUM_script_thread_call",
"ENUM_undefined",
"ENUM_self",
"ENUM_self_frozen",
"ENUM_level",
"ENUM_game",
"ENUM_anim",
"ENUM_if",
"ENUM_if_else",
"ENUM_while",
"ENUM_for",
"ENUM_inc",
"ENUM_dec",
"ENUM_binary_equals",
"ENUM_statement_list",
"ENUM_developer_statement_list",
"ENUM_expression_list",
"ENUM_bool_or",
"ENUM_bool_and",
"ENUM_binary",
"ENUM_bool_not",
"ENUM_bool_complement",
"ENUM_size_field",
"ENUM_self_field",
"ENUM_precachetree",
"ENUM_waittill",
"ENUM_waittillmatch",
"ENUM_waittillFrameEnd",
"ENUM_notify",
"ENUM_endon",
"ENUM_switch",
"ENUM_case",
"ENUM_default",
"ENUM_break",
"ENUM_continue",
"ENUM_expression",
"ENUM_empty_array",
"ENUM_animation",
"ENUM_thread",
"ENUM_begin_developer_thread",
"ENUM_end_developer_thread",
"ENUM_usingtree",
"ENUM_false",
"ENUM_true",
"ENUM_animtree",
"ENUM_breakon",
"ENUM_breakpoint",
"ENUM_prof_begin",
"ENUM_prof_end",
"ENUM_vector",
"ENUM_object",
"ENUM_thread_object",
"ENUM_local",
"ENUM_statement",
"ENUM_bad_expression",
"ENUM_bad_statement",
"ENUM_include",
"ENUM_argument"
};
const char* OpcodeVMToString[] = {
"OP_End",
"OP_Return",
"OP_GetUndefined",
"OP_GetZero",
"OP_GetByte",
"OP_GetNegByte",
"OP_GetUnsignedShort",
"OP_GetNegUnsignedShort",
"OP_GetInteger",
"OP_GetFloat",
"OP_GetString",
"OP_GetIString",
"OP_GetVector",
"OP_GetLevelObject",
"OP_GetAnimObject",
"OP_GetSelf",
"OP_GetLevel",
"OP_GetGame",
"OP_GetAnim",
"OP_GetAnimation",
"OP_GetGameRef",
"OP_GetFunction",
"OP_CreateLocalVariable",
"OP_RemoveLocalVariables",
"OP_EvalLocalVariableCached0",
"OP_EvalLocalVariableCached1",
"OP_EvalLocalVariableCached2",
"OP_EvalLocalVariableCached3",
"OP_EvalLocalVariableCached4",
"OP_EvalLocalVariableCached5",
"OP_EvalLocalVariableCached",
"OP_EvalLocalArrayCached",
"OP_EvalArray",
"OP_EvalLocalArrayRefCached0",
"OP_EvalLocalArrayRefCached",
"OP_EvalArrayRef",
"OP_ClearArray",
"OP_EmptyArray",
"OP_GetSelfObject",
"OP_EvalLevelFieldVariable",
"OP_EvalAnimFieldVariable",
"OP_EvalSelfFieldVariable",
"OP_EvalFieldVariable",
"OP_EvalLevelFieldVariableRef",
"OP_EvalAnimFieldVariableRef",
"OP_EvalSelfFieldVariableRef",
"OP_EvalFieldVariableRef",
"OP_ClearFieldVariable",
"OP_SafeCreateVariableFieldCached",
"OP_SafeSetVariableFieldCached0",
"OP_SafeSetVariableFieldCached",
"OP_SafeSetWaittillVariableFieldCached",
"OP_clearparams",
"OP_checkclearparams",
"OP_EvalLocalVariableRefCached0",
"OP_EvalLocalVariableRefCached",
"OP_SetLevelFieldVariableField",
"OP_SetVariableField",
"OP_SetAnimFieldVariableField",
"OP_SetSelfFieldVariableField",
"OP_SetLocalVariableFieldCached0",
"OP_SetLocalVariableFieldCached",
"OP_CallBuiltin0",
"OP_CallBuiltin1",
"OP_CallBuiltin2",
"OP_CallBuiltin3",
"OP_CallBuiltin4",
"OP_CallBuiltin5",
"OP_CallBuiltin",
"OP_CallBuiltinMethod0",
"OP_CallBuiltinMethod1",
"OP_CallBuiltinMethod2",
"OP_CallBuiltinMethod3",
"OP_CallBuiltinMethod4",
"OP_CallBuiltinMethod5",
"OP_CallBuiltinMethod",
"OP_wait",
"OP_waittillFrameEnd",
"OP_PreScriptCall",
"OP_ScriptFunctionCall2",
"OP_ScriptFunctionCall",
"OP_ScriptFunctionCallPointer",
"OP_ScriptMethodCall",
"OP_ScriptMethodCallPointer",
"OP_ScriptThreadCall",
"OP_ScriptThreadCallPointer",
"OP_ScriptMethodThreadCall",
"OP_ScriptMethodThreadCallPointer",
"OP_DecTop",
"OP_CastFieldObject",
"OP_EvalLocalVariableObjectCached",
"OP_CastBool",
"OP_BoolNot",
"OP_BoolComplement",
"OP_JumpOnFalse",
"OP_JumpOnTrue",
"OP_JumpOnFalseExpr",
"OP_JumpOnTrueExpr",
"OP_jump",
"OP_jumpback",
"OP_inc",
"OP_dec",
"OP_bit_or",
"OP_bit_ex_or",
"OP_bit_and",
"OP_equality",
"OP_inequality",
"OP_less",
"OP_greater",
"OP_less_equal",
"OP_greater_equal",
"OP_shift_left",
"OP_shift_right",
"OP_plus",
"OP_minus",
"OP_multiply",
"OP_divide",
"OP_mod",
"OP_size",
"OP_waittillmatch",
"OP_waittill",
"OP_notify",
"OP_endon",
"OP_voidCodepos",
"OP_switch",
"OP_endswitch",
"OP_vector",
"OP_NOP",
"OP_abort",
"OP_object",
"OP_thread_object",
"OP_EvalLocalVariable",
"OP_EvalLocalVariableRef",
"OP_prof_begin",
"OP_prof_end",
"OP_breakpoint",
"OP_assignmentBreakpoint",
"OP_manualAndAssignmentBreakpoint",
"OP_count"
};
nlohmann::json print_statement_ast(game::scriptInstance_t inst, game::sval_u val)
{
nlohmann::json answer{};
game::sval_u *node;
game::sval_u *start_node;
int i;
answer["type"] = scr_enum_t_to_string[val.node[0].type];
switch (val.node[0].type)
{
case game::ENUM_array_variable:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["index"] = print_statement_ast(inst, val.node[2]);
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["indexSourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_field_variable:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["field"] = game::SL_ConvertToString(val.node[2].stringValue, inst);
answer["sourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_assignment:
answer["lhs"] = print_statement_ast(inst, val.node[1]);
answer["rhs"] = print_statement_ast(inst, val.node[2]);
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["rhsSourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_far_function:
answer["filename"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["threadName"] = game::SL_ConvertToString(val.node[2].stringValue, inst);
answer["sourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_local_function:
answer["threadName"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_function:
case game::ENUM_function_pointer:
answer["func"] = print_statement_ast(inst, val.node[1]);
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_script_call:
answer["func_name"] = print_statement_ast(inst, val.node[1]);
answer["nameSourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_script_thread_call:
answer["func_name"] = print_statement_ast(inst, val.node[1]);
answer["sourcePos"] = val.node[2].sourcePosValue;
answer["nameSourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_call:
answer["func_name"] = print_statement_ast(inst, val.node[1]);
answer["params"] = nlohmann::json::array();
for (i = 0, node = val.node[2].node[0].node;
node;
node = node[1].node, i++)
{
answer["params"][i] = print_statement_ast(inst, node->node[0]);
}
answer["sourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_method:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["func_name"] = print_statement_ast(inst, val.node[2]);
answer["params"] = nlohmann::json::array();
for (i = 0, node = val.node[3].node[0].node;
node;
node = node[1].node, i++)
{
answer["params"][i] = print_statement_ast(inst, node->node[0]);
}
answer["sourcePos"] = val.node[4].sourcePosValue;
answer["methodSourcePos"] = val.node[5].sourcePosValue;
break;
case game::ENUM_integer:
case game::ENUM_minus_integer:
answer["value"] = val.node[1].intValue;
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_float:
case game::ENUM_minus_float:
answer["value"] = val.node[1].floatValue;
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_string:
case game::ENUM_istring:
answer["value"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_expression_list:
answer["exprlist"] = nlohmann::json::array();
for (i = 0, node = val.node[1].node->node;
node;
node = node[1].node, i++)
{
answer["exprlist"][i] = print_statement_ast(inst, *node->node);
}
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_thread:
answer["threadName"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["formalParams"] = nlohmann::json::array();
for (i = 0, node = val.node[2].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["formalParams"][i]["expr_name"] = game::SL_ConvertToString(node->node[0].stringValue, inst);
answer["formalParams"][i]["sourcePos"] = node->node[1].sourcePosValue;
}
answer["statements"] = nlohmann::json::array();
for (i = 0, node = val.node[3].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["statements"][i] = print_statement_ast(inst, *node);
}
answer["sourcePos"] = val.node[4].sourcePosValue;
answer["endSourcePos"] = val.node[5].sourcePosValue;
{
auto stmtblock = &val.node[6].block;
stmtblock = stmtblock;
}
break;
case game::ENUM_usingtree:
answer["string"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["sourcePos"] = val.node[2].sourcePosValue;
answer["sourcePos2"] = val.node[3].sourcePosValue;
break;
case game::ENUM_wait:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["sourcePos"] = val.node[2].sourcePosValue;
answer["waitSourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_developer_statement_list:
answer["list"] = nlohmann::json::array();
for (i = 0, node = val.node[1].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["list"][i] = print_statement_ast(inst, *node);
}
answer["sourcePos"] = val.node[2].sourcePosValue;
{
auto devStatBlock = val.node[3].block;
devStatBlock = devStatBlock;
}
break;
case game::ENUM_statement_list:
answer["list"] = nlohmann::json::array();
for (i = 0, node = val.node[1].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["list"][i] = print_statement_ast(inst, *node);
}
answer["sourcePos"] = val.node[2].sourcePosValue;
answer["sourcePos2"] = val.node[3].sourcePosValue;
break;
case game::ENUM_if:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["stmt"] = print_statement_ast(inst, val.node[2]);
answer["sourcePos"] = val.node[3].sourcePosValue;
{
auto ifStatBlock = val.node[4].block;
ifStatBlock = ifStatBlock;
}
break;
case game::ENUM_if_else:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["stmt1"] = print_statement_ast(inst, val.node[2]);
answer["stmt2"] = print_statement_ast(inst, val.node[3]);
answer["sourcePos"] = val.node[4].sourcePosValue;
answer["elseSourcePos"] = val.node[5].sourcePosValue;
{
auto ifBlock = val.node[6].block;
auto elseBlock = val.node[7].block;
ifBlock = ifBlock;
elseBlock = elseBlock;
}
break;
case game::ENUM_while:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["stmt"] = print_statement_ast(inst, val.node[2]);
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["whileSourcePos"] = val.node[4].sourcePosValue;
{
auto whileStatBlock = val.node[5].block;
whileStatBlock = whileStatBlock;
}
break;
case game::ENUM_for:
answer["stmt1"] = print_statement_ast(inst, val.node[1]);
answer["expr"] = print_statement_ast(inst, val.node[2]);
answer["stmt2"] = print_statement_ast(inst, val.node[3]);
answer["stmt"] = print_statement_ast(inst, val.node[4]);
answer["sourcePos"] = val.node[5].sourcePosValue;
answer["forSourcePos"] = val.node[6].sourcePosValue;
{
auto forStatBlock = val.node[7].block;
auto forStatPostBlock = val.node[8].block;
forStatBlock = forStatBlock;
forStatPostBlock = forStatPostBlock;
}
break;
case game::ENUM_bool_or:
case game::ENUM_bool_and:
answer["expr1"] = print_statement_ast(inst, val.node[1]);
answer["expr2"] = print_statement_ast(inst, val.node[2]);
answer["expr1SourcePos"] = val.node[3].sourcePosValue;
answer["expr2SourcePos"] = val.node[4].sourcePosValue;
answer["sourcePos"] = val.node[5].sourcePosValue;
break;
case game::ENUM_binary:
{
auto expr1 = val.node[1];
auto expr2 = val.node[2];
auto opcode = val.node[3].type;
auto sourcePos = val.node[4].sourcePosValue;
answer["opcode"] = OpcodeVMToString[opcode];
answer["sourcePos"] = sourcePos;
answer["expr1"] = print_statement_ast(inst, expr1);
answer["expr2"] = print_statement_ast(inst, expr2);
break;
}
case game::ENUM_binary_equals:
answer["lhs"] = print_statement_ast(inst, val.node[1]);
answer["rhs"] = print_statement_ast(inst, val.node[2]);
answer["opcode"] = OpcodeVMToString[val.node[3].type];
answer["sourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_endon:
answer["obj"] = print_statement_ast(inst, val.node[1]);
answer["expr"] = print_statement_ast(inst, val.node[2]);
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["exprSourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_notify:
answer["obj"] = print_statement_ast(inst, val.node[1]);
answer["exprlist"] = nlohmann::json::array();
start_node = nullptr;
for (i = 0, node = val.node[2].node->node;
node;
node = node[1].node, i++)
{
start_node = node;
answer["exprlist"][i] = print_statement_ast(inst, *node->node);
}
answer["startNodeSourcePos"] = start_node->node[1].sourcePosValue;
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["notifySourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_waittill:
answer["obj"] = print_statement_ast(inst, val.node[1]);
node = val.node[2].node->node[1].node;
answer["expr"]["expr"] = print_statement_ast(inst, *node->node);
answer["expr"]["sourcePos"] = node->node[1].sourcePosValue;
answer["exprlist"] = nlohmann::json::array();
for (i = 0, node = node[1].node;
node;
node = node[1].node, i++)
{
answer["exprlist"][i]["expr"] = game::SL_ConvertToString(node[0].node->stringValue, inst);
answer["exprlist"][i]["sourcePos"] = node->node[1].sourcePosValue;
}
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["waitSourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_switch:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["stmtlist"] = nlohmann::json::array();
for (i = 0, node = val.node[2].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["stmtlist"][i] = print_statement_ast(inst, *node);
}
answer["sourcePos"] = val.node[3].sourcePosValue;
break;
case game::ENUM_default:
answer["sourcePos"] = val.node[1].sourcePosValue;
{
auto breakBlock = val.node[2].block;
breakBlock = breakBlock;
}
break;
case game::ENUM_case:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["sourcePos"] = val.node[2].sourcePosValue;
{
auto caseBlock = val.node[3].block;
caseBlock = caseBlock;
}
break;
case game::ENUM_waittillmatch:
answer["obj"] = print_statement_ast(inst, val.node[1]);
answer["exprlist"] = nlohmann::json::array();
for (i = 0, node = val.node[2].node->node[1].node;
node;
node = node[1].node, i++)
{
answer["exprlist"][i]["expr"] = print_statement_ast(inst, *node->node);
answer["exprlist"][i]["sourcePos"] = node->node[1].sourcePosValue;
}
answer["sourcePos"] = val.node[3].sourcePosValue;
answer["waitSourcePos"] = val.node[4].sourcePosValue;
break;
case game::ENUM_local_variable:
case game::ENUM_prof_begin:
case game::ENUM_prof_end:
case game::ENUM_animation:
answer["name"] = game::SL_ConvertToString(val.node[1].stringValue, inst);
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_begin_developer_thread:
case game::ENUM_end_developer_thread:
case game::ENUM_undefined:
case game::ENUM_false:
case game::ENUM_true:
case game::ENUM_return2:
case game::ENUM_self:
case game::ENUM_level:
case game::ENUM_game:
case game::ENUM_anim:
case game::ENUM_empty_array:
case game::ENUM_waittillFrameEnd:
case game::ENUM_break:
case game::ENUM_continue:
case game::ENUM_animtree:
case game::ENUM_breakpoint:
answer["sourcePos"] = val.node[1].sourcePosValue;
break;
case game::ENUM_duplicate_variable:
case game::ENUM_duplicate_expression:
case game::ENUM_call_expression:
case game::ENUM_call_expression_statement:
case game::ENUM_expression:
case game::ENUM_statement:
answer["expr"] = print_statement_ast(inst, val.node[1]);
break;
case game::ENUM_variable:
case game::ENUM_primitive_expression:
case game::ENUM_return:
case game::ENUM_inc:
case game::ENUM_dec:
case game::ENUM_bool_not:
case game::ENUM_bool_complement:
case game::ENUM_size_field:
answer["expr"] = print_statement_ast(inst, val.node[1]);
answer["sourcePos"] = val.node[2].sourcePosValue;
break;
case game::ENUM_NOP:
case game::ENUM_program: // unk
case game::ENUM_unknown_variable: // unk
case game::ENUM_local_variable_frozen: // unk, debugger?
case game::ENUM_unknown_field: // unk
case game::ENUM_field_variable_frozen: // unk, debugger?
case game::ENUM_self_frozen: // unk, debugger?
case game::ENUM_include: // handled
case game::ENUM_self_field: // debugger
case game::ENUM_object: // debugger
case game::ENUM_precachetree: // unk
case game::ENUM_local: // unk
case game::ENUM_bad_expression: // unk
case game::ENUM_bad_statement: // unk
case game::ENUM_argument: // unk
case game::ENUM_thread_object: // unk
case game::ENUM_vector: // unk
case game::ENUM_breakon: // debugger unk 2 vals 1 pos
default:
break;
}
return answer;
}
void print_ast(game::scriptInstance_t inst, game::sval_u val)
{
nlohmann::json answer{};
game::sval_u* node;
int i;
answer["filename"] = game::gScrParserPub[inst].scriptfilename;
// this is the include list
answer["includes"] = nlohmann::json::array();
for ( i = 0, node = val.node[0].node->node[1].node;
node;
node = node[1].node, i++ )
{
answer["includes"][i]["type"] = scr_enum_t_to_string[node->node[0].type];
answer["includes"][i]["filename"] = game::SL_ConvertToString(node->node[1].stringValue, inst);
answer["includes"][i]["sourcePos"] = node->node[2].sourcePosValue;
}
// this is the thread list
answer["threads"] = nlohmann::json::array();
for ( i = 0, node = val.node[1].node->node[1].node;
node;
node = node[1].node, i++ )
{
answer["threads"][i] = print_statement_ast(inst, *node);
}
utils::io::write_file(std::format("t4sp-server-plugin/ast-{}.json", game::gScrParserPub[inst].scriptfilename), answer.dump(2));
}
// https://stackoverflow.com/questions/5693192/win32-backtrace-from-c-code
std::string build_code_stack()
{
unsigned int i;
void * stack[ 100 ];
unsigned short frames;
SYMBOL_INFO * symbol;
HANDLE process;
std::string answer{};
process = GetCurrentProcess();
SymInitialize( process, NULL, TRUE );
frames = CaptureStackBackTrace( 0, 100, stack, NULL );
symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 );
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
for( i = 0; i < frames; i++ )
{
SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol );
answer += std::format("{}: {} - 0x{:06x}\n", frames - i - 1, symbol->Name, symbol->Address);
}
free( symbol );
return answer;
}
std::string build_builtin_history(game::scriptInstance_t inst)
{
std::string answer{};
int count = builtin_idx_rolled_over[inst] ? ARRAY_COUNT(builtin_history[inst]) : builtin_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = builtin_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(builtin_history[inst]);
}
// todo, convert to builtin name
answer += std::format("{}\n", builtin_history[inst][idx]);
}
return answer;
}
std::string build_codepos_history(game::scriptInstance_t inst)
{
std::string answer{};
int bufferIndex;
int prevSourcePos;
int col;
char line[1024];
int lineNum;
const char* fileName;
int count = codepos_idx_rolled_over[inst] ? ARRAY_COUNT(codepos_history[inst]) : codepos_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = codepos_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(codepos_history[inst]);
}
bufferIndex = game::Scr_GetSourceBuffer(inst, codepos_history[inst][idx]);
prevSourcePos = game::Scr_GetPrevSourcePos(inst, codepos_history[inst][idx], 0);
lineNum = game::Scr_GetLineInfo(&col, game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].sourceBuf, prevSourcePos, line);
fileName = game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].buf;
answer += std::format("{}({}, {}): '{}'\n", fileName, lineNum, col, line);
}
return answer;
}
std::string build_op_history(game::scriptInstance_t inst)
{
std::string answer{};
int count = op_idx_rolled_over[inst] ? ARRAY_COUNT(op_history[inst]) : op_idx[inst];
for (auto i = 0; i < count; i++)
{
auto idx = op_idx[inst] - 1 - i;
if (idx < 0)
{
idx += ARRAY_COUNT(op_history[inst]);
}
if ((int)op_history[inst][idx] >= 0 && op_history[inst][idx] < game::OP_count)
{
answer += std::format("{}\n", OpcodeVMToString[op_history[inst][idx]]);
}
else
{
answer += std::format("0x{:02x}\n", (int)op_history[inst][idx]);
}
}
return answer;
}
std::string build_gsc_stack(game::scriptInstance_t inst)
{
std::string answer{};
int bufferIndex;
int prevSourcePos;
int col;
char line[1024];
int lineNum;
const char* fileName;
if (!game::gFs[inst].pos || !game::Scr_IsInOpcodeMemory(inst, game::gFs[inst].pos))
{
return answer;
}
for (auto frame = game::gScrVmPub[inst].function_frame_start;; frame++)
{
if (!frame->fs.pos || !game::Scr_IsInOpcodeMemory(inst, frame->fs.pos))
{
break;
}
bufferIndex = game::Scr_GetSourceBuffer(inst, frame->fs.pos - 1);
prevSourcePos = game::Scr_GetPrevSourcePos(inst, frame->fs.pos - 1, 0);
lineNum = game::Scr_GetLineInfo(&col, game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].sourceBuf, prevSourcePos, line);
fileName = game::gScrParserPub[inst].sourceBufferLookup[bufferIndex].buf;
answer += std::format("{}({}, {}): '{}'\n", fileName, lineNum, col, line);
if (frame == game::gScrVmPub[inst].function_frame)
{
break;
}
}
return answer;
}
std::string build_gsc_dump(game::scriptInstance_t inst)
{
nlohmann::json answer{};
auto t = *game::gInst;
*game::gInst = inst;
answer["inst"] = inst;
answer["gScrVarPub"] = game::gScrVarPub[inst];
answer["codeCallStack"] = build_code_stack();
answer["gscCallStack"] = build_gsc_stack(inst);
answer["opHistory"] = build_op_history(inst);
answer["builtinHistory"] = build_builtin_history(inst);
answer["codeposHistory"] = build_codepos_history(inst);
*game::gInst = t;
return answer.dump(2);
}
void push_opcode_history(game::scriptInstance_t inst, game::OpcodeVM op)
{
assert(inst == 0 || inst == 1);
//assert((int)op >= 0 && op < game::OP_count);
op_history[inst][op_idx[inst]++] = op;
if (op_idx[inst] >= ARRAY_COUNT(op_history[inst]))
{
op_idx_rolled_over[inst] = true;
op_idx[inst] = 0;
}
}
void push_builtin_history(game::scriptInstance_t inst, int idx)
{
assert(inst == 0 || inst == 1);
assert(idx >= 0 && idx < 1024);
builtin_history[inst][builtin_idx[inst]++] = idx;
if (builtin_idx[inst] >= ARRAY_COUNT(builtin_history[inst]))
{
builtin_idx_rolled_over[inst] = true;
builtin_idx[inst] = 0;
}
}
void push_codepos_history(game::scriptInstance_t inst, const char* pos)
{
assert(inst == 0 || inst == 1);
assert(game::Scr_IsInOpcodeMemory(inst, pos));
codepos_history[inst][codepos_idx[inst]++] = pos;
if (codepos_idx[inst] >= ARRAY_COUNT(codepos_history[inst]))
{
codepos_idx_rolled_over[inst] = true;
codepos_idx[inst] = 0;
}
}