diff --git a/include/lua.hpp b/include/lua.hpp index f45a838de..ceb91cae0 100644 --- a/include/lua.hpp +++ b/include/lua.hpp @@ -1,5 +1,6 @@ #pragma once #include "helpers.hpp" +#include "memory.hpp" #ifdef PANDA3DS_ENABLE_LUA extern "C" { @@ -15,8 +16,15 @@ class LuaManager { bool initialized = false; public: + // For Lua we must have some global pointers to our emulator objects to use them in script code via thunks. See the thunks in lua.cpp as an + // example + static Memory* g_memory; + + LuaManager(Memory& mem) { g_memory = &mem; } + void close(); void initialize(); + void initializeThunks(); void loadFile(const char* path); void reset(); }; @@ -24,6 +32,8 @@ class LuaManager { #elif // Lua not enabled, Lua manager does nothing class LuaManager { public: + LuaManager(Memory& mem) {} + void close() {} void initialize() {} void loadFile(const char* path) {} diff --git a/src/emulator.cpp b/src/emulator.cpp index c5acce761..c21e86b9f 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -13,7 +13,7 @@ __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1; Emulator::Emulator() : config(std::filesystem::current_path() / "config.toml"), kernel(cpu, memory, gpu, config), cpu(memory, kernel), gpu(memory, config), - memory(cpu.getTicksRef(), config), cheats(memory, kernel.getServiceManager().getHID()), running(false), programRunning(false) + memory(cpu.getTicksRef(), config), cheats(memory, kernel.getServiceManager().getHID()), lua(memory), running(false), programRunning(false) #ifdef PANDA3DS_ENABLE_HTTP_SERVER , httpServer(this) #endif diff --git a/src/lua.cpp b/src/lua.cpp index a01cc0b54..1cdcc6895 100644 --- a/src/lua.cpp +++ b/src/lua.cpp @@ -3,14 +3,16 @@ void LuaManager::initialize() { L = luaL_newstate(); // Open Lua - + if (!L) { printf("Lua initialization failed, continuing without Lua"); - initialized = false; + initialized = false; return; } luaL_openlibs(L); + initializeThunks(); + initialized = true; } @@ -34,4 +36,41 @@ void LuaManager::loadFile(const char* path) { void LuaManager::reset() { // Reset scripts } + +// Initialize C++ thunks for Lua code to call here +// All code beyond this point is terrible and full of global state, don't judge + +Memory* LuaManager::g_memory = nullptr; + +#define MAKE_MEMORY_FUNCTIONS(size) \ + static int read##size##Thunk(lua_State* L) { \ + const u32 vaddr = (u32)lua_tonumber(L, 1); \ + lua_pushnumber(L, LuaManager::g_memory->read##size(vaddr)); \ + return 1; \ + } \ + static int write##size##Thunk(lua_State* L) { \ + const u32 vaddr = (u32)lua_tonumber(L, 1); \ + const u##size value = (u##size)lua_tonumber(L, 2); \ + LuaManager::g_memory->write##size(vaddr, value); \ + return 0; \ + } + + +MAKE_MEMORY_FUNCTIONS(8) +MAKE_MEMORY_FUNCTIONS(16) +MAKE_MEMORY_FUNCTIONS(32) +MAKE_MEMORY_FUNCTIONS(64) +#undef MAKE_MEMORY_FUNCTIONS + +void LuaManager::initializeThunks() { + lua_register(L, "read8", read8Thunk); + lua_register(L, "read16", read16Thunk); + lua_register(L, "read32", read32Thunk); + lua_register(L, "read64", read64Thunk); + lua_register(L, "write8", write8Thunk); + lua_register(L, "write16", write16Thunk); + lua_register(L, "write32", write32Thunk); + lua_register(L, "write64", write64Thunk); +} + #endif \ No newline at end of file