diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index 6ca7a4bb5..d164d2db5 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 85c593629..74f008b6f 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 460683d84..f1ba3519b 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