Binary interface: Memory and register access & hooks
This commit is contained in:
parent
b18e2058cb
commit
651cb53fbe
|
@ -30,6 +30,10 @@
|
||||||
#include "lua-engine.h"
|
#include "lua-engine.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
#include "frontend/interface/interface.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_JIT
|
#ifdef HAVE_JIT
|
||||||
#include "arm_jit.h"
|
#include "arm_jit.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -699,6 +703,9 @@ FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u3
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 1, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
CallRegisteredLuaMemHook(addr, 1, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 1, HOOK_READ);
|
||||||
|
#endif
|
||||||
|
|
||||||
// break points, wheee
|
// break points, wheee
|
||||||
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
||||||
|
@ -744,6 +751,9 @@ FORCEINLINE u16 _MMU_read16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 2, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
CallRegisteredLuaMemHook(addr, 2, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 2, HOOK_READ);
|
||||||
|
#endif
|
||||||
|
|
||||||
// break points, wheee
|
// break points, wheee
|
||||||
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
||||||
|
@ -801,6 +811,9 @@ FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u
|
||||||
|
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 4, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
CallRegisteredLuaMemHook(addr, 4, /*FIXME*/ 0, LUAMEMHOOK_READ);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 4, HOOK_READ);
|
||||||
#endif
|
#endif
|
||||||
// break points, wheee
|
// break points, wheee
|
||||||
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
for (size_t i = 0; i < memReadBreakPoints.size(); ++i)
|
||||||
|
@ -883,6 +896,9 @@ FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val);
|
T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val);
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 1, HOOK_READ);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -894,6 +910,9 @@ FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val);
|
T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val);
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 1, HOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -903,6 +922,9 @@ FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 1, HOOK_WRITE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val)
|
FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val)
|
||||||
|
@ -932,6 +954,9 @@ FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val);
|
T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val);
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 2, HOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -952,6 +977,9 @@ FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 2, HOOK_WRITE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val)
|
FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val)
|
||||||
|
@ -981,6 +1009,9 @@ FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
T1WriteLong(MMU.ARM9_DTCM, addr & 0x3FFC, val);
|
T1WriteLong(MMU.ARM9_DTCM, addr & 0x3FFC, val);
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 4, HOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -993,6 +1024,9 @@ FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val);
|
T1WriteLong( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK32, val);
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 4, HOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1002,6 +1036,9 @@ FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(addr, 4, HOOK_WRITE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,9 @@
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
#include "lua-engine.h"
|
#include "lua-engine.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
#include "frontend/interface/interface.h"
|
||||||
|
#endif
|
||||||
#ifdef HAVE_JIT
|
#ifdef HAVE_JIT
|
||||||
#include "arm_jit.h"
|
#include "arm_jit.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -674,6 +677,9 @@ u32 armcpu_exec()
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
|
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 4, ARMPROC.instruction, LUAMEMHOOK_EXEC); // should report even if condition=false?
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 4, HOOK_EXEC);
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEVELOPER
|
#ifdef DEVELOPER
|
||||||
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
|
DEBUG_statistics.instructionHits[PROCNUM].arm[INSTRUCTION_INDEX(ARMPROC.instruction)]++;
|
||||||
|
@ -695,6 +701,9 @@ u32 armcpu_exec()
|
||||||
|
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
|
CallRegisteredLuaMemHook(ARMPROC.instruct_adr, 2, ARMPROC.instruction, LUAMEMHOOK_EXEC);
|
||||||
|
#endif
|
||||||
|
#ifdef TARGET_INTERFACE
|
||||||
|
call_registered_interface_mem_hook(ARMPROC.instruct_adr, 2, HOOK_EXEC);
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEVELOPER
|
#ifdef DEVELOPER
|
||||||
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
|
DEBUG_statistics.instructionHits[PROCNUM].thumb[ARMPROC.instruction>>6]++;
|
||||||
|
|
|
@ -32,6 +32,8 @@ if ( test -d ../../../../.git; ) && test "x${GIT}" != "x" -a -x "${GIT}" ; then
|
||||||
fi
|
fi
|
||||||
AC_DEFINE_UNQUOTED([GIT_COMMIT], ["$COMMIT"], [git commit hash])
|
AC_DEFINE_UNQUOTED([GIT_COMMIT], ["$COMMIT"], [git commit hash])
|
||||||
|
|
||||||
|
AC_DEFINE([TARGET_INTERFACE])
|
||||||
|
|
||||||
dnl - Check for zlib
|
dnl - Check for zlib
|
||||||
AC_CHECK_LIB(z, gzopen, [], [AC_MSG_ERROR([zlib was not found, we can't go further. Please install it or specify the location where it's installed.])])
|
AC_CHECK_LIB(z, gzopen, [], [AC_MSG_ERROR([zlib was not found, we can't go further. Please install it or specify the location where it's installed.])])
|
||||||
|
|
||||||
|
|
|
@ -25,11 +25,13 @@
|
||||||
// TODO: OSD Support isn't really done yet! Test!
|
// TODO: OSD Support isn't really done yet! Test!
|
||||||
#include "../modules/osd/agg/agg_osd.h"
|
#include "../modules/osd/agg/agg_osd.h"
|
||||||
#include "../../SPU.h"
|
#include "../../SPU.h"
|
||||||
|
#include "../../MMU.h"
|
||||||
#include "../../rasterize.h"
|
#include "../../rasterize.h"
|
||||||
#include "../../saves.h"
|
#include "../../saves.h"
|
||||||
#include "../../movie.h"
|
#include "../../movie.h"
|
||||||
#include "../../mc.h"
|
#include "../../mc.h"
|
||||||
#include "../../firmware.h"
|
#include "../../firmware.h"
|
||||||
|
#include "../../armcpu.h"
|
||||||
#include "../posix/shared/sndsdl.h"
|
#include "../posix/shared/sndsdl.h"
|
||||||
#include "../posix/shared/ctrlssdl.h"
|
#include "../posix/shared/ctrlssdl.h"
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
@ -38,6 +40,8 @@
|
||||||
|
|
||||||
#define SCREENS_PIXEL_SIZE 98304
|
#define SCREENS_PIXEL_SIZE 98304
|
||||||
volatile bool execute = false;
|
volatile bool execute = false;
|
||||||
|
TieredRegion hooked_regions [HOOK_COUNT];
|
||||||
|
std::map<unsigned int, memory_cb_fnc> hooks[HOOK_COUNT];
|
||||||
|
|
||||||
|
|
||||||
SoundInterface_struct *SNDCoreList[] = {
|
SoundInterface_struct *SNDCoreList[] = {
|
||||||
|
@ -311,29 +315,198 @@ EXPORTED void desmume_volume_set(int volume)
|
||||||
SNDSDLSetAudioVolume(volume);
|
SNDSDLSetAudioVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
EXPORTED unsigned char desmume_memory_read_byte(int address)
|
||||||
//EXPORTED unsigned char desmume_memory_read_byte(int address);
|
{
|
||||||
//EXPORTED signed char desmume_memory_read_byte_signed(int address);
|
return (unsigned char)(_MMU_read08<ARMCPU_ARM9>(address) & 0xFF);
|
||||||
//EXPORTED unsigned short desmume_memory_read_short(int address);
|
}
|
||||||
//EXPORTED signed short desmume_memory_read_short_signed(int address);
|
|
||||||
//EXPORTED unsigned long desmume_memory_read_long(int address);
|
EXPORTED signed char desmume_memory_read_byte_signed(int address)
|
||||||
//EXPORTED signed long desmume_memory_read_long_signed(int address);
|
{
|
||||||
//EXPORTED unsigned char *desmume_memory_read_byterange(int address, int length);
|
return (signed char)(_MMU_read08<ARMCPU_ARM9>(address) & 0xFF);
|
||||||
//
|
}
|
||||||
//EXPORTED void desmume_memory_write_byte(int address, unsigned char value);
|
|
||||||
//EXPORTED void desmume_memory_write_byte_signed(int address, signed char value);
|
EXPORTED unsigned short desmume_memory_read_short(int address)
|
||||||
//EXPORTED void desmume_memory_write_short(int address, unsigned short value);
|
{
|
||||||
//EXPORTED void desmume_memory_write_short_signed(int address, signed short value);
|
return (unsigned short)(_MMU_read16<ARMCPU_ARM9>(address) & 0xFFFF);
|
||||||
//EXPORTED void desmume_memory_write_long(int address, unsigned long value);
|
}
|
||||||
//EXPORTED void desmume_memory_write_long_signed(int address, signed long value);
|
|
||||||
//EXPORTED void desmume_memory_write_byterange(int address, const unsigned char *bytes);
|
EXPORTED signed short desmume_memory_read_short_signed(int address)
|
||||||
//
|
{
|
||||||
//EXPORTED long desmume_memory_read_register(char* register_name);
|
return (signed short)(_MMU_read16<ARMCPU_ARM9>(address) & 0xFFFF);
|
||||||
//EXPORTED void desmume_memory_write_register(char* register_name, long value);
|
}
|
||||||
//
|
|
||||||
//EXPORTED void desmume_memory_register_write(int address, int size, memory_cb_fnc cb);
|
EXPORTED unsigned long desmume_memory_read_long(int address)
|
||||||
//EXPORTED void desmume_memory_register_read(int address, int size, memory_cb_fnc cb);
|
{
|
||||||
//EXPORTED void desmume_memory_register_exec(int address, int size, memory_cb_fnc cb);
|
return (unsigned long)(_MMU_read32<ARMCPU_ARM9>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED signed long desmume_memory_read_long_signed(int address)
|
||||||
|
{
|
||||||
|
return (signed long)(_MMU_read32<ARMCPU_ARM9>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_write_byte(int address, unsigned char value)
|
||||||
|
{
|
||||||
|
_MMU_write08<ARMCPU_ARM9>(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_write_short(int address, unsigned short value)
|
||||||
|
{
|
||||||
|
_MMU_write16<ARMCPU_ARM9>(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_write_long(int address, unsigned long value)
|
||||||
|
{
|
||||||
|
_MMU_write32<ARMCPU_ARM9>(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct registerPointerMap
|
||||||
|
{
|
||||||
|
const char* registerName;
|
||||||
|
unsigned int* pointer;
|
||||||
|
int dataSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RPM_ENTRY(name,var) {name, (unsigned int*)&var, sizeof(var)},
|
||||||
|
|
||||||
|
registerPointerMap arm9PointerMap [] = {
|
||||||
|
RPM_ENTRY("r0", NDS_ARM9.R[0])
|
||||||
|
RPM_ENTRY("r1", NDS_ARM9.R[1])
|
||||||
|
RPM_ENTRY("r2", NDS_ARM9.R[2])
|
||||||
|
RPM_ENTRY("r3", NDS_ARM9.R[3])
|
||||||
|
RPM_ENTRY("r4", NDS_ARM9.R[4])
|
||||||
|
RPM_ENTRY("r5", NDS_ARM9.R[5])
|
||||||
|
RPM_ENTRY("r6", NDS_ARM9.R[6])
|
||||||
|
RPM_ENTRY("r7", NDS_ARM9.R[7])
|
||||||
|
RPM_ENTRY("r8", NDS_ARM9.R[8])
|
||||||
|
RPM_ENTRY("r9", NDS_ARM9.R[9])
|
||||||
|
RPM_ENTRY("r10", NDS_ARM9.R[10])
|
||||||
|
RPM_ENTRY("r11", NDS_ARM9.R[11])
|
||||||
|
RPM_ENTRY("r12", NDS_ARM9.R[12])
|
||||||
|
RPM_ENTRY("r13", NDS_ARM9.R[13])
|
||||||
|
RPM_ENTRY("r14", NDS_ARM9.R[14])
|
||||||
|
RPM_ENTRY("r15", NDS_ARM9.R[15])
|
||||||
|
RPM_ENTRY("cpsr", NDS_ARM9.CPSR.val)
|
||||||
|
RPM_ENTRY("spsr", NDS_ARM9.SPSR.val)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
registerPointerMap arm7PointerMap [] = {
|
||||||
|
RPM_ENTRY("r0", NDS_ARM7.R[0])
|
||||||
|
RPM_ENTRY("r1", NDS_ARM7.R[1])
|
||||||
|
RPM_ENTRY("r2", NDS_ARM7.R[2])
|
||||||
|
RPM_ENTRY("r3", NDS_ARM7.R[3])
|
||||||
|
RPM_ENTRY("r4", NDS_ARM7.R[4])
|
||||||
|
RPM_ENTRY("r5", NDS_ARM7.R[5])
|
||||||
|
RPM_ENTRY("r6", NDS_ARM7.R[6])
|
||||||
|
RPM_ENTRY("r7", NDS_ARM7.R[7])
|
||||||
|
RPM_ENTRY("r8", NDS_ARM7.R[8])
|
||||||
|
RPM_ENTRY("r9", NDS_ARM7.R[9])
|
||||||
|
RPM_ENTRY("r10", NDS_ARM7.R[10])
|
||||||
|
RPM_ENTRY("r11", NDS_ARM7.R[11])
|
||||||
|
RPM_ENTRY("r12", NDS_ARM7.R[12])
|
||||||
|
RPM_ENTRY("r13", NDS_ARM7.R[13])
|
||||||
|
RPM_ENTRY("r14", NDS_ARM7.R[14])
|
||||||
|
RPM_ENTRY("r15", NDS_ARM7.R[15])
|
||||||
|
RPM_ENTRY("cpsr", NDS_ARM7.CPSR.val)
|
||||||
|
RPM_ENTRY("spsr", NDS_ARM7.SPSR.val)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpuToRegisterMap
|
||||||
|
{
|
||||||
|
const char* cpuName;
|
||||||
|
registerPointerMap* rpmap;
|
||||||
|
}
|
||||||
|
cpuToRegisterMaps [] =
|
||||||
|
{
|
||||||
|
{"arm9.", arm9PointerMap},
|
||||||
|
{"main.", arm9PointerMap},
|
||||||
|
{"arm7.", arm7PointerMap},
|
||||||
|
{"sub.", arm7PointerMap},
|
||||||
|
{"", arm9PointerMap},
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPORTED int desmume_memory_read_register(char* register_name)
|
||||||
|
{
|
||||||
|
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
|
||||||
|
{
|
||||||
|
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
|
||||||
|
int cpuNameLen = strlen(ctrm.cpuName);
|
||||||
|
if(!strncasecmp(register_name, ctrm.cpuName, cpuNameLen))
|
||||||
|
{
|
||||||
|
register_name += cpuNameLen;
|
||||||
|
for(int reg = 0; ctrm.rpmap[reg].dataSize; reg++)
|
||||||
|
{
|
||||||
|
registerPointerMap rpm = ctrm.rpmap[reg];
|
||||||
|
if(!strcasecmp(register_name, rpm.registerName))
|
||||||
|
{
|
||||||
|
switch(rpm.dataSize)
|
||||||
|
{ default:
|
||||||
|
case 1: return *(unsigned char*)rpm.pointer;
|
||||||
|
case 2: return *(unsigned short*)rpm.pointer;
|
||||||
|
case 4: return *(unsigned long*)rpm.pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_write_register(char* register_name, long value)
|
||||||
|
{
|
||||||
|
for(int cpu = 0; cpu < sizeof(cpuToRegisterMaps)/sizeof(*cpuToRegisterMaps); cpu++)
|
||||||
|
{
|
||||||
|
cpuToRegisterMap ctrm = cpuToRegisterMaps[cpu];
|
||||||
|
int cpuNameLen = strlen(ctrm.cpuName);
|
||||||
|
if(!strncasecmp(register_name, ctrm.cpuName, cpuNameLen))
|
||||||
|
{
|
||||||
|
register_name += cpuNameLen;
|
||||||
|
for(int reg = 0; ctrm.rpmap[reg].dataSize; reg++)
|
||||||
|
{
|
||||||
|
registerPointerMap rpm = ctrm.rpmap[reg];
|
||||||
|
if(!strcasecmp(register_name, rpm.registerName))
|
||||||
|
{
|
||||||
|
switch(rpm.dataSize)
|
||||||
|
{ default:
|
||||||
|
case 1: *(unsigned char*)rpm.pointer = (unsigned char)(value & 0xFF); break;
|
||||||
|
case 2: *(unsigned short*)rpm.pointer = (unsigned short)(value & 0xFFFF); break;
|
||||||
|
case 4: *(unsigned long*)rpm.pointer = value; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void memory_register_hook(int addr, MemHookType hook_type, int size, memory_cb_fnc cb)
|
||||||
|
{
|
||||||
|
for(unsigned int i = addr; i != addr+size; i++)
|
||||||
|
{
|
||||||
|
hooks[hook_type][i] = cb;
|
||||||
|
}
|
||||||
|
std::vector<unsigned int> hooked_bytes;
|
||||||
|
for(std::map<unsigned int, memory_cb_fnc>::iterator it = hooks[hook_type].begin(); it != hooks[hook_type].end(); ++it) {
|
||||||
|
hooked_bytes.push_back(it->first);
|
||||||
|
}
|
||||||
|
hooked_regions[hook_type].Calculate(hooked_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_register_write(int address, int size, memory_cb_fnc cb)
|
||||||
|
{
|
||||||
|
memory_register_hook(address, HOOK_WRITE, size, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_register_read(int address, int size, memory_cb_fnc cb)
|
||||||
|
{
|
||||||
|
memory_register_hook(address, HOOK_READ, size, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORTED void desmume_memory_register_exec(int address, int size, memory_cb_fnc cb)
|
||||||
|
{
|
||||||
|
memory_register_hook(address, HOOK_EXEC, size, cb);
|
||||||
|
}
|
||||||
|
|
||||||
EXPORTED void desmume_screenshot(char *screenshot_buffer)
|
EXPORTED void desmume_screenshot(char *screenshot_buffer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,9 +44,18 @@
|
||||||
# define EXPORTED
|
# define EXPORTED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum MemHookType
|
||||||
|
{
|
||||||
|
HOOK_WRITE,
|
||||||
|
HOOK_READ,
|
||||||
|
HOOK_EXEC,
|
||||||
|
|
||||||
|
HOOK_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// callback for memory hooks: if it returns false, remove it.
|
// callback for memory hooks (get's two values: address and size of operation that triggered the hook)
|
||||||
typedef BOOL (*memory_cb_fnc)(void);
|
typedef BOOL (*memory_cb_fnc)(unsigned int, int);
|
||||||
|
|
||||||
struct SimpleDate {
|
struct SimpleDate {
|
||||||
int year;
|
int year;
|
||||||
|
@ -68,6 +77,7 @@ EXPORTED void desmume_set_savetype(int type);
|
||||||
EXPORTED void desmume_pause(void);
|
EXPORTED void desmume_pause(void);
|
||||||
EXPORTED void desmume_resume(void);
|
EXPORTED void desmume_resume(void);
|
||||||
EXPORTED void desmume_reset(void);
|
EXPORTED void desmume_reset(void);
|
||||||
|
EXPORTED void desmume_stop(void);
|
||||||
EXPORTED BOOL desmume_running(void);
|
EXPORTED BOOL desmume_running(void);
|
||||||
EXPORTED void desmume_skip_next_frame(void);
|
EXPORTED void desmume_skip_next_frame(void);
|
||||||
EXPORTED void desmume_cycle(void);
|
EXPORTED void desmume_cycle(void);
|
||||||
|
@ -115,17 +125,14 @@ EXPORTED unsigned short desmume_memory_read_short(int address);
|
||||||
EXPORTED signed short desmume_memory_read_short_signed(int address);
|
EXPORTED signed short desmume_memory_read_short_signed(int address);
|
||||||
EXPORTED unsigned long desmume_memory_read_long(int address);
|
EXPORTED unsigned long desmume_memory_read_long(int address);
|
||||||
EXPORTED signed long desmume_memory_read_long_signed(int address);
|
EXPORTED signed long desmume_memory_read_long_signed(int address);
|
||||||
EXPORTED unsigned char *desmume_memory_read_byterange(int address, int length);
|
//EXPORTED unsigned char *desmume_memory_read_byterange(int address, int length);
|
||||||
|
|
||||||
EXPORTED void desmume_memory_write_byte(int address, unsigned char value);
|
EXPORTED void desmume_memory_write_byte(int address, unsigned char value);
|
||||||
EXPORTED void desmume_memory_write_byte_signed(int address, signed char value);
|
|
||||||
EXPORTED void desmume_memory_write_short(int address, unsigned short value);
|
EXPORTED void desmume_memory_write_short(int address, unsigned short value);
|
||||||
EXPORTED void desmume_memory_write_short_signed(int address, signed short value);
|
|
||||||
EXPORTED void desmume_memory_write_long(int address, unsigned long value);
|
EXPORTED void desmume_memory_write_long(int address, unsigned long value);
|
||||||
EXPORTED void desmume_memory_write_long_signed(int address, signed long value);
|
//EXPORTED void desmume_memory_write_byterange(int address, int length, const unsigned char *bytes);
|
||||||
EXPORTED void desmume_memory_write_byterange(int address, const unsigned char *bytes);
|
|
||||||
|
|
||||||
EXPORTED long desmume_memory_read_register(char* register_name);
|
EXPORTED int desmume_memory_read_register(char* register_name);
|
||||||
EXPORTED void desmume_memory_write_register(char* register_name, long value);
|
EXPORTED void desmume_memory_write_register(char* register_name, long value);
|
||||||
|
|
||||||
EXPORTED void desmume_memory_register_write(int address, int size, memory_cb_fnc cb);
|
EXPORTED void desmume_memory_register_write(int address, int size, memory_cb_fnc cb);
|
||||||
|
@ -168,4 +175,118 @@ EXPORTED void desmume_movie_replay();
|
||||||
EXPORTED void desmume_movie_stop();
|
EXPORTED void desmume_movie_stop();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Below is mostly just from lua-engine.h, might think about how to get rid of the code duplication.
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// the purpose of this structure is to provide a way of
|
||||||
|
// QUICKLY determining whether a memory address range has a hook associated with it,
|
||||||
|
// with a bias toward fast rejection because the majority of addresses will not be hooked.
|
||||||
|
// (it must not use any part of Lua or perform any per-script operations,
|
||||||
|
// otherwise it would definitely be too slow.)
|
||||||
|
// calculating the regions when a hook is added/removed may be slow,
|
||||||
|
// but this is an intentional tradeoff to obtain a high speed of checking during later execution
|
||||||
|
struct TieredRegion
|
||||||
|
{
|
||||||
|
template<unsigned int maxGap>
|
||||||
|
struct Region
|
||||||
|
{
|
||||||
|
struct Island
|
||||||
|
{
|
||||||
|
unsigned int start;
|
||||||
|
unsigned int end;
|
||||||
|
FORCEINLINE bool Contains(unsigned int address, int size) const { return address < end && address+size > start; }
|
||||||
|
};
|
||||||
|
std::vector<Island> islands;
|
||||||
|
|
||||||
|
void Calculate(const std::vector<unsigned int>& bytes)
|
||||||
|
{
|
||||||
|
islands.clear();
|
||||||
|
|
||||||
|
unsigned int lastEnd = ~0;
|
||||||
|
|
||||||
|
std::vector<unsigned int>::const_iterator iter = bytes.begin();
|
||||||
|
std::vector<unsigned int>::const_iterator end = bytes.end();
|
||||||
|
for(; iter != end; ++iter)
|
||||||
|
{
|
||||||
|
unsigned int addr = *iter;
|
||||||
|
if(addr < lastEnd || addr > lastEnd + (long long)maxGap)
|
||||||
|
{
|
||||||
|
islands.push_back(Island());
|
||||||
|
islands.back().start = addr;
|
||||||
|
}
|
||||||
|
islands.back().end = addr+1;
|
||||||
|
lastEnd = addr+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Contains(unsigned int address, int size) const
|
||||||
|
{
|
||||||
|
typename std::vector<Island>::const_iterator iter = islands.begin();
|
||||||
|
typename std::vector<Island>::const_iterator end = islands.end();
|
||||||
|
for(; iter != end; ++iter)
|
||||||
|
if(iter->Contains(address, size))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Region<0xFFFFFFFF> broad;
|
||||||
|
Region<0x1000> mid;
|
||||||
|
Region<0> narrow;
|
||||||
|
|
||||||
|
void Calculate(std::vector<unsigned int>& bytes)
|
||||||
|
{
|
||||||
|
std::sort(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
|
broad.Calculate(bytes);
|
||||||
|
mid.Calculate(bytes);
|
||||||
|
narrow.Calculate(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
TieredRegion()
|
||||||
|
{
|
||||||
|
std::vector<unsigned int> somevector;
|
||||||
|
Calculate(somevector);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int NotEmpty()
|
||||||
|
{
|
||||||
|
return broad.islands.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: it is illegal to call this if NotEmpty() returns 0
|
||||||
|
FORCEINLINE bool Contains(unsigned int address, int size)
|
||||||
|
{
|
||||||
|
return broad.islands[0].Contains(address,size) &&
|
||||||
|
mid.Contains(address,size) &&
|
||||||
|
narrow.Contains(address,size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
extern TieredRegion hooked_regions [HOOK_COUNT];
|
||||||
|
|
||||||
|
extern std::map<unsigned int, memory_cb_fnc> hooks[HOOK_COUNT];
|
||||||
|
|
||||||
|
FORCEINLINE void call_registered_interface_mem_hook(unsigned int address, int size, MemHookType hook_type)
|
||||||
|
{
|
||||||
|
// See notes for CallRegisteredLuaMemHook!
|
||||||
|
if(hooked_regions[hook_type].NotEmpty())
|
||||||
|
{
|
||||||
|
if(hooked_regions[hook_type].Contains(address, size))
|
||||||
|
{
|
||||||
|
for(int i = address; i != address+size; i++)
|
||||||
|
{
|
||||||
|
memory_cb_fnc hook = hooks[hook_type][i];
|
||||||
|
if(hook != 0)
|
||||||
|
{
|
||||||
|
(*hook)(address, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif //DESMUME_INTERFACE_H
|
#endif //DESMUME_INTERFACE_H
|
||||||
|
|
Loading…
Reference in New Issue