From 8e7e5e8c05d283b0caadc26e03303f209dd3d22a Mon Sep 17 00:00:00 2001 From: harry Date: Mon, 15 Jan 2024 09:31:53 -0500 Subject: [PATCH] Minor refactor of script memory hook interface so that both lua and js script can coexist nicely. Script engines now register themselves with the CPU module for their functions to be called. --- src/lua-engine.cpp | 22 +++++++ src/x6502.cpp | 155 ++++++++++++++++++++++++++++++++++++++------- src/x6502.h | 22 +++++++ 3 files changed, 176 insertions(+), 23 deletions(-) diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index 6ca7a4bb..d164d2db 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -118,6 +118,19 @@ bool DemandLua() #endif } +static void luaReadMemHook(unsigned int address, unsigned int value) +{ + CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_READ); +} +static void luaWriteMemHook(unsigned int address, unsigned int value) +{ + CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_WRITE); +} +static void luaExecMemHook(unsigned int address, unsigned int value) +{ + CallRegisteredLuaMemHook(address, 1, value, LUAMEMHOOK_EXEC); +} + extern "C" { #include @@ -6378,6 +6391,7 @@ void FCEU_LuaFrameBoundary() #endif } + /** * Loads and runs the given Lua script. * The emulator MUST be paused for this function to be @@ -6486,6 +6500,10 @@ int FCEU_LoadLuaCode(const char *filename, const char *arg) lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, luaMemHookTypeStrings[i]); } + + X6502_MemHook::Add( X6502_MemHook::Read , luaReadMemHook ); + X6502_MemHook::Add( X6502_MemHook::Write, luaWriteMemHook ); + X6502_MemHook::Add( X6502_MemHook::Exec , luaExecMemHook ); } // We make our thread NOW because we want it at the bottom of the stack. @@ -6601,6 +6619,10 @@ void FCEU_LuaStop() { //already killed if (!L) return; + X6502_MemHook::Remove( X6502_MemHook::Read , luaReadMemHook ); + X6502_MemHook::Remove( X6502_MemHook::Write, luaWriteMemHook ); + X6502_MemHook::Remove( X6502_MemHook::Exec , luaExecMemHook ); + // Since the script is exiting, we want to prevent an infinite loop. // CallExitFunction() > HandleCallbackError() > FCEU_LuaStop() > CallExitFunction() ... if (luaexiterrorcount > 0) { diff --git a/src/x6502.cpp b/src/x6502.cpp index 85c59362..74f008b6 100644 --- a/src/x6502.cpp +++ b/src/x6502.cpp @@ -44,13 +44,116 @@ void (*MapIRQHook)(int a); if(!overclocking) soundtimestamp+=__x; \ } +static X6502_MemHook* readMemHook = nullptr; +static X6502_MemHook* writeMemHook = nullptr; +static X6502_MemHook* execMemHook = nullptr; + +void X6502_MemHook::Add(enum X6502_MemHook::Type type, void (*func)(unsigned int address, unsigned int value) ) +{ + X6502_MemHook** hookStart = nullptr; + + switch (type) + { + case Read: + hookStart = &readMemHook; + break; + case Write: + hookStart = &writeMemHook; + break; + case Exec: + hookStart = &execMemHook; + break; + } + if (hookStart == nullptr) + { + return; + } + + if (*hookStart != nullptr) + { + X6502_MemHook* hook = *hookStart; + + while (hook->next != nullptr) + { + if (hook->func == func) + { + // Already registered + //printf("LUA MemHook Already Registered\n"); + return; + } + hook = hook->next; + } + X6502_MemHook* newHook = new X6502_MemHook(); + newHook->type = type; + newHook->func = func; + hook->next = newHook; + } + else + { + X6502_MemHook* newHook = new X6502_MemHook(); + newHook->type = type; + newHook->func = func; + *hookStart = newHook; + } + //printf("LUA MemHook Added: %p\n", func); +} + +void X6502_MemHook::Remove(enum X6502_MemHook::Type type, void (*func)(unsigned int address, unsigned int value) ) +{ + X6502_MemHook** hookStart = nullptr; + + switch (type) + { + case Read: + hookStart = &readMemHook; + break; + case Write: + hookStart = &writeMemHook; + break; + case Exec: + hookStart = &execMemHook; + break; + } + if (hookStart == nullptr) + { + return; + } + + if (*hookStart != nullptr) + { + X6502_MemHook* hook = *hookStart; + X6502_MemHook* prev = nullptr; + + while (hook != nullptr) + { + if (hook->func == func) + { + if (prev != nullptr) + { + prev->next = hook->next; + } + else + { + *hookStart = hook->next; + } + delete hook; + //printf("LUA MemHook Removed: %p\n", func); + return; + } + prev = hook; + hook = hook->next; + } + } +} + //normal memory read static INLINE uint8 RdMem(unsigned int A) { _DB=ARead[A](A); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ); - #endif + if (readMemHook) + { + readMemHook->call(A, _DB); + } return(_DB); } @@ -58,18 +161,20 @@ static INLINE uint8 RdMem(unsigned int A) static INLINE void WrMem(unsigned int A, uint8 V) { BWrite[A](A,V); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE); - #endif - _DB = V; + if (writeMemHook) + { + writeMemHook->call(A, V); + } + _DB = V; } static INLINE uint8 RdRAM(unsigned int A) { _DB=ARead[A](A); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ); - #endif + if (readMemHook) + { + readMemHook->call(A, _DB); + } //bbit edited: this was changed so cheat substituion would work // return(_DB=RAM[A]); return(_DB); @@ -78,19 +183,21 @@ static INLINE uint8 RdRAM(unsigned int A) static INLINE void WrRAM(unsigned int A, uint8 V) { RAM[A]=V; - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE); - #endif - _DB = V; + if (writeMemHook) + { + writeMemHook->call(A, V); + } + _DB = V; } uint8 X6502_DMR(uint32 A) { ADDCYC(1); _DB=ARead[A](A); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, _DB, LUAMEMHOOK_READ); - #endif + if (readMemHook) + { + readMemHook->call(A, _DB); + } return(_DB); } @@ -98,9 +205,10 @@ void X6502_DMW(uint32 A, uint8 V) { ADDCYC(1); BWrite[A](A,V); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(A, 1, V, LUAMEMHOOK_WRITE); - #endif + if (writeMemHook) + { + writeMemHook->call(A, V); + } _DB = V; } @@ -520,9 +628,10 @@ extern int test; test++; if (!overclocking) FCEU_SoundCPUHook(temp); - #ifdef _S9XLUA_H - CallRegisteredLuaMemHook(_PC, 1, 0, LUAMEMHOOK_EXEC); - #endif + if (execMemHook) + { + execMemHook->call(_PC, 0); + } _PC++; switch(b1) { diff --git a/src/x6502.h b/src/x6502.h index 460683d8..f1ba3519 100644 --- a/src/x6502.h +++ b/src/x6502.h @@ -92,5 +92,27 @@ void X6502_IRQEnd(int w); int X6502_GetOpcodeCycles( int op ); +class X6502_MemHook +{ + public: + enum Type { Read = 0, Write, Exec } type; + + static void Add(enum Type type, void (*func)(unsigned int address, unsigned int value) ); + static void Remove(enum Type type, void (*func)(unsigned int address, unsigned int value) ); + + inline void call( unsigned int address, unsigned int value ) + { + func(address, value); + + if (next != nullptr) + { + next->call(address, value); + } + } + private: + void (*func)(unsigned int address, unsigned int value) = nullptr; + X6502_MemHook* next = nullptr; +}; + #define _X6502H #endif