[Script] Refactor loading code & add pseudo int64 (#419)

This commit is contained in:
Edo 2022-08-23 09:12:20 +02:00 committed by GitHub
parent c0433ce883
commit 3246ed1bf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 158 additions and 59 deletions

View File

@ -24,10 +24,10 @@ namespace Components
Game::SafeArea Console::OriginalSafeArea; Game::SafeArea Console::OriginalSafeArea;
char** Console::GetAutoCompleteFileList(const char* path, const char* extension, Game::FsListBehavior_e behavior, int* numfiles, int allocTrackType) const char** Console::GetAutoCompleteFileList(const char* path, const char* extension, Game::FsListBehavior_e behavior, int* numfiles, int allocTrackType)
{ {
if (path == reinterpret_cast<char*>(0xBAADF00D) || path == reinterpret_cast<char*>(0xCDCDCDCD) || ::Utils::Memory::IsBadReadPtr(path)) return nullptr; if (path == reinterpret_cast<char*>(0xBAADF00D) || path == reinterpret_cast<char*>(0xCDCDCDCD) || ::Utils::Memory::IsBadReadPtr(path)) return nullptr;
return Game::FS_GetFileList(path, extension, behavior, numfiles, allocTrackType); return Game::FS_ListFiles(path, extension, behavior, numfiles, allocTrackType);
} }
void Console::RefreshStatus() void Console::RefreshStatus()

View File

@ -63,7 +63,7 @@ namespace Components
static void StoreSafeArea(); static void StoreSafeArea();
static void RestoreSafeArea(); static void RestoreSafeArea();
static char** GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType); static const char** GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType);
static void Con_ToggleConsole(); static void Con_ToggleConsole();
static void AddConsoleCommand(); static void AddConsoleCommand();

View File

@ -160,8 +160,8 @@ namespace Components
{ {
std::vector<std::string> fileList; std::vector<std::string> fileList;
int numFiles = 0; auto numFiles = 0;
char** files = Game::FS_GetFileList(path.data(), extension.data(), Game::FS_LIST_PURE_ONLY, &numFiles, 0); const auto** files = Game::FS_ListFiles(path.data(), extension.data(), Game::FS_LIST_PURE_ONLY, &numFiles, 10);
if (files) if (files)
{ {
@ -169,11 +169,11 @@ namespace Components
{ {
if (files[i]) if (files[i])
{ {
fileList.push_back(files[i]); fileList.emplace_back(files[i]);
} }
} }
Game::FS_FreeFileList(files); Game::FS_FreeFileList(files, 10);
} }
return fileList; return fileList;
@ -183,8 +183,8 @@ namespace Components
{ {
std::vector<std::string> fileList; std::vector<std::string> fileList;
int numFiles = 0; auto numFiles = 0;
char** files = Game::Sys_ListFiles(path.data(), extension.data(), nullptr, &numFiles, folders); const auto** files = Game::Sys_ListFiles(path.data(), extension.data(), nullptr, &numFiles, folders);
if (files) if (files)
{ {
@ -192,7 +192,7 @@ namespace Components
{ {
if (files[i]) if (files[i])
{ {
fileList.push_back(files[i]); fileList.emplace_back(files[i]);
} }
} }
@ -204,7 +204,7 @@ namespace Components
bool FileSystem::_DeleteFile(const std::string& folder, const std::string& file) bool FileSystem::_DeleteFile(const std::string& folder, const std::string& file)
{ {
char path[MAX_PATH] = { 0 }; char path[MAX_PATH] = {0};
Game::FS_BuildPathToFile(Dvar::Var("fs_basepath").get<const char*>(), reinterpret_cast<char*>(0x63D0BB8), Utils::String::VA("%s/%s", folder.data(), file.data()), reinterpret_cast<char**>(&path)); Game::FS_BuildPathToFile(Dvar::Var("fs_basepath").get<const char*>(), reinterpret_cast<char*>(0x63D0BB8), Utils::String::VA("%s/%s", folder.data(), file.data()), reinterpret_cast<char**>(&path));
return Game::FS_Remove(path); return Game::FS_Remove(path);
} }

View File

@ -1,5 +1,6 @@
#include <STDInclude.hpp> #include <STDInclude.hpp>
#include "Int64.hpp"
#include "IO.hpp" #include "IO.hpp"
#include "Script.hpp" #include "Script.hpp"
#include "ScriptExtension.hpp" #include "ScriptExtension.hpp"
@ -9,6 +10,7 @@ namespace Components
{ {
GSC::GSC() GSC::GSC()
{ {
Loader::Register(new Int64());
Loader::Register(new IO()); Loader::Register(new IO());
Loader::Register(new Script()); Loader::Register(new Script());
Loader::Register(new ScriptExtension()); Loader::Register(new ScriptExtension());

View File

@ -0,0 +1,95 @@
#include <STDInclude.hpp>
#include "Int64.hpp"
#include "Script.hpp"
#define INT64_OPERATION(expr) [](const std::int64_t a, [[maybe_unused]] const std::int64_t b) { return expr; }
namespace Components
{
std::unordered_map<std::string, Int64::int64_OP> Int64::Operations =
{
{"+", INT64_OPERATION(a + b)},
{"-", INT64_OPERATION(a - b)},
{"*", INT64_OPERATION(a * b)},
{"/", INT64_OPERATION(a / b)},
{"&", INT64_OPERATION(a & b)},
{"^", INT64_OPERATION(a ^ b)},
{"|", INT64_OPERATION(a | b)},
{"~", INT64_OPERATION(~a)},
{"%", INT64_OPERATION(a % b)},
{">>", INT64_OPERATION(a >> b)},
{"<<", INT64_OPERATION(a << b)},
{"++", INT64_OPERATION(a + 1)},
{"--", INT64_OPERATION(a - 1)},
};
std::unordered_map<std::string, Int64::int64_Comp> Int64::Comparisons
{
{">", INT64_OPERATION(a > b)},
{">=", INT64_OPERATION(a >= b)},
{"==", INT64_OPERATION(a == b)},
{"<=", INT64_OPERATION(a <= b)},
{"<", INT64_OPERATION(a < b)},
};
std::int64_t Int64::GetInt64Arg(unsigned int index, bool optional)
{
if ((optional) && (index >= Game::Scr_GetNumParam()))
{
return 0;
}
if (Game::Scr_GetType(index) == Game::VAR_INTEGER)
{
return Game::Scr_GetInt(index);
}
if (Game::Scr_GetType(index) == Game::VAR_STRING)
{
return std::strtoll(Game::Scr_GetString(index), nullptr, 0);
}
Game::Scr_ParamError(index, Utils::String::VA("cannot cast %s to int64", Game::Scr_GetTypeName(index)));
return 0;
}
void Int64::AddFunctions()
{
Script::AddFunction("Int64IsInt", []
{
const auto value = GetInt64Arg(0, false);
Game::Scr_AddBool(value <= std::numeric_limits<std::int32_t>::max() && value >= std::numeric_limits<std::int32_t>::min());
});
Script::AddFunction("Int64ToInt", []
{
Game::Scr_AddInt(static_cast<std::int32_t>(GetInt64Arg(0, false)));
});
Script::AddFunction("Int64OP", []
{
const auto a = GetInt64Arg(0, false);
const auto* op = Game::Scr_GetString(1);
const auto b = GetInt64Arg(2, true);
if (const auto got = Operations.find(op); got != Operations.end())
{
Game::Scr_AddString(Utils::String::VA("%lld", got->second(a, b)));
return;
}
if (const auto got = Comparisons.find(op); got != Comparisons.end())
{
Game::Scr_AddBool(got->second(a, b));
return;
}
Game::Scr_ParamError(1, "Invalid int64 operation");
});
}
Int64::Int64()
{
AddFunctions();
}
}

View File

@ -0,0 +1,20 @@
#pragma once
namespace Components
{
class Int64 : public Component
{
public:
Int64();
private:
using int64_OP = std::function<std::int64_t(std::int64_t, std::int64_t)>;
using int64_Comp = std::function<bool(std::int64_t, std::int64_t)>;
static std::unordered_map<std::string, int64_OP> Operations;
static std::unordered_map<std::string, int64_Comp> Comparisons;
static std::int64_t GetInt64Arg(unsigned int index, bool optional);
static void AddFunctions();
};
}

View File

@ -225,42 +225,44 @@ namespace Components
Game::Scr_StartupGameType(); Game::Scr_StartupGameType();
} }
// Do not use C++ objects because Scr_LoadScript may longjmp
void Script::GScr_LoadGameTypeScript_Stub() void Script::GScr_LoadGameTypeScript_Stub()
{ {
// Clear handles (from previous GSC loading session) // Clear handles (from previous GSC loading session)
Script::ScriptMainHandles.clear(); Script::ScriptMainHandles.clear();
Script::ScriptInitHandles.clear(); Script::ScriptInitHandles.clear();
const auto list = FileSystem::GetFileList("scripts/", "gsc"); char path[MAX_PATH]{};
for (const auto& file : list) auto numFiles = 0;
{ const auto** files = Game::FS_ListFiles("scripts/", "gsc", Game::FS_LIST_ALL, &numFiles, 10);
std::string script = "scripts/" + file;
if (Utils::String::EndsWith(script, ".gsc")) for (auto i = 0; i < numFiles; ++i)
{ {
script = script.substr(0, script.size() - 4); const auto* scriptFile = files[i];
Logger::Print("Loading script {}...\n", scriptFile);
sprintf_s(path, "%s/%s", "scripts", scriptFile);
// Scr_LoadScriptInternal will add the '.gsc' suffix so we remove it
path[std::strlen(path) - 4] = '\0';
if (!Game::Scr_LoadScript(path))
{
Logger::Print("Script {} encountered an error while loading. (doesn't exist?)", path);
continue;
} }
Logger::Print("Loading script {}.gsc...\n", script); Logger::Print("Script {}.gsc loaded successfully.\n", path);
if (!Game::Scr_LoadScript(script.data()))
{
Logger::Print("Script {} encountered an error while loading. (doesn't exist?)", script);
Logger::Error(Game::ERR_DROP, "Could not find script '{}'", script);
return;
}
Logger::Print("Script {}.gsc loaded successfully.\n", script);
Logger::Debug("Finding script handle main or init..."); Logger::Debug("Finding script handle main or init...");
const auto initHandle = Game::Scr_GetFunctionHandle(script.data(), "init"); const auto initHandle = Game::Scr_GetFunctionHandle(path, "init");
if (initHandle != 0) if (initHandle != 0)
{ {
Script::ScriptInitHandles.push_back(initHandle); Script::ScriptInitHandles.push_back(initHandle);
} }
const auto mainHandle = Game::Scr_GetFunctionHandle(script.data(), "main"); const auto mainHandle = Game::Scr_GetFunctionHandle(path, "main");
if (mainHandle != 0) if (mainHandle != 0)
{ {
Script::ScriptMainHandles.push_back(mainHandle); Script::ScriptMainHandles.push_back(mainHandle);
@ -269,6 +271,7 @@ namespace Components
// Allow scripts with no handles // Allow scripts with no handles
} }
Game::FS_FreeFileList(files, 10);
Game::GScr_LoadGameTypeScript(); Game::GScr_LoadGameTypeScript();
} }

View File

@ -3483,7 +3483,7 @@ namespace Components
Command::Add("decryptImages", [](Command::Params*) Command::Add("decryptImages", [](Command::Params*)
{ {
auto images = Game::Sys_ListFilesWrapper("iw4x/images", "iwi"); auto images = FileSystem::GetSysFileList("iw4x/images", "iwi");
Logger::Print("decrypting {} images...\n", images.size()); Logger::Print("decrypting {} images...\n", images.size());
for (auto& image : images) for (auto& image : images)
@ -3514,9 +3514,10 @@ namespace Components
Logger::Print("decrypted {} images!\n", images.size()); Logger::Print("decrypted {} images!\n", images.size());
}); });
Command::Add("decryptSounds", [](Command::Params*) Command::Add("decryptSounds", [](Command::Params*)
{ {
auto sounds = Game::Sys_ListFilesWrapper("iw4x/sound", "iwi"); auto sounds = FileSystem::GetSysFileList("iw4x/sound", "iwi");
Logger::Print("decrypting {} sounds...\n", sounds.size()); Logger::Print("decrypting {} sounds...\n", sounds.size());
for (auto& sound : sounds) for (auto& sound : sounds)

View File

@ -2,26 +2,6 @@
namespace Game namespace Game
{ {
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension)
{
auto fileCount = 0;
auto** const files = Sys_ListFiles(directory.data(), extension.data(), nullptr, &fileCount, 0);
std::vector<std::string> result;
for (auto i = 0; i < fileCount; i++)
{
if (files[i] != nullptr)
{
result.emplace_back(files[i]);
}
}
FS_FreeFileList(files);
return result;
}
AddRefToObject_t AddRefToObject = AddRefToObject_t(0x61C360); AddRefToObject_t AddRefToObject = AddRefToObject_t(0x61C360);
AllocObject_t AllocObject = AllocObject_t(0x434320); AllocObject_t AllocObject = AllocObject_t(0x434320);
AddRefToValue_t AddRefToValue = AddRefToValue_t(0x482740); AddRefToValue_t AddRefToValue = AddRefToValue_t(0x482740);
@ -150,7 +130,7 @@ namespace Game
FS_FileExists_t FS_FileExists = FS_FileExists_t(0x4DEFA0); FS_FileExists_t FS_FileExists = FS_FileExists_t(0x4DEFA0);
FS_FreeFile_t FS_FreeFile = FS_FreeFile_t(0x4416B0); FS_FreeFile_t FS_FreeFile = FS_FreeFile_t(0x4416B0);
FS_ReadFile_t FS_ReadFile = FS_ReadFile_t(0x4F4B90); FS_ReadFile_t FS_ReadFile = FS_ReadFile_t(0x4F4B90);
FS_GetFileList_t FS_GetFileList = FS_GetFileList_t(0x441BB0); FS_ListFiles_t FS_ListFiles = FS_ListFiles_t(0x441BB0);
FS_FreeFileList_t FS_FreeFileList = FS_FreeFileList_t(0x4A5DE0); FS_FreeFileList_t FS_FreeFileList = FS_FreeFileList_t(0x4A5DE0);
FS_FOpenFileAppend_t FS_FOpenFileAppend = FS_FOpenFileAppend_t(0x410BB0); FS_FOpenFileAppend_t FS_FOpenFileAppend = FS_FOpenFileAppend_t(0x410BB0);
FS_FOpenFileAppend_t FS_FOpenFileWrite = FS_FOpenFileAppend_t(0x4BA530); FS_FOpenFileAppend_t FS_FOpenFileWrite = FS_FOpenFileAppend_t(0x4BA530);

View File

@ -20,8 +20,6 @@ namespace Game
return retval; return retval;
} }
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension);
typedef void(__cdecl * AddRefToObject_t)(unsigned int id); typedef void(__cdecl * AddRefToObject_t)(unsigned int id);
extern AddRefToObject_t AddRefToObject; extern AddRefToObject_t AddRefToObject;
@ -376,10 +374,10 @@ namespace Game
typedef int(__cdecl * FS_ReadFile_t)(const char* path, char** buffer); typedef int(__cdecl * FS_ReadFile_t)(const char* path, char** buffer);
extern FS_ReadFile_t FS_ReadFile; extern FS_ReadFile_t FS_ReadFile;
typedef char** (__cdecl * FS_GetFileList_t)(const char *path, const char *extension, FsListBehavior_e behavior, int *numfiles, int allocTrackType); typedef const char**(__cdecl * FS_ListFiles_t)(const char* path, const char* extension, FsListBehavior_e behavior, int* numfiles, int allocTrackType);
extern FS_GetFileList_t FS_GetFileList; extern FS_ListFiles_t FS_ListFiles;
typedef void(__cdecl * FS_FreeFileList_t)(char** list); typedef void(__cdecl * FS_FreeFileList_t)(const char** list, int allocTrackType);
extern FS_FreeFileList_t FS_FreeFileList; extern FS_FreeFileList_t FS_FreeFileList;
typedef int(__cdecl * FS_FOpenFileAppend_t)(const char* file); typedef int(__cdecl * FS_FOpenFileAppend_t)(const char* file);
@ -978,7 +976,7 @@ namespace Game
typedef void(__cdecl * Sys_Error_t)(const char* error, ...); typedef void(__cdecl * Sys_Error_t)(const char* error, ...);
extern Sys_Error_t Sys_Error; extern Sys_Error_t Sys_Error;
typedef void(__cdecl * Sys_FreeFileList_t)(char** list); typedef void(__cdecl * Sys_FreeFileList_t)(const char** list);
extern Sys_FreeFileList_t Sys_FreeFileList; extern Sys_FreeFileList_t Sys_FreeFileList;
typedef int(__cdecl * Sys_IsDatabaseReady_t)(); typedef int(__cdecl * Sys_IsDatabaseReady_t)();
@ -999,7 +997,7 @@ namespace Game
typedef bool(__cdecl * Sys_IsDatabaseThread_t)(); typedef bool(__cdecl * Sys_IsDatabaseThread_t)();
extern Sys_IsDatabaseThread_t Sys_IsDatabaseThread; extern Sys_IsDatabaseThread_t Sys_IsDatabaseThread;
typedef char**(__cdecl * Sys_ListFiles_t)(const char* directory, const char* extension, const char* filter, int* numfiles, int wantsubs); typedef const char**(__cdecl * Sys_ListFiles_t)(const char* directory, const char* extension, const char* filter, int* numfiles, int wantsubs);
extern Sys_ListFiles_t Sys_ListFiles; extern Sys_ListFiles_t Sys_ListFiles;
typedef int(__cdecl * Sys_Milliseconds_t)(); typedef int(__cdecl * Sys_Milliseconds_t)();