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.

This commit is contained in:
harry 2024-01-15 09:31:53 -05:00
parent f90a269386
commit 8e7e5e8c05
3 changed files with 176 additions and 23 deletions

View File

@ -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 <lua.h>
@ -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) {

View File

@ -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
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,9 +183,10 @@ 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
if (writeMemHook)
{
writeMemHook->call(A, V);
}
_DB = V;
}
@ -88,9 +194,10 @@ 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)
{

View File

@ -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