diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj index ec8f50b1..c983651b 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj +++ b/build-windows-visual-studio/sm64ex.vcxproj @@ -512,6 +512,7 @@ + @@ -958,6 +959,7 @@ + diff --git a/build-windows-visual-studio/sm64ex.vcxproj.filters b/build-windows-visual-studio/sm64ex.vcxproj.filters index b3af4401..29a0926e 100644 --- a/build-windows-visual-studio/sm64ex.vcxproj.filters +++ b/build-windows-visual-studio/sm64ex.vcxproj.filters @@ -4833,6 +4833,9 @@ Source Files\src\game + + Source Files\src\pc\lua + @@ -5956,5 +5959,8 @@ Source Files\src\game + + Source Files\src\pc\lua + - + \ No newline at end of file diff --git a/src/pc/lua/smlua.c b/src/pc/lua/smlua.c index 5b01bb95..a9e7add6 100644 --- a/src/pc/lua/smlua.c +++ b/src/pc/lua/smlua.c @@ -2,135 +2,6 @@ lua_State* gLuaState = NULL; - /////////////////// - // hooked events // -/////////////////// - -#define MAX_HOOKED_REFERENCES 64 - -struct LuaHookedEvent { - int reference[MAX_HOOKED_REFERENCES]; - int count; -}; - -static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 }; - -int smlua_hook_event(lua_State* L) { - u16 hookType = lua_tointeger(L, -2); - if (hookType >= HOOK_MAX) { - LOG_LUA("LUA: Hook Type: %d exceeds max!", hookType); - return 0; - } - - struct LuaHookedEvent* hook = &sHookedEvents[hookType]; - if (hook->count >= MAX_HOOKED_REFERENCES) { - LOG_LUA("LUA: Hook Type: %d exceeded maximum references!", hookType); - return 0; - } - - hook->reference[hook->count] = luaL_ref(L, LUA_REGISTRYINDEX); - hook->count++; - return 1; -} - -void smlua_call_event_hooks(enum LuaHookedEventType hookType) { - lua_State* L = gLuaState; - struct LuaHookedEvent* hook = &sHookedEvents[hookType]; - for (int i = 0; i < hook->count; i++) { - // push the callback onto the stack - lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); - - // call the callback - if (0 != lua_pcall(L, 0, 0, 0)) { - LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); - continue; - } - } -} - -void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m) { - lua_State* L = gLuaState; - struct LuaHookedEvent* hook = &sHookedEvents[hookType]; - for (int i = 0; i < hook->count; i++) { - // push the callback onto the stack - lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); - - // push mario state - lua_getglobal(L, "gMarioStates"); - lua_pushinteger(L, m->playerIndex); - lua_gettable(L, -2); - lua_remove(L, -2); - - // call the callback - if (0 != lua_pcall(L, 1, 0, 0)) { - LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); - continue; - } - } -} - - //////////////////// - // hooked actions // -//////////////////// - -struct LuaHookedMarioAction { - u32 action; - int reference; -}; - -#define MAX_HOOKED_ACTIONS 64 - -static struct LuaHookedMarioAction sHookedMarioActions[MAX_HOOKED_ACTIONS] = { 0 }; -static int sHookedMarioActionsCount = 0; - -int smlua_hook_mario_action(lua_State* L) { - if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) { - LOG_LUA("LUA: Hooked mario actions exceeded maximum references!"); - return 0; - } - - struct LuaHookedMarioAction* hooked = &sHookedMarioActions[sHookedMarioActionsCount]; - hooked->action = lua_tointeger(L, -2); - hooked->reference = luaL_ref(L, LUA_REGISTRYINDEX); - - sHookedMarioActionsCount++; - return 1; -} - -bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) { - lua_State* L = gLuaState; - for (int i = 0; i < sHookedMarioActionsCount; i++) { - if (sHookedMarioActions[i].action == m->action) { - // push the callback onto the stack - lua_rawgeti(L, LUA_REGISTRYINDEX, sHookedMarioActions[i].reference); - - // push mario state - lua_getglobal(L, "gMarioStates"); - lua_pushinteger(L, m->playerIndex); - lua_gettable(L, -2); - lua_remove(L, -2); - - // call the callback - if (0 != lua_pcall(L, 1, 1, 0)) { - LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); - continue; - } - - // output the return value - *returnValue = lua_tointeger(L, -1); - lua_pop(L, 1); - - return true; - } - } - - return false; -} - - ////////// - // main // -////////// - static void smlua_execfile(char* path) { lua_State* L = gLuaState; if (luaL_dofile(L, path) != LUA_OK) { @@ -168,12 +39,7 @@ void smlua_init(void) { luaL_requiref(L, "table", luaopen_table, 1); //luaopen_utf8(L); - lua_pushcfunction(L, smlua_hook_event); - lua_setglobal(L, "hook_event"); - - lua_pushcfunction(L, smlua_hook_mario_action); - lua_setglobal(L, "hook_mario_action"); - + smlua_bind_hooks(); smlua_bind_cobject(); smlua_bind_functions(); smlua_bind_functions_autogen(); @@ -190,18 +56,4 @@ void smlua_update(void) { void smlua_shutdown(void) { lua_State* L = gLuaState; lua_close(L); - - for (int i = 0; i < HOOK_MAX; i++) { - for (int j = 0; j < sHookedEvents[i].count; j++) { - sHookedEvents[i].reference[j] = 0; - } - sHookedEvents[i].count = 0; - } - - for (int i = 0; i < sHookedMarioActionsCount; i++) { - sHookedMarioActions[i].action = 0; - sHookedMarioActions[i].reference = 0; - } - sHookedMarioActionsCount = 0; - } diff --git a/src/pc/lua/smlua.h b/src/pc/lua/smlua.h index cce4e4fd..d404ec4c 100644 --- a/src/pc/lua/smlua.h +++ b/src/pc/lua/smlua.h @@ -11,25 +11,14 @@ #include "smlua_utils.h" #include "smlua_functions.h" #include "smlua_functions_autogen.h" +#include "smlua_hooks.h" #include "pc/debuglog.h" #define LOG_LUA LOG_INFO -enum LuaHookedEventType { - HOOK_UPDATE, - HOOK_MARIO_UPDATE, - HOOK_BEFORE_MARIO_UPDATE, - HOOK_MAX, -}; - extern lua_State* gLuaState; -void smlua_call_event_hooks(enum LuaHookedEventType hookType); -void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m); - -bool smlua_call_action_hook(struct MarioState* m, s32* returnValue); - void smlua_init(void); void smlua_update(void); void smlua_shutdown(void); diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index 7fd1be3c..0b07e659 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -388,10 +388,7 @@ static int smlua__set_field(lua_State* L) { void smlua_bind_cobject(void) { lua_State* L = gLuaState; - lua_pushcfunction(L, smlua__get_field); - lua_setglobal(L, "_get_field"); - - lua_pushcfunction(L, smlua__set_field); - lua_setglobal(L, "_set_field"); + smlua_bind_function(L, "_get_field", smlua__get_field); + smlua_bind_function(L, "_set_field", smlua__set_field); } \ No newline at end of file diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c new file mode 100644 index 00000000..fffe4074 --- /dev/null +++ b/src/pc/lua/smlua_hooks.c @@ -0,0 +1,150 @@ +#include "smlua.h" + +#define MAX_HOOKED_REFERENCES 64 + +struct LuaHookedEvent { + int reference[MAX_HOOKED_REFERENCES]; + int count; +}; + +static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 }; + +int smlua_hook_event(lua_State* L) { + u16 hookType = lua_tointeger(L, -2); + if (hookType >= HOOK_MAX) { + LOG_LUA("LUA: Hook Type: %d exceeds max!", hookType); + return 0; + } + + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + if (hook->count >= MAX_HOOKED_REFERENCES) { + LOG_LUA("LUA: Hook Type: %d exceeded maximum references!", hookType); + return 0; + } + + hook->reference[hook->count] = luaL_ref(L, LUA_REGISTRYINDEX); + hook->count++; + return 1; +} + +void smlua_call_event_hooks(enum LuaHookedEventType hookType) { + lua_State* L = gLuaState; + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + for (int i = 0; i < hook->count; i++) { + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); + + // call the callback + if (0 != lua_pcall(L, 0, 0, 0)) { + LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); + continue; + } + } +} + +void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m) { + lua_State* L = gLuaState; + struct LuaHookedEvent* hook = &sHookedEvents[hookType]; + for (int i = 0; i < hook->count; i++) { + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]); + + // push mario state + lua_getglobal(L, "gMarioStates"); + lua_pushinteger(L, m->playerIndex); + lua_gettable(L, -2); + lua_remove(L, -2); + + // call the callback + if (0 != lua_pcall(L, 1, 0, 0)) { + LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); + continue; + } + } +} + + //////////////////// + // hooked actions // +//////////////////// + +struct LuaHookedMarioAction { + u32 action; + int reference; +}; + +#define MAX_HOOKED_ACTIONS 64 + +static struct LuaHookedMarioAction sHookedMarioActions[MAX_HOOKED_ACTIONS] = { 0 }; +static int sHookedMarioActionsCount = 0; + +int smlua_hook_mario_action(lua_State* L) { + if (sHookedMarioActionsCount >= MAX_HOOKED_ACTIONS) { + LOG_LUA("LUA: Hooked mario actions exceeded maximum references!"); + return 0; + } + + struct LuaHookedMarioAction* hooked = &sHookedMarioActions[sHookedMarioActionsCount]; + hooked->action = lua_tointeger(L, -2); + hooked->reference = luaL_ref(L, LUA_REGISTRYINDEX); + + sHookedMarioActionsCount++; + return 1; +} + +bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) { + lua_State* L = gLuaState; + for (int i = 0; i < sHookedMarioActionsCount; i++) { + if (sHookedMarioActions[i].action == m->action) { + // push the callback onto the stack + lua_rawgeti(L, LUA_REGISTRYINDEX, sHookedMarioActions[i].reference); + + // push mario state + lua_getglobal(L, "gMarioStates"); + lua_pushinteger(L, m->playerIndex); + lua_gettable(L, -2); + lua_remove(L, -2); + + // call the callback + if (0 != lua_pcall(L, 1, 1, 0)) { + LOG_LUA("LUA: Failed to call the callback: %s", lua_tostring(L, -1)); + continue; + } + + // output the return value + *returnValue = lua_tointeger(L, -1); + lua_pop(L, 1); + + return true; + } + } + + return false; +} + + ////////// + // misc // +////////// + +static void smlua_clear_hooks(void) { + for (int i = 0; i < HOOK_MAX; i++) { + for (int j = 0; j < sHookedEvents[i].count; j++) { + sHookedEvents[i].reference[j] = 0; + } + sHookedEvents[i].count = 0; + } + + for (int i = 0; i < sHookedMarioActionsCount; i++) { + sHookedMarioActions[i].action = 0; + sHookedMarioActions[i].reference = 0; + } + sHookedMarioActionsCount = 0; +} + +void smlua_bind_hooks(void) { + lua_State* L = gLuaState; + smlua_clear_hooks(); + + smlua_bind_function(L, "hook_event", smlua_hook_event); + smlua_bind_function(L, "hook_mario_action", smlua_hook_mario_action); + +} diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h new file mode 100644 index 00000000..46475705 --- /dev/null +++ b/src/pc/lua/smlua_hooks.h @@ -0,0 +1,19 @@ +#ifndef SMLUA_HOOKS_H +#define SMLUA_HOOKS_H + +#include + +enum LuaHookedEventType { + HOOK_UPDATE, + HOOK_MARIO_UPDATE, + HOOK_BEFORE_MARIO_UPDATE, + HOOK_MAX, +}; + +void smlua_call_event_hooks(enum LuaHookedEventType hookType); +void smlua_call_event_hooks_mario_param(enum LuaHookedEventType hookType, struct MarioState* m); +bool smlua_call_action_hook(struct MarioState* m, s32* returnValue); + +void smlua_bind_hooks(void); + +#endif \ No newline at end of file