Initial rodecomp source snapshot
This commit is contained in:
commit
d456e8f64a
916 changed files with 156023 additions and 0 deletions
143
Source/Script/LuaInstance.cpp
Normal file
143
Source/Script/LuaInstance.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
#include "Script/LuaInstance.h"
|
||||
#include "File/File.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
}
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <windows.h>
|
||||
|
||||
// OFFSET: 0x005221E0
|
||||
// FUNCTION: fn_01123
|
||||
CLuaInstance::CLuaInstance() : m_state(luaL_newstate()) {
|
||||
if (this->m_state) {
|
||||
luaL_openlibs(this->m_state);
|
||||
lua_register(this->m_state, "MessageBox", LuaMessageBox);
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00522290
|
||||
CLuaInstance::~CLuaInstance() {
|
||||
if (this->m_state) {
|
||||
lua_close(this->m_state);
|
||||
this->m_state = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x005223D0
|
||||
// FUNCTION: fn_01128
|
||||
bool CLuaInstance::Execute(const std::string& name) {
|
||||
lua_getglobal(this->m_state, name.c_str());
|
||||
|
||||
if (lua_pcall(this->m_state, 0, 0, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// STATIC: 0x010D9630
|
||||
// STRING: st_00223
|
||||
const char* error = lua_tostring(this->m_state, -1);
|
||||
MessageBoxA(nullptr, error, "Lua Error", 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00522460
|
||||
// FUNCTION: fn_01129
|
||||
int CLuaInstance::LuaMessageBox(lua_State* state) {
|
||||
const std::string text = lua_tostring(state, -1);
|
||||
MessageBoxA(nullptr, text.c_str(), "CLuaInstance", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// OFFSET: 0x005225F0
|
||||
// FUNCTION: fn_01130
|
||||
bool CLuaInstance::LoadFile(const std::string& path, bool showError) {
|
||||
if (luaL_loadfile(this->m_state, path.c_str()) == 0 && lua_pcall(this->m_state, 0, LUA_MULTRET, 0) == 0) {
|
||||
return true;
|
||||
}
|
||||
if (showError) {
|
||||
MessageBoxA(nullptr, lua_tostring(this->m_state, -1), path.c_str(), 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00522660
|
||||
// FUNCTION: fn_01131
|
||||
bool CLuaInstance::LoadFile(const std::string& path) {
|
||||
CFile file;
|
||||
if (!file.Open(path.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::uint32_t size = file.GetSize();
|
||||
char* buffer = static_cast<char*>(std::malloc(size + 1));
|
||||
if (!buffer) {
|
||||
file.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memset(buffer, 0, size + 1);
|
||||
file.Read(buffer, size);
|
||||
file.Close();
|
||||
|
||||
if (luaL_loadbuffer(this->m_state, buffer, size, path.c_str()) == 0 &&
|
||||
lua_pcall(this->m_state, 0, 0, 0) == 0) {
|
||||
std::free(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* error = lua_tostring(this->m_state, -1);
|
||||
MessageBoxA(nullptr, error, path.c_str(), 0);
|
||||
lua_pop(this->m_state, 1);
|
||||
std::free(buffer);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00522870
|
||||
// FUNCTION: fn_01132
|
||||
void CLuaInstance::SetGlobal(const std::string& name, bool value) {
|
||||
lua_pushboolean(this->m_state, value);
|
||||
lua_setglobal(this->m_state, name.c_str());
|
||||
}
|
||||
|
||||
// OFFSET: 0x005228B0
|
||||
// FUNCTION: fn_01133
|
||||
void CLuaInstance::SetGlobal(const std::string& name, int value) {
|
||||
lua_pushinteger(this->m_state, value);
|
||||
lua_setglobal(this->m_state, name.c_str());
|
||||
}
|
||||
|
||||
// OFFSET: 0x005228F0
|
||||
// FUNCTION: fn_01134
|
||||
void CLuaInstance::SetGlobal(const std::string& name, double value) {
|
||||
lua_pushnumber(this->m_state, value);
|
||||
lua_setglobal(this->m_state, name.c_str());
|
||||
}
|
||||
|
||||
// OFFSET: 0x00E27850
|
||||
// FUNCTION: fn_23942
|
||||
int CLuaInstance::ReadStrings(std::vector<std::string>& values, const char* global) {
|
||||
lua_getglobal(this->m_state, global);
|
||||
int type = lua_type(this->m_state, -1);
|
||||
if (type != LUA_TTABLE) {
|
||||
lua_pop(this->m_state, 1);
|
||||
return (type != LUA_TNIL) + 1;
|
||||
}
|
||||
values.resize(lua_objlen(this->m_state, -1));
|
||||
lua_pushnil(this->m_state);
|
||||
std::size_t index = 0;
|
||||
while (lua_next(this->m_state, -2)) {
|
||||
type = lua_type(this->m_state, -1);
|
||||
if (type != LUA_TSTRING) {
|
||||
lua_pop(this->m_state, 3);
|
||||
return (type != LUA_TNIL) + 1;
|
||||
}
|
||||
values[index++] = lua_tostring(this->m_state, -1);
|
||||
lua_pop(this->m_state, 1);
|
||||
}
|
||||
lua_pop(this->m_state, 1);
|
||||
return 0;
|
||||
}
|
||||
34
Source/Script/LuaInstance.h
Normal file
34
Source/Script/LuaInstance.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef RAGNAROK_SOURCE_SCRIPT_LUAINSTANCE_H
|
||||
#define RAGNAROK_SOURCE_SCRIPT_LUAINSTANCE_H
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CLuaInstance {
|
||||
public:
|
||||
CLuaInstance();
|
||||
virtual ~CLuaInstance();
|
||||
bool Execute(const std::string& name);
|
||||
bool LoadFile(const std::string& path);
|
||||
bool LoadFile(const std::string& path, bool showError);
|
||||
void SetGlobal(const std::string& name, bool value);
|
||||
void SetGlobal(const std::string& name, int value);
|
||||
void SetGlobal(const std::string& name, double value);
|
||||
int ReadStrings(std::vector<std::string>& values, const char* global);
|
||||
|
||||
protected:
|
||||
/* 0004 */ lua_State* m_state;
|
||||
|
||||
private:
|
||||
static int LuaMessageBox(lua_State* state);
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
static_assert(sizeof(CLuaInstance) == 8);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
311
Source/Script/LuaScript.cpp
Normal file
311
Source/Script/LuaScript.cpp
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
#include "Script/LuaScript.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lauxlib.h>
|
||||
}
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <windows.h>
|
||||
|
||||
// OFFSET: 0x00AFC830
|
||||
LuaScript::LuaScript() : m_state(nullptr) {
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFC860
|
||||
// FUNCTION: fn_18324
|
||||
LuaScript::~LuaScript() {
|
||||
this->Close();
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFDDB0
|
||||
// FUNCTION: fn_18336
|
||||
void LuaScript::Close() {
|
||||
if (this->m_state) {
|
||||
lua_close(this->m_state);
|
||||
this->m_state = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFDD60
|
||||
// FUNCTION: fn_18335
|
||||
bool LuaScript::Execute(const void* bytes, std::size_t size) {
|
||||
return this->m_state && luaL_loadbuffer(this->m_state, static_cast<const char*>(bytes), size, "buf") == 0 &&
|
||||
lua_pcall(this->m_state, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD1D0
|
||||
// FUNCTION: fn_18328
|
||||
void LuaScript::Error(const char* caption, const char* format, ...) {
|
||||
char text[500];
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
_vsnprintf_s(text, sizeof(text), _TRUNCATE, format, arguments);
|
||||
va_end(arguments);
|
||||
MessageBoxA(nullptr, text, caption, 0);
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFC9A0
|
||||
// FUNCTION: fn_18326
|
||||
bool LuaScript::Call(std::string function, const char* signature, ...) {
|
||||
if (!this->m_state) {
|
||||
return false;
|
||||
}
|
||||
va_list arguments;
|
||||
va_start(arguments, signature);
|
||||
lua_getglobal(this->m_state, function.c_str());
|
||||
int inputCount = 0;
|
||||
while (*signature) {
|
||||
luaL_checkstack(this->m_state, 1, "too many arguments");
|
||||
char option = *signature++;
|
||||
if (option == '>') {
|
||||
break;
|
||||
}
|
||||
switch (option) {
|
||||
case 'b':
|
||||
lua_pushboolean(this->m_state, static_cast<unsigned char>(va_arg(arguments, int)));
|
||||
break;
|
||||
case 'd':
|
||||
lua_pushnumber(this->m_state, va_arg(arguments, int));
|
||||
break;
|
||||
case 'l':
|
||||
lua_pushnumber(this->m_state, va_arg(arguments, double));
|
||||
break;
|
||||
case 's':
|
||||
lua_pushstring(this->m_state, va_arg(arguments, const char*));
|
||||
break;
|
||||
default:
|
||||
this->Error(function.c_str(), "invalid option (%c)", option);
|
||||
break;
|
||||
}
|
||||
++inputCount;
|
||||
}
|
||||
int outputCount = static_cast<int>(std::strlen(signature));
|
||||
if (lua_pcall(this->m_state, inputCount, outputCount, 0)) {
|
||||
std::string error = lua_tostring(this->m_state, -1);
|
||||
this->Error(function.c_str(), "%s\n", error.c_str());
|
||||
if (this->m_state) {
|
||||
lua_settop(this->m_state, 0);
|
||||
}
|
||||
va_end(arguments);
|
||||
return false;
|
||||
}
|
||||
for (int output = -outputCount; *signature; ++output) {
|
||||
switch (*signature++) {
|
||||
case 'b':
|
||||
*va_arg(arguments, bool*) = lua_toboolean(this->m_state, output) != 0;
|
||||
break;
|
||||
case 'd':
|
||||
*va_arg(arguments, int*) = static_cast<int>(lua_tonumber(this->m_state, output));
|
||||
break;
|
||||
case 'l':
|
||||
*va_arg(arguments, double*) = lua_tonumber(this->m_state, output);
|
||||
break;
|
||||
case 's':
|
||||
*va_arg(arguments, const char**) = lua_tostring(this->m_state, output);
|
||||
break;
|
||||
default:
|
||||
this->Error(function.c_str(), "invalid option (%c)", signature[-1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outputCount) {
|
||||
lua_pop(this->m_state, outputCount);
|
||||
if (this->m_state) {
|
||||
lua_settop(this->m_state, 0);
|
||||
}
|
||||
}
|
||||
va_end(arguments);
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFCD90
|
||||
// FUNCTION: fn_18327
|
||||
bool LuaScript::CallTable(std::string table, std::string function, const char* signature, ...) {
|
||||
if (!this->m_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list arguments;
|
||||
va_start(arguments, signature);
|
||||
|
||||
lua_getglobal(this->m_state, table.c_str());
|
||||
lua_getfield(this->m_state, -1, function.c_str());
|
||||
|
||||
int inputCount = 0;
|
||||
while (*signature) {
|
||||
luaL_checkstack(this->m_state, 1, "too many arguments");
|
||||
|
||||
char option = *signature++;
|
||||
if (option == '>') {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case 'b':
|
||||
lua_pushboolean(this->m_state, static_cast<unsigned char>(va_arg(arguments, int)));
|
||||
break;
|
||||
case 'd':
|
||||
lua_pushnumber(this->m_state, va_arg(arguments, int));
|
||||
break;
|
||||
case 'l':
|
||||
lua_pushnumber(this->m_state, va_arg(arguments, double));
|
||||
break;
|
||||
case 's':
|
||||
lua_pushstring(this->m_state, va_arg(arguments, const char*));
|
||||
break;
|
||||
default:
|
||||
this->Error(function.c_str(), "invalid option (%c)", option);
|
||||
break;
|
||||
}
|
||||
|
||||
++inputCount;
|
||||
}
|
||||
|
||||
int outputCount = static_cast<int>(std::strlen(signature));
|
||||
if (lua_pcall(this->m_state, inputCount, outputCount, 0)) {
|
||||
std::string error = lua_tostring(this->m_state, -1);
|
||||
this->Error(function.c_str(), "%s\n", error.c_str());
|
||||
if (this->m_state) {
|
||||
lua_settop(this->m_state, 0);
|
||||
}
|
||||
va_end(arguments);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int output = -outputCount; *signature; ++output) {
|
||||
switch (*signature++) {
|
||||
case 'b':
|
||||
*va_arg(arguments, bool*) = lua_toboolean(this->m_state, output) != 0;
|
||||
break;
|
||||
case 'd':
|
||||
*va_arg(arguments, int*) = static_cast<int>(lua_tonumber(this->m_state, output));
|
||||
break;
|
||||
case 'l':
|
||||
*va_arg(arguments, double*) = lua_tonumber(this->m_state, output);
|
||||
break;
|
||||
case 's':
|
||||
*va_arg(arguments, const char**) = lua_tostring(this->m_state, output);
|
||||
break;
|
||||
default:
|
||||
this->Error(function.c_str(), "invalid option (%c)", signature[-1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (outputCount) {
|
||||
lua_settop(this->m_state, -1 - outputCount);
|
||||
if (this->m_state) {
|
||||
lua_settop(this->m_state, 0);
|
||||
}
|
||||
}
|
||||
|
||||
va_end(arguments);
|
||||
return true;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD2A0
|
||||
// FUNCTION: fn_18329
|
||||
int LuaScript::GlobalInteger(const char* name) {
|
||||
if (!this->m_state) {
|
||||
return 0;
|
||||
}
|
||||
lua_getglobal(this->m_state, name);
|
||||
if (!lua_isnumber(this->m_state, -1)) {
|
||||
return -1;
|
||||
}
|
||||
int value = static_cast<int>(lua_tonumber(this->m_state, -1));
|
||||
lua_pop(this->m_state, 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD310
|
||||
// FUNCTION: fn_18330
|
||||
std::string LuaScript::GlobalString(const char* name) {
|
||||
if (!this->m_state) {
|
||||
return {};
|
||||
}
|
||||
lua_getglobal(this->m_state, name);
|
||||
if (!lua_isstring(this->m_state, -1)) {
|
||||
return {};
|
||||
}
|
||||
std::string value = lua_tostring(this->m_state, -1);
|
||||
lua_pop(this->m_state, 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD490
|
||||
// FUNCTION: fn_18331
|
||||
bool LuaScript::HasTable(const char* name) {
|
||||
if (!this->m_state) {
|
||||
return false;
|
||||
}
|
||||
lua_getglobal(this->m_state, name);
|
||||
// The original deliberately leaves this fetched global on the stack.
|
||||
return lua_type(this->m_state, -1) == LUA_TTABLE;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD4D0
|
||||
// FUNCTION: fn_18332
|
||||
std::list<int> LuaScript::TableKeys(const char* name, int) {
|
||||
std::list<int> keys;
|
||||
|
||||
if (!this->m_state) {
|
||||
return keys;
|
||||
}
|
||||
|
||||
lua_getglobal(this->m_state, name);
|
||||
|
||||
if (lua_type(this->m_state, -1) == LUA_TTABLE) {
|
||||
lua_pushnil(this->m_state);
|
||||
|
||||
while (lua_next(this->m_state, -2)) {
|
||||
keys.push_back(static_cast<int>(lua_tonumber(this->m_state, -2)));
|
||||
lua_pop(this->m_state, 1);
|
||||
}
|
||||
|
||||
lua_pop(this->m_state, 1);
|
||||
keys.sort();
|
||||
}
|
||||
|
||||
// A missing/non-table global remains on the stack in the original.
|
||||
return keys;
|
||||
}
|
||||
|
||||
// OFFSET: 0x00AFD830
|
||||
// FUNCTION: fn_18333
|
||||
int LuaScript::TableInteger(std::string table, int keyType, std::intptr_t key) {
|
||||
if (!this->m_state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int value = -1;
|
||||
lua_getglobal(this->m_state, table.c_str());
|
||||
|
||||
if (lua_type(this->m_state, -1) != LUA_TTABLE) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (keyType == 0) {
|
||||
lua_pushnumber(this->m_state, static_cast<int>(key));
|
||||
lua_gettable(this->m_state, -2);
|
||||
} else if (keyType == 1) {
|
||||
lua_pushstring(this->m_state, reinterpret_cast<const char*>(key));
|
||||
lua_gettable(this->m_state, -2);
|
||||
} else if (keyType != 2) {
|
||||
// Unknown selectors construct signature "d": perform the integer lookup,
|
||||
// but retain its value without attempting the absent output conversion.
|
||||
lua_pushnumber(this->m_state, static_cast<int>(key));
|
||||
lua_gettable(this->m_state, -2);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Selector two constructs "ld"; the original input helper does not implement
|
||||
// 'l', so it leaves the table itself for the numeric output check.
|
||||
if (lua_isnumber(this->m_state, -1)) {
|
||||
value = static_cast<int>(lua_tonumber(this->m_state, -1));
|
||||
lua_pop(this->m_state, 1);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
37
Source/Script/LuaScript.h
Normal file
37
Source/Script/LuaScript.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef RAGNAROK_SOURCE_SCRIPT_LUASCRIPT_H
|
||||
#define RAGNAROK_SOURCE_SCRIPT_LUASCRIPT_H
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
// Reconstructed name for the original one-pointer script wrapper. This does not
|
||||
// claim the unreconstructed application's native-registration initializer.
|
||||
class LuaScript {
|
||||
public:
|
||||
LuaScript();
|
||||
~LuaScript();
|
||||
bool Call(std::string function, const char* signature, ...);
|
||||
bool CallTable(std::string table, std::string function, const char* signature, ...);
|
||||
bool Execute(const void* bytes, std::size_t size);
|
||||
int GlobalInteger(const char* name);
|
||||
std::string GlobalString(const char* name);
|
||||
bool HasTable(const char* name);
|
||||
std::list<int> TableKeys(const char* name, int unused);
|
||||
int TableInteger(std::string table, int keyType, std::intptr_t key);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
/* 0000 */ lua_State* m_state;
|
||||
|
||||
private:
|
||||
void Error(const char* caption, const char* format, ...);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue