mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-16 02:49:48 +12:00
[Lua] Add event handles
This commit is contained in:
parent
baa9cab051
commit
7936a87fb0
3 changed files with 73 additions and 9 deletions
|
@ -2,6 +2,13 @@
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
|
||||||
|
// The kinds of events that can cause a Lua call.
|
||||||
|
// Frame: Call program on frame end
|
||||||
|
// TODO: Add more
|
||||||
|
enum class LuaEvent {
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef PANDA3DS_ENABLE_LUA
|
#ifdef PANDA3DS_ENABLE_LUA
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
@ -14,6 +21,9 @@ extern "C" {
|
||||||
class LuaManager {
|
class LuaManager {
|
||||||
lua_State* L = nullptr;
|
lua_State* L = nullptr;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
bool haveScript = false;
|
||||||
|
|
||||||
|
void signalEventInternal(LuaEvent e);
|
||||||
|
|
||||||
public:
|
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
|
// 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
|
||||||
|
@ -27,6 +37,11 @@ class LuaManager {
|
||||||
void initializeThunks();
|
void initializeThunks();
|
||||||
void loadFile(const char* path);
|
void loadFile(const char* path);
|
||||||
void reset();
|
void reset();
|
||||||
|
void signalEvent(LuaEvent e) {
|
||||||
|
if (haveScript) [[unlikely]] {
|
||||||
|
signalEventInternal(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif // Lua not enabled, Lua manager does nothing
|
#elif // Lua not enabled, Lua manager does nothing
|
||||||
|
@ -38,5 +53,6 @@ class LuaManager {
|
||||||
void initialize() {}
|
void initialize() {}
|
||||||
void loadFile(const char* path) {}
|
void loadFile(const char* path) {}
|
||||||
void reset() {}
|
void reset() {}
|
||||||
|
void signalEvent(LuaEvent e) {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -414,6 +414,7 @@ void Emulator::runFrame() {
|
||||||
if (running) {
|
if (running) {
|
||||||
cpu.runFrame(); // Run 1 frame of instructions
|
cpu.runFrame(); // Run 1 frame of instructions
|
||||||
gpu.display(); // Display graphics
|
gpu.display(); // Display graphics
|
||||||
|
lua.signalEvent(LuaEvent::Frame);
|
||||||
|
|
||||||
// Send VBlank interrupts
|
// Send VBlank interrupts
|
||||||
ServiceManager& srv = kernel.getServiceManager();
|
ServiceManager& srv = kernel.getServiceManager();
|
||||||
|
|
65
src/lua.cpp
65
src/lua.cpp
|
@ -14,12 +14,14 @@ void LuaManager::initialize() {
|
||||||
initializeThunks();
|
initializeThunks();
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
haveScript = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaManager::close() {
|
void LuaManager::close() {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
haveScript = false;
|
||||||
L = nullptr;
|
L = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,12 +31,24 @@ void LuaManager::loadFile(const char* path) {
|
||||||
int ret = lua_pcall(L, 0, 0, 0); // tell Lua to run the script
|
int ret = lua_pcall(L, 0, 0, 0); // tell Lua to run the script
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
haveScript = false;
|
||||||
fprintf(stderr, "%s\n", lua_tostring(L, -1)); // tell us what mistake we made
|
fprintf(stderr, "%s\n", lua_tostring(L, -1)); // tell us what mistake we made
|
||||||
|
} else {
|
||||||
|
haveScript = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaManager::signalEventInternal(LuaEvent e) {
|
||||||
|
lua_getglobal(L, "eventHandler"); // We want to call the event handler
|
||||||
|
lua_pushnumber(L, static_cast<int>(e)); // Push event type
|
||||||
|
|
||||||
|
// Call the function with 1 argument and 0 outputs, without an error handler
|
||||||
|
lua_pcall(L, 1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void LuaManager::reset() {
|
void LuaManager::reset() {
|
||||||
// Reset scripts
|
// Reset scripts
|
||||||
|
haveScript = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize C++ thunks for Lua code to call here
|
// Initialize C++ thunks for Lua code to call here
|
||||||
|
@ -64,18 +78,51 @@ MAKE_MEMORY_FUNCTIONS(64)
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static constexpr luaL_Reg functions[] = {
|
static constexpr luaL_Reg functions[] = {
|
||||||
{ "read8", read8Thunk },
|
{ "__read8", read8Thunk },
|
||||||
{ "read16", read16Thunk },
|
{ "__read16", read16Thunk },
|
||||||
{ "read32", read32Thunk },
|
{ "__read32", read32Thunk },
|
||||||
{ "read64", read64Thunk },
|
{ "__read64", read64Thunk },
|
||||||
{ "write8", write8Thunk} ,
|
{ "__write8", write8Thunk} ,
|
||||||
{ "write16", write16Thunk },
|
{ "__write16", write16Thunk },
|
||||||
{ "write32", write32Thunk },
|
{ "__write32", write32Thunk },
|
||||||
{ "write64", write64Thunk },
|
{ "__write64", write64Thunk },
|
||||||
{ nullptr, nullptr },
|
{ nullptr, nullptr },
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
void LuaManager::initializeThunks() { luaL_register(L, "pand", functions); }
|
void LuaManager::initializeThunks() {
|
||||||
|
static const char* runtimeInit = R"(
|
||||||
|
Pand = {
|
||||||
|
read8 = function(addr) return GLOBALS.__read8(addr) end,
|
||||||
|
read16 = function(addr) return GLOBALS.__read16(addr) end,
|
||||||
|
read32 = function(addr) return GLOBALS.__read32(addr) end,
|
||||||
|
read64 = function(addr) return GLOBALS.__read64(addr) end,
|
||||||
|
write8 = function(addr, value) GLOBALS.__write8(addr, value) end,
|
||||||
|
write16 = function(addr, value) GLOBALS.__write16(addr, value) end,
|
||||||
|
write32 = function(addr, value) GLOBALS.__write32(addr, value) end,
|
||||||
|
write64 = function(addr, value) GLOBALS.__write64(addr, value) end,
|
||||||
|
Frame = __Frame,
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto addIntConstant = [&]<typename T>(T x, const char* name) {
|
||||||
|
lua_pushinteger(L, (int)x);
|
||||||
|
lua_setglobal(L, name);
|
||||||
|
};
|
||||||
|
|
||||||
|
luaL_register(L, "GLOBALS", functions);
|
||||||
|
addIntConstant(LuaEvent::Frame, "__Frame");
|
||||||
|
|
||||||
|
// Call our Lua runtime initialization before any Lua script runs
|
||||||
|
luaL_loadstring(L, runtimeInit);
|
||||||
|
int ret = lua_pcall(L, 0, 0, 0); // tell Lua to run the script
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
initialized = false;
|
||||||
|
fprintf(stderr, "%s\n", lua_tostring(L, -1)); // Init should never fail!
|
||||||
|
} else {
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Add table
Reference in a new issue