[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;
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;
return Game::FS_GetFileList(path, extension, behavior, numfiles, allocTrackType);
return Game::FS_ListFiles(path, extension, behavior, numfiles, allocTrackType);
}
void Console::RefreshStatus()

View File

@ -63,7 +63,7 @@ namespace Components
static void StoreSafeArea();
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 AddConsoleCommand();

View File

@ -160,8 +160,8 @@ namespace Components
{
std::vector<std::string> fileList;
int numFiles = 0;
char** files = Game::FS_GetFileList(path.data(), extension.data(), Game::FS_LIST_PURE_ONLY, &numFiles, 0);
auto numFiles = 0;
const auto** files = Game::FS_ListFiles(path.data(), extension.data(), Game::FS_LIST_PURE_ONLY, &numFiles, 10);
if (files)
{
@ -169,11 +169,11 @@ namespace Components
{
if (files[i])
{
fileList.push_back(files[i]);
fileList.emplace_back(files[i]);
}
}
Game::FS_FreeFileList(files);
Game::FS_FreeFileList(files, 10);
}
return fileList;
@ -183,8 +183,8 @@ namespace Components
{
std::vector<std::string> fileList;
int numFiles = 0;
char** files = Game::Sys_ListFiles(path.data(), extension.data(), nullptr, &numFiles, folders);
auto numFiles = 0;
const auto** files = Game::Sys_ListFiles(path.data(), extension.data(), nullptr, &numFiles, folders);
if (files)
{
@ -192,7 +192,7 @@ namespace Components
{
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)
{
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));
return Game::FS_Remove(path);
}

View File

@ -1,5 +1,6 @@
#include <STDInclude.hpp>
#include "Int64.hpp"
#include "IO.hpp"
#include "Script.hpp"
#include "ScriptExtension.hpp"
@ -9,6 +10,7 @@ namespace Components
{
GSC::GSC()
{
Loader::Register(new Int64());
Loader::Register(new IO());
Loader::Register(new Script());
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();
}
// Do not use C++ objects because Scr_LoadScript may longjmp
void Script::GScr_LoadGameTypeScript_Stub()
{
// Clear handles (from previous GSC loading session)
Script::ScriptMainHandles.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);
for (auto i = 0; i < numFiles; ++i)
{
std::string script = "scripts/" + file;
const auto* scriptFile = files[i];
Logger::Print("Loading script {}...\n", scriptFile);
if (Utils::String::EndsWith(script, ".gsc"))
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))
{
script = script.substr(0, script.size() - 4);
Logger::Print("Script {} encountered an error while loading. (doesn't exist?)", path);
continue;
}
Logger::Print("Loading script {}.gsc...\n", script);
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::Print("Script {}.gsc loaded successfully.\n", path);
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)
{
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)
{
Script::ScriptMainHandles.push_back(mainHandle);
@ -269,6 +271,7 @@ namespace Components
// Allow scripts with no handles
}
Game::FS_FreeFileList(files, 10);
Game::GScr_LoadGameTypeScript();
}

View File

@ -3483,14 +3483,14 @@ namespace Components
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());
for (auto& image : images)
{
char* buffer = nullptr;
auto fileLength = Game::FS_ReadFile(Utils::String::VA("images/%s", image.data()), &buffer);
if (fileLength && buffer)
{
if (!std::filesystem::exists("raw/images"))
@ -3514,9 +3514,10 @@ namespace Components
Logger::Print("decrypted {} images!\n", images.size());
});
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());
for (auto& sound : sounds)

View File

@ -2,26 +2,6 @@
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);
AllocObject_t AllocObject = AllocObject_t(0x434320);
AddRefToValue_t AddRefToValue = AddRefToValue_t(0x482740);
@ -150,7 +130,7 @@ namespace Game
FS_FileExists_t FS_FileExists = FS_FileExists_t(0x4DEFA0);
FS_FreeFile_t FS_FreeFile = FS_FreeFile_t(0x4416B0);
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_FOpenFileAppend_t FS_FOpenFileAppend = FS_FOpenFileAppend_t(0x410BB0);
FS_FOpenFileAppend_t FS_FOpenFileWrite = FS_FOpenFileAppend_t(0x4BA530);

View File

@ -20,8 +20,6 @@ namespace Game
return retval;
}
std::vector<std::string> Sys_ListFilesWrapper(const std::string& directory, const std::string& extension);
typedef void(__cdecl * AddRefToObject_t)(unsigned int id);
extern AddRefToObject_t AddRefToObject;
@ -376,10 +374,10 @@ namespace Game
typedef int(__cdecl * FS_ReadFile_t)(const char* path, char** buffer);
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);
extern FS_GetFileList_t FS_GetFileList;
typedef const char**(__cdecl * FS_ListFiles_t)(const char* path, const char* extension, FsListBehavior_e behavior, int* numfiles, int allocTrackType);
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;
typedef int(__cdecl * FS_FOpenFileAppend_t)(const char* file);
@ -978,7 +976,7 @@ namespace Game
typedef void(__cdecl * Sys_Error_t)(const char* 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;
typedef int(__cdecl * Sys_IsDatabaseReady_t)();
@ -999,7 +997,7 @@ namespace Game
typedef bool(__cdecl * Sys_IsDatabaseThread_t)();
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;
typedef int(__cdecl * Sys_Milliseconds_t)();