Script stuff
This commit is contained in:
parent
b3aacf8731
commit
0a0d6ae5e6
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit ed87c1fe2c6e1633cadb62cf54b2723b2b25c280
|
||||
Subproject commit 40ff94ebef494e2e16107ce2965215ae67c031c1
|
@ -20,6 +20,7 @@ namespace Components
|
||||
Loader::Register(new Colors());
|
||||
Loader::Register(new D3D9Ex());
|
||||
Loader::Register(new Logger());
|
||||
Loader::Register(new Script());
|
||||
Loader::Register(new Weapon());
|
||||
Loader::Register(new Window());
|
||||
Loader::Register(new Command());
|
||||
|
@ -32,6 +32,7 @@ namespace Components
|
||||
#include "Modules\Colors.hpp"
|
||||
#include "Modules\D3D9Ex.hpp"
|
||||
#include "Modules\Logger.hpp"
|
||||
#include "Modules\Script.hpp"
|
||||
#include "Modules\Weapon.hpp"
|
||||
#include "Modules\Window.hpp"
|
||||
#include "Modules\Command.hpp"
|
||||
|
@ -20,7 +20,6 @@ namespace Assets
|
||||
{
|
||||
if (asset->materials[i])
|
||||
{
|
||||
//Components::Logger::Print("%s\n", asset->materials[i]->name);
|
||||
builder->LoadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materials[i]->name);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace Components
|
||||
return i;
|
||||
}
|
||||
|
||||
Game::script_t* Menus::LoadMenuScript(std::string name, std::string buffer)
|
||||
Game::script_t* Menus::LoadMenuScript(std::string name, std::string& buffer)
|
||||
{
|
||||
Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length());
|
||||
|
||||
@ -52,7 +52,7 @@ namespace Components
|
||||
return script;
|
||||
}
|
||||
|
||||
int Menus::LoadMenuSource(std::string name, std::string buffer)
|
||||
int Menus::LoadMenuSource(std::string name, std::string& buffer)
|
||||
{
|
||||
int handle = Menus::ReserveSourceHandle();
|
||||
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!
|
||||
|
@ -27,8 +27,8 @@ namespace Components
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef);
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(std::string file);
|
||||
|
||||
static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
|
||||
static int LoadMenuSource(std::string name, std::string buffer);
|
||||
static Game::script_t* LoadMenuScript(std::string name, std::string& buffer);
|
||||
static int LoadMenuSource(std::string name, std::string& buffer);
|
||||
|
||||
static int ReserveSourceHandle();
|
||||
static bool IsValidSourceHandle(int handle);
|
||||
|
255
src/Components/Modules/Script.cpp
Normal file
255
src/Components/Modules/Script.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::string Script::ScriptName;
|
||||
std::vector<int> Script::ScriptHandles;
|
||||
std::vector<std::string> Script::ScriptNameStack;
|
||||
unsigned short Script::FunctionName;
|
||||
|
||||
void Script::FunctionError()
|
||||
{
|
||||
std::string funcName = Game::SL_ConvertToString(Script::FunctionName);
|
||||
|
||||
Game::Com_Printf(23, "\n");
|
||||
Game::Com_Printf(23, "******* script compile error *******\n");
|
||||
Game::Com_Printf(23, "Error: unknown function %s in %s\n", funcName.data(), Script::ScriptName.data());
|
||||
Game::Com_Printf(23, "************************************\n");
|
||||
|
||||
Game::Com_Error(5, "script compile error\nunknown function %s\n%s\n", funcName.data(), Script::ScriptName.data());
|
||||
}
|
||||
|
||||
void __declspec(naked) Script::StoreFunctionNameStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp - 8h]
|
||||
mov Script::FunctionName, ax
|
||||
|
||||
sub esp, 0Ch
|
||||
push 0
|
||||
push edi
|
||||
|
||||
mov eax, 612DB6h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
void Script::StoreScriptName(const char* name)
|
||||
{
|
||||
Script::ScriptNameStack.push_back(Script::ScriptName);
|
||||
Script::ScriptName = name;
|
||||
|
||||
if (!Utils::EndsWith(Script::ScriptName, ".gsc"))
|
||||
{
|
||||
Script::ScriptName.append(".gsc");
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) Script::StoreScriptNameStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
lea ecx, [esp + 10h]
|
||||
push ecx
|
||||
|
||||
call Script::StoreScriptName
|
||||
add esp, 4h
|
||||
|
||||
push ebp
|
||||
mov ebp, ds:1CDEAA8h
|
||||
mov ecx, 427DC3h
|
||||
jmp ecx
|
||||
}
|
||||
}
|
||||
|
||||
void Script::RestoreScriptName()
|
||||
{
|
||||
Script::ScriptName = Script::ScriptNameStack.back();
|
||||
Script::ScriptNameStack.pop_back();
|
||||
}
|
||||
|
||||
void __declspec(naked) Script::RestoreScriptNameStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
call Script::RestoreScriptName
|
||||
|
||||
mov ds:1CDEAA8h, ebp
|
||||
|
||||
mov eax, 427E77h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Optimize that!
|
||||
void Script::PrintSourcePos(const char* filename, int offset)
|
||||
{
|
||||
int line = 0;
|
||||
int inLineOffset = 0;
|
||||
char* scriptFile = 0;
|
||||
char* currentLine = 0;
|
||||
bool freeScript = false;
|
||||
|
||||
if (Game::FS_ReadFile(filename, &scriptFile) > -1)
|
||||
{
|
||||
int globalOffset = 0;
|
||||
|
||||
freeScript = true;
|
||||
|
||||
for (char* c = scriptFile; *c != '\0'; c++)
|
||||
{
|
||||
if (!currentLine || *c == '\n')
|
||||
{
|
||||
line++;
|
||||
inLineOffset = 0;
|
||||
currentLine = c;
|
||||
}
|
||||
|
||||
if (globalOffset == offset)
|
||||
{
|
||||
while (*c != '\r' && *c != '\n' && c != '\0')
|
||||
{
|
||||
c++;
|
||||
}
|
||||
|
||||
*c = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
if (*c == '\t')
|
||||
{
|
||||
*c = ' ';
|
||||
}
|
||||
|
||||
globalOffset++;
|
||||
inLineOffset++;
|
||||
}
|
||||
}
|
||||
|
||||
Game::Com_Printf(23, "in file %s, line %d:", filename, line);
|
||||
|
||||
if (currentLine)
|
||||
{
|
||||
Game::Com_Printf(23, "%s\n", currentLine);
|
||||
|
||||
for (int i = 0; i < (inLineOffset - 1); i++)
|
||||
{
|
||||
Game::Com_Printf(23, " ");
|
||||
}
|
||||
|
||||
Game::Com_Printf(23, "*\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Game::Com_Printf(23, "\n");
|
||||
}
|
||||
|
||||
if (freeScript)
|
||||
{
|
||||
Game::FS_FreeFile(scriptFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Script::CompileError(int offset, const char* message, ...)
|
||||
{
|
||||
char msgbuf[1024] = { 0 };
|
||||
va_list v;
|
||||
va_start(v, message);
|
||||
_vsnprintf(msgbuf, sizeof(msgbuf), message, v);
|
||||
va_end(v);
|
||||
|
||||
Game::Scr_ShutdownAllocNode();
|
||||
|
||||
Game::Com_Printf(23, "\n");
|
||||
Game::Com_Printf(23, "******* script compile error *******\n");
|
||||
Game::Com_Printf(23, "Error: %s ", msgbuf);
|
||||
Script::PrintSourcePos(Script::ScriptName.data(), offset);
|
||||
Game::Com_Printf(23, "************************************\n");
|
||||
|
||||
Game::Com_Error(5, "script compile error\n%s\n%s\n(see console for actual details)\n", msgbuf, Script::ScriptName.data());
|
||||
}
|
||||
|
||||
int Script::LoadScriptAndLabel(std::string script, std::string label)
|
||||
{
|
||||
Logger::Print("Loading script %s.gsc...\n", script.data());
|
||||
|
||||
if (!Game::Scr_LoadScript(script.data()))
|
||||
{
|
||||
Logger::Print("Script %s encountered an error while loading. (doesn't exist?)", script.data());
|
||||
Game::Com_Error(1, (char*)0x70B810, script.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Script %s.gsc loaded successfully.\n", script.data());
|
||||
}
|
||||
|
||||
Logger::Print("Finding script handle %s::%s...\n", script.data(), label.data());
|
||||
int handle = Game::Scr_GetFunctionHandle(script.data(), label.data());
|
||||
if (handle)
|
||||
{
|
||||
Logger::Print("Script handle %s::%s loaded successfully.\n", script.data(), label.data());
|
||||
return handle;
|
||||
}
|
||||
|
||||
Logger::Print("Script handle %s::%s couldn't be loaded. (file with no entry point?)\n", script.data(), label.data());
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Script::LoadGameType()
|
||||
{
|
||||
for (auto handle : Script::ScriptHandles)
|
||||
{
|
||||
Game::Scr_FreeThread(Game::Scr_ExecThread(handle, 0));
|
||||
}
|
||||
|
||||
Game::Scr_LoadGameType();
|
||||
}
|
||||
|
||||
void Script::LoadGameTypeScript()
|
||||
{
|
||||
Script::ScriptHandles.clear();
|
||||
|
||||
auto list = FileSystem::GetFileList("scripts/", "gsc");
|
||||
|
||||
for (auto file : list)
|
||||
{
|
||||
file = "scripts/" + file;
|
||||
|
||||
if (Utils::EndsWith(file, ".gsc"))
|
||||
{
|
||||
file = file.substr(0, file.size() - 4);
|
||||
}
|
||||
|
||||
int handle = Script::LoadScriptAndLabel(file, "init");
|
||||
|
||||
if (handle)
|
||||
{
|
||||
Script::ScriptHandles.push_back(handle);
|
||||
}
|
||||
}
|
||||
|
||||
Game::GScr_LoadGameTypeScript();
|
||||
}
|
||||
|
||||
Script::Script()
|
||||
{
|
||||
Utils::Hook(0x612DB0, Script::StoreFunctionNameStub, HOOK_JUMP).Install()->Quick();
|
||||
Utils::Hook(0x427E71, Script::RestoreScriptNameStub, HOOK_JUMP).Install()->Quick();
|
||||
Utils::Hook(0x427DBC, Script::StoreScriptNameStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
Utils::Hook(0x612E8D, Script::FunctionError, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x612EA2, Script::FunctionError, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x434260, Script::CompileError, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
Utils::Hook(0x48EFFE, Script::LoadGameType, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x45D44A, Script::LoadGameTypeScript, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
|
||||
Script::~Script()
|
||||
{
|
||||
Script::ScriptName.clear();
|
||||
Script::ScriptHandles.clear();
|
||||
Script::ScriptNameStack.clear();
|
||||
}
|
||||
}
|
33
src/Components/Modules/Script.hpp
Normal file
33
src/Components/Modules/Script.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
namespace Components
|
||||
{
|
||||
class Script : public Component
|
||||
{
|
||||
public:
|
||||
Script();
|
||||
~Script();
|
||||
const char* GetName() { return "Script"; };
|
||||
|
||||
static int LoadScriptAndLabel(std::string script, std::string label);
|
||||
|
||||
private:
|
||||
static std::string ScriptName;
|
||||
static std::vector<int> ScriptHandles;
|
||||
static std::vector<std::string> ScriptNameStack;
|
||||
static unsigned short FunctionName;
|
||||
|
||||
static void CompileError(int offset, const char* message, ...);
|
||||
static void PrintSourcePos(const char* filename, int offset);
|
||||
|
||||
static void FunctionError();
|
||||
static void StoreFunctionNameStub();
|
||||
|
||||
static void StoreScriptName(const char* name);
|
||||
static void StoreScriptNameStub();
|
||||
|
||||
static void RestoreScriptName();
|
||||
static void RestoreScriptNameStub();
|
||||
|
||||
static void LoadGameType();
|
||||
static void LoadGameTypeScript();
|
||||
};
|
||||
}
|
@ -66,6 +66,8 @@ namespace Game
|
||||
FS_Restart_t FS_Restart = (FS_Restart_t)0x461A50;
|
||||
FS_BuildPathToFile_t FS_BuildPathToFile = (FS_BuildPathToFile_t)0x4702C0;
|
||||
|
||||
GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript = (GScr_LoadGameTypeScript_t)0x4ED9A0;
|
||||
|
||||
Image_LoadFromFileWithReader_t Image_LoadFromFileWithReader = (Image_LoadFromFileWithReader_t)0x53ABF0;
|
||||
Image_Release_t Image_Release = (Image_Release_t)0x51F010;
|
||||
|
||||
@ -103,8 +105,6 @@ namespace Game
|
||||
LocalizeString_t LocalizeString = (LocalizeString_t)0x4FB010;
|
||||
LocalizeMapString_t LocalizeMapString = (LocalizeMapString_t)0x44BB30;
|
||||
|
||||
SE_Load_t SE_Load = (SE_Load_t)0x502A30;
|
||||
|
||||
PC_ReadToken_t PC_ReadToken = (PC_ReadToken_t)0x4ACCD0;
|
||||
PC_ReadTokenHandle_t PC_ReadTokenHandle = (PC_ReadTokenHandle_t)0x4D2060;
|
||||
PC_SourceError_t PC_SourceError = (PC_SourceError_t)0x467A00;
|
||||
@ -120,11 +120,23 @@ namespace Game
|
||||
R_LoadGraphicsAssets_t R_LoadGraphicsAssets = (R_LoadGraphicsAssets_t)0x506AC0;
|
||||
R_TextWidth_t R_TextWidth = (R_TextWidth_t)0x5056C0;
|
||||
R_TextHeight_t R_TextHeight = (R_TextHeight_t)0x505770;
|
||||
|
||||
Scr_LoadGameType_t Scr_LoadGameType = (Scr_LoadGameType_t)0x4D9520;
|
||||
|
||||
Scr_LoadScript_t Scr_LoadScript = (Scr_LoadScript_t)0x45D940;
|
||||
Scr_GetFunctionHandle_t Scr_GetFunctionHandle = (Scr_GetFunctionHandle_t)0x4234F0;
|
||||
|
||||
Scr_ExecThread_t Scr_ExecThread = (Scr_ExecThread_t)0x4AD0B0;
|
||||
Scr_FreeThread_t Scr_FreeThread = (Scr_FreeThread_t)0x4BD320;
|
||||
|
||||
Scr_ShutdownAllocNode_t Scr_ShutdownAllocNode = (Scr_ShutdownAllocNode_t)0x441650;
|
||||
|
||||
Script_Alloc_t Script_Alloc = (Script_Alloc_t)0x422E70;
|
||||
Script_SetupTokens_t Script_SetupTokens = (Script_SetupTokens_t)0x4E6950;
|
||||
Script_CleanString_t Script_CleanString = (Script_CleanString_t)0x498220;
|
||||
|
||||
SE_Load_t SE_Load = (SE_Load_t)0x502A30;
|
||||
|
||||
SetConsole_t SetConsole = (SetConsole_t)0x44F060;
|
||||
|
||||
SL_ConvertToString_t SL_ConvertToString = (SL_ConvertToString_t)0x4EC1D0;
|
||||
|
@ -154,6 +154,9 @@ namespace Game
|
||||
typedef int(__cdecl * FS_BuildPathToFile_t)(const char*, const char*, const char*, char**);
|
||||
extern FS_BuildPathToFile_t FS_BuildPathToFile;
|
||||
|
||||
typedef void(__cdecl * GScr_LoadGameTypeScript_t)();
|
||||
extern GScr_LoadGameTypeScript_t GScr_LoadGameTypeScript;
|
||||
|
||||
typedef int(__cdecl * Reader_t)(char const*, int *);
|
||||
typedef bool(__cdecl * Image_LoadFromFileWithReader_t)(GfxImage* image, Reader_t reader);
|
||||
extern Image_LoadFromFileWithReader_t Image_LoadFromFileWithReader;
|
||||
@ -245,9 +248,6 @@ namespace Game
|
||||
typedef char* (__cdecl * LocalizeMapString_t)(char*);
|
||||
extern LocalizeMapString_t LocalizeMapString;
|
||||
|
||||
typedef char* (__cdecl * SE_Load_t)(char* file, int Unk);
|
||||
extern SE_Load_t SE_Load;
|
||||
|
||||
typedef int(__cdecl * PC_ReadToken_t)(source_t*, token_t*);
|
||||
extern PC_ReadToken_t PC_ReadToken;
|
||||
|
||||
@ -287,6 +287,24 @@ namespace Game
|
||||
typedef int(__cdecl * R_TextHeight_t)(Font* font);
|
||||
extern R_TextHeight_t R_TextHeight;
|
||||
|
||||
typedef void(__cdecl * Scr_ShutdownAllocNode_t)();
|
||||
extern Scr_ShutdownAllocNode_t Scr_ShutdownAllocNode;
|
||||
|
||||
typedef int(__cdecl * Scr_LoadGameType_t)();
|
||||
extern Scr_LoadGameType_t Scr_LoadGameType;
|
||||
|
||||
typedef int(__cdecl * Scr_LoadScript_t)(const char*);
|
||||
extern Scr_LoadScript_t Scr_LoadScript;
|
||||
|
||||
typedef int(__cdecl * Scr_GetFunctionHandle_t)(const char*, const char*);
|
||||
extern Scr_GetFunctionHandle_t Scr_GetFunctionHandle;
|
||||
|
||||
typedef int(__cdecl * Scr_ExecThread_t)(int, int);
|
||||
extern Scr_ExecThread_t Scr_ExecThread;
|
||||
|
||||
typedef int(__cdecl * Scr_FreeThread_t)(int);
|
||||
extern Scr_FreeThread_t Scr_FreeThread;
|
||||
|
||||
typedef script_t* (__cdecl * Script_Alloc_t)(int length);
|
||||
extern Script_Alloc_t Script_Alloc;
|
||||
|
||||
@ -296,6 +314,9 @@ namespace Game
|
||||
typedef int(__cdecl * Script_CleanString_t)(char* buffer);
|
||||
extern Script_CleanString_t Script_CleanString;
|
||||
|
||||
typedef char* (__cdecl * SE_Load_t)(char* file, int Unk);
|
||||
extern SE_Load_t SE_Load;
|
||||
|
||||
typedef void(__cdecl * SetConsole_t)(const char* cvar, const char* value);
|
||||
extern SetConsole_t SetConsole;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user