Created
September 20, 2010 05:30
-
-
Save oupo/587467 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -upr src-orig/MMU.cpp src-my/MMU.cpp | |
--- src-orig/MMU.cpp 2010-08-28 04:11:00.000000000 +0900 | |
+++ src-my/MMU.cpp 2010-09-20 13:17:37.109375000 +0900 | |
@@ -988,10 +988,12 @@ void MMU_Reset() | |
MMU_timing.arm9dataCache.Reset(); | |
} | |
-void MMU_setRom(u8 * rom, u32 mask) | |
+void MMU_setRom(u8 * rom, u32 mask, FILE *file, int size) | |
{ | |
MMU.CART_ROM = rom; | |
MMU.CART_ROM_MASK = mask; | |
+ MMU.CART_ROM_FILE = file; | |
+ MMU.CART_ROM_FILE_SIZE = size; | |
rom_mask = mask; | |
} | |
@@ -999,9 +1001,35 @@ void MMU_unsetRom() | |
{ | |
MMU.CART_ROM=MMU.UNUSED_RAM; | |
MMU.CART_ROM_MASK = 3; | |
+ MMU.CART_ROM_FILE = NULL; | |
+ MMU.CART_ROM_FILE_SIZE = 0; | |
rom_mask = ROM_MASK; | |
} | |
+u16 MMU_rom_read16(u32 addr) | |
+{ | |
+#ifdef NO_LOAD_ALL_ROM | |
+ u8 buf[2]; | |
+ fseek(MMU.CART_ROM_FILE, addr, SEEK_SET); | |
+ fread(buf, 1, 2, MMU.CART_ROM_FILE); | |
+ return T1ReadWord(buf, 0); | |
+#else | |
+ return T1ReadWord(MMU.CART_ROM, addr); | |
+#endif | |
+} | |
+ | |
+u32 MMU_rom_read32(u32 addr) | |
+{ | |
+#ifdef NO_LOAD_ALL_ROM | |
+ u8 buf[4]; | |
+ fseek(MMU.CART_ROM_FILE, addr, SEEK_SET); | |
+ fread(buf, 1, 4, MMU.CART_ROM_FILE); | |
+ return T1ReadLong(buf, 0); | |
+#else | |
+ return T1ReadLong(MMU.CART_ROM, addr); | |
+#endif | |
+} | |
+ | |
static void execsqrt() { | |
u32 ret; | |
u8 mode = MMU_new.sqrt.mode; | |
diff -upr src-orig/MMU.h src-my/MMU.h | |
--- src-orig/MMU.h 2010-04-23 12:31:54.000000000 +0900 | |
+++ src-my/MMU.h 2010-09-20 13:17:37.140625000 +0900 | |
@@ -358,6 +358,8 @@ struct MMU_struct | |
//Card rom & ram | |
u8 * CART_ROM; | |
u32 CART_ROM_MASK; | |
+ FILE *CART_ROM_FILE; | |
+ int CART_ROM_FILE_SIZE; | |
u8 CART_RAM[0x10000]; | |
//Unused ram | |
@@ -460,8 +462,10 @@ void MMU_DeInit(void); | |
void MMU_Reset( void); | |
-void MMU_setRom(u8 * rom, u32 mask); | |
+void MMU_setRom(u8 * rom, u32 mask, FILE *file, int size); | |
void MMU_unsetRom( void); | |
+u16 MMU_rom_read16(u32 adr); | |
+u32 MMU_rom_read32(u32 adr); | |
void print_memory_profiling( void); | |
@@ -741,6 +745,36 @@ dunno: | |
else return _MMU_ARM7_read32(addr); | |
} | |
+#ifdef HAVE_LUA | |
+FORCEINLINE void CALL_WRITE_HOOK_08(u32 addr, u8 val) { | |
+ CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); | |
+#ifdef ENABLE_ADVANCEMENT_HOOK | |
+ CheckBytesPattern(addr, val); | |
+#endif | |
+} | |
+FORCEINLINE void CALL_WRITE_HOOK_16(u32 addr, u16 val) { | |
+ CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); | |
+#ifdef ENABLE_ADVANCEMENT_HOOK | |
+ CheckBytesPattern(addr, val & 0xff); | |
+ CheckBytesPattern(addr, val >> 8); | |
+#endif | |
+} | |
+FORCEINLINE void CALL_WRITE_HOOK_32(u32 addr, u32 val) { | |
+ CallRegisteredLuaMemHook(addr, 4, val, LUAMEMHOOK_WRITE); | |
+#ifdef ENABLE_ADVANCEMENT_HOOK | |
+ CheckBytesPattern(addr, val & 0xff); | |
+ CheckBytesPattern(addr, val >> 8 & 0xff); | |
+ CheckBytesPattern(addr, val >> 16 & 0xff); | |
+ CheckBytesPattern(addr, val >> 24); | |
+#endif | |
+} | |
+#else | |
+FORCEINLINE void CALL_WRITE_HOOK_08(u32 addr, u8 val) {} | |
+FORCEINLINE void CALL_WRITE_HOOK_16(u32 addr, u16 val) {} | |
+FORCEINLINE void CALL_WRITE_HOOK_32(u32 addr, u32 val) {} | |
+#endif | |
+ | |
+ | |
FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u8 val) | |
{ | |
CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,8,val); | |
@@ -756,25 +790,19 @@ FORCEINLINE void _MMU_write08(const int | |
if((addr&(~0x3FFF)) == MMU.DTCMRegion) | |
{ | |
T1WriteByte(MMU.ARM9_DTCM, addr & 0x3FFF, val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_08(addr, val); | |
return; | |
} | |
if ( (addr & 0x0F000000) == 0x02000000) { | |
T1WriteByte( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK, val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_08(addr, val); | |
return; | |
} | |
if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write08(addr,val); | |
else _MMU_ARM7_write08(addr,val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 1, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_08(addr, val); | |
} | |
FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val) | |
@@ -792,25 +820,19 @@ FORCEINLINE void _MMU_write16(const int | |
if((addr&(~0x3FFF)) == MMU.DTCMRegion) | |
{ | |
T1WriteWord(MMU.ARM9_DTCM, addr & 0x3FFE, val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_16(addr, val); | |
return; | |
} | |
if ( (addr & 0x0F000000) == 0x02000000) { | |
T1WriteWord( MMU.MAIN_MEM, addr & _MMU_MAIN_MEM_MASK16, val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_16(addr, val); | |
return; | |
} | |
if(PROCNUM==ARMCPU_ARM9) _MMU_ARM9_write16(addr,val); | |
else _MMU_ARM7_write16(addr,val); | |
-#ifdef HAVE_LUA | |
- CallRegisteredLuaMemHook(addr, 2, val, LUAMEMHOOK_WRITE); | |
-#endif | |
+ CALL_WRITE_HOOK_16(addr, val); | |
} | |
FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val) | |
diff -upr src-orig/NDSSystem.cpp src-my/NDSSystem.cpp | |
--- src-orig/NDSSystem.cpp 2010-09-03 20:21:10.000000000 +0900 | |
+++ src-my/NDSSystem.cpp 2010-09-20 14:18:35.828125000 +0900 | |
@@ -183,9 +183,9 @@ void NDS_DeInit(void) { | |
#endif | |
} | |
-BOOL NDS_SetROM(u8 * rom, u32 mask) | |
+BOOL NDS_SetROM(u8 * rom, u32 mask, FILE *file, int size) | |
{ | |
- MMU_setRom(rom, mask); | |
+ MMU_setRom(rom, mask, file, size); | |
return TRUE; | |
} | |
@@ -314,6 +314,9 @@ RomBanner::RomBanner(bool defaultInit) | |
bool GameInfo::hasRomBanner() | |
{ | |
+#ifdef NO_LOAD_ALL_ROM | |
+ return false; | |
+#endif | |
if(header.IconOff + sizeof(RomBanner) > romsize) | |
return false; | |
else return true; | |
@@ -423,10 +426,14 @@ static void loadrom(std::string fname) { | |
fseek(inf,0,SEEK_SET); | |
gameInfo.resize(size); | |
- fread(gameInfo.romdata,1,size,inf); | |
+#ifndef NO_LOAD_ALL_ROM | |
+ int load_size = size; | |
+#else | |
+ int load_size = gameInfo.allocatedSize; | |
+#endif | |
+ fread(gameInfo.romdata,1,load_size,inf); | |
gameInfo.fillGap(); | |
- | |
- fclose(inf); | |
+ gameInfo.file = inf; | |
} | |
int NDS_LoadROM(const char *filename, const char *logicalFilename) | |
@@ -459,8 +466,13 @@ int NDS_LoadROM(const char *filename, co | |
if(type == ROM_DSGBA) | |
{ | |
+#ifndef NO_LOAD_ALL_ROM | |
std::vector<char> v(gameInfo.romdata + DSGBA_LOADER_SIZE, gameInfo.romdata + gameInfo.romsize); | |
gameInfo.loadData(&v[0],gameInfo.romsize - DSGBA_LOADER_SIZE); | |
+#else | |
+ printf("ROM_DSGBA not implemented\n"); | |
+#endif | |
+ return -1; | |
} | |
//check that size is at least the size of the header | |
@@ -471,7 +483,7 @@ int NDS_LoadROM(const char *filename, co | |
//decrypt if necessary.. | |
//but this is untested and suspected to fail on big endian, so lets not support this on big endian | |
-#ifndef WORDS_BIGENDIAN | |
+#if !defined(WORDS_BIGENDIAN) && !defined(NO_LOAD_ALL_ROM) | |
bool okRom = DecryptSecureArea((u8*)gameInfo.romdata,gameInfo.romsize); | |
if(!okRom) { | |
@@ -485,18 +497,22 @@ int NDS_LoadROM(const char *filename, co | |
FCEUI_StopMovie(); | |
MMU_unsetRom(); | |
- NDS_SetROM((u8*)gameInfo.romdata, gameInfo.mask); | |
+ NDS_SetROM((u8*)gameInfo.romdata, gameInfo.mask, gameInfo.file, gameInfo.romsize); | |
gameInfo.populate(); | |
+#ifndef NO_LOAD_ALL_ROM | |
gameInfo.crc = crc32(0,(u8*)gameInfo.romdata,gameInfo.romsize); | |
INFO("\nROM crc: %08X\n", gameInfo.crc); | |
+#endif | |
INFO("ROM serial: %s\n", gameInfo.ROMserial); | |
INFO("ROM internal name: %s\n\n", gameInfo.ROMname); | |
INFO("ROM game code: %c%c%c%c\n\n", gameInfo.header.gameCode[0], gameInfo.header.gameCode[1], gameInfo.header.gameCode[2], gameInfo.header.gameCode[3]); | |
+#ifndef NO_LOAD_ALL_ROM | |
//for homebrew, try auto-patching DLDI. should be benign if there is no DLDI or if it fails | |
if(!memcmp(gameInfo.header.gameCode,"####",4)) | |
DLDI::tryPatch((void*)gameInfo.romdata, gameInfo.romsize); | |
+#endif | |
NDS_Reset(); | |
@@ -643,6 +659,10 @@ void NDS_FreeROM(void) | |
gameInfo.romdata = NULL; | |
if (MMU.CART_ROM != MMU.UNUSED_RAM) | |
delete [] MMU.CART_ROM; | |
+ if (gameInfo.file != NULL) { | |
+ fclose(gameInfo.file); | |
+ gameInfo.file = NULL; | |
+ } | |
MMU_unsetRom(); | |
} | |
@@ -2305,7 +2325,7 @@ void NDS_Reset() | |
//INFO("Copy secure area from 0x%08X to 0x%08X (size %i/0x%08X)\n", src, dst, size, size); | |
for (u32 i = 0; i < size; i++) | |
{ | |
- _MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src)); | |
+ _MMU_write32<ARMCPU_ARM9>(dst, MMU_rom_read32(src)); | |
src += 4; dst += 4; | |
} | |
} | |
@@ -2335,7 +2355,7 @@ void NDS_Reset() | |
for(u32 i = 0; i < (header->ARM9binSize>>2); ++i) | |
{ | |
- _MMU_write32<ARMCPU_ARM9>(dst, T1ReadLong(MMU.CART_ROM, src)); | |
+ _MMU_write32<ARMCPU_ARM9>(dst, MMU_rom_read32(src)); | |
dst += 4; | |
src += 4; | |
} | |
@@ -2345,7 +2365,7 @@ void NDS_Reset() | |
for(u32 i = 0; i < (header->ARM7binSize>>2); ++i) | |
{ | |
- _MMU_write32<ARMCPU_ARM7>(dst, T1ReadLong(MMU.CART_ROM, src)); | |
+ _MMU_write32<ARMCPU_ARM7>(dst, MMU_rom_read32(src)); | |
dst += 4; | |
src += 4; | |
} | |
@@ -2411,10 +2431,10 @@ void NDS_Reset() | |
//zero 27-jun-09 : why did this copy 0x90 more? gbatek says its not stored in ram. | |
//for (i = 0; i < ((0x170+0x90)/4); i++) { | |
for (int i = 0; i < ((0x170)/4); i++) | |
- _MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); | |
+ _MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, MMU_rom_read32(i*4)); | |
// Write the header checksum to memory (the firmware needs it to see the cart) | |
- _MMU_write16<ARMCPU_ARM9>(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E)); | |
+ _MMU_write16<ARMCPU_ARM9>(0x027FF808, MMU_rom_read16(0x15E)); | |
//-------------------------------- | |
//setup the homebrew argv | |
diff -upr src-orig/NDSSystem.h src-my/NDSSystem.h | |
--- src-orig/NDSSystem.h 2010-09-10 08:04:16.000000000 +0900 | |
+++ src-my/NDSSystem.h 2010-09-20 13:44:20.250000000 +0900 | |
@@ -270,7 +270,7 @@ void Desmume_InitOnce(); | |
void NDS_DeInit(void); | |
-BOOL NDS_SetROM(u8 * rom, u32 mask); | |
+BOOL NDS_SetROM(u8 * rom, u32 mask, FILE *file, int size); | |
NDS_header * NDS_getROMHeader(void); | |
struct RomBanner | |
@@ -304,6 +304,7 @@ struct GameInfo | |
: romdata(NULL) | |
{} | |
+#ifndef NO_LOAD_ALL_ROM | |
void loadData(char* buf, int size) | |
{ | |
resize(size); | |
@@ -311,15 +312,19 @@ struct GameInfo | |
romsize = (u32)size; | |
fillGap(); | |
} | |
+#endif | |
void fillGap() | |
{ | |
+#ifndef NO_LOAD_ALL_ROM | |
memset(romdata+romsize,0xFF,allocatedSize-romsize); | |
+#endif | |
} | |
void resize(int size) { | |
if(romdata != NULL) delete[] romdata; | |
+#ifndef NO_LOAD_ALL_ROM | |
//calculate the necessary mask for the requested size | |
mask = size-1; | |
mask |= (mask >>1); | |
@@ -331,6 +336,10 @@ struct GameInfo | |
//now, we actually need to over-allocate, because bytes from anywhere protected by that mask | |
//could be read from the rom | |
allocatedSize = mask+1; | |
+#else | |
+ allocatedSize = 512; | |
+ mask = 511; | |
+#endif | |
romdata = new char[allocatedSize]; | |
romsize = size; | |
@@ -345,6 +354,7 @@ struct GameInfo | |
u32 romsize; | |
u32 allocatedSize; | |
u32 mask; | |
+ FILE *file; | |
const RomBanner& getRomBanner(); | |
bool hasRomBanner(); | |
}; | |
diff -upr src-orig/addons/slot1_retail.cpp src-my/addons/slot1_retail.cpp | |
--- src-orig/addons/slot1_retail.cpp 2010-08-06 18:39:36.000000000 +0900 | |
+++ src-my/addons/slot1_retail.cpp 2010-09-20 13:32:35.812500000 +0900 | |
@@ -127,7 +127,7 @@ static u32 read32_GCDATAIN(u8 PROCNUM) | |
} | |
//but, this is actually handled by the cart rom buffer being oversized and full of 0xFF. | |
//is this a good idea? We think so. | |
- return T1ReadLong(MMU.CART_ROM, card.address & MMU.CART_ROM_MASK); | |
+ return MMU_rom_read32(card.address); | |
} | |
break; | |
default: | |
diff -upr src-orig/arm_instructions.cpp src-my/arm_instructions.cpp | |
--- src-orig/arm_instructions.cpp 2010-05-16 08:23:10.000000000 +0900 | |
+++ src-my/arm_instructions.cpp 2010-09-20 13:17:37.171875000 +0900 | |
@@ -3207,6 +3207,12 @@ TEMPLATE static u32 FASTCALL OP_BX(cons | |
{ | |
u32 tmp = cpu->R[REG_POS(i, 0)]; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ if (REG_POS(i, 0) == 14) | |
+ { | |
+ LogReturn(cpu->instruct_adr, cpu->R[0]); | |
+ } | |
+#endif | |
if (REG_POS(i, 0) == 15) | |
{ | |
printf("ARM%c: BX using PC as operand\n", PROCNUM?'7':'9'); | |
@@ -4976,6 +4982,12 @@ TEMPLATE static u32 FASTCALL OP_LDMIA_W | |
u32 start = cpu->R[REG_POS(i,16)]; | |
u32 bitList = (~((2 << REG_POS(i,16))-1)) & 0xFFFF; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ if (REG_POS(i,16) == 13 && BIT15(i)) { | |
+ LogReturn(cpu->instruct_adr, cpu->R[0]); | |
+ } | |
+#endif | |
+ | |
u32 * registres = cpu->R; | |
OP_L_IA(0, start); | |
@@ -5767,6 +5779,12 @@ TEMPLATE static u32 FASTCALL OP_STMDB_W | |
u32 c = 0, b; | |
u32 start = cpu->R[REG_POS(i,16)]; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ if (REG_POS(i,16) == 13 && BIT_N(i, 14) && PROCNUM == 0) { | |
+ CallRegisteredLuaFunctions(LUACALL_ENTERFUNCTION); | |
+ } | |
+#endif | |
+ | |
for(b=0; b<16; b++) | |
{ | |
if(BIT_N(i, 15-b)) | |
diff -upr src-orig/armcpu.cpp src-my/armcpu.cpp | |
--- src-orig/armcpu.cpp 2010-08-10 19:07:56.000000000 +0900 | |
+++ src-my/armcpu.cpp 2010-09-20 13:17:37.171875000 +0900 | |
@@ -408,6 +408,9 @@ FORCEINLINE static u32 armcpu_prefetch() | |
// u32 temp_instruction; | |
//#endif | |
u32 curInstruction = armcpu->next_instruction; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ armcpu->prev_instruct_adr = armcpu->instruct_adr; | |
+#endif | |
if(armcpu->CPSR.bits.T == 0) | |
{ | |
@@ -685,7 +688,7 @@ u32 armcpu_exec() | |
{ | |
if( | |
CONDITION(ARMPROC.instruction) == 0x0E //fast path for unconditional instructions | |
- || (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), ARMPROC.CPSR)) //handles any condition | |
+ || (TEST_COND(CONDITION(ARMPROC.instruction), CODE(ARMPROC.instruction), &ARMPROC)) //handles any condition | |
) | |
{ | |
#ifdef HAVE_LUA | |
diff -upr src-orig/armcpu.h src-my/armcpu.h | |
--- src-orig/armcpu.h 2010-07-05 00:19:16.000000000 +0900 | |
+++ src-my/armcpu.h 2010-09-20 13:17:37.187500000 +0900 | |
@@ -99,9 +99,6 @@ inline bool OverflowFromSUB(s32 alu_out, | |
extern const unsigned char arm_cond_table[16*16]; | |
-#define TEST_COND(cond, inst, CPSR) ((arm_cond_table[((CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst))) | |
- | |
- | |
enum Mode | |
{ | |
USR = 0x10, | |
@@ -235,6 +232,9 @@ struct armcpu_t | |
/** the ctrl interface */ | |
struct armcpu_ctrl_iface ctrl_iface; | |
#endif | |
+ | |
+ | |
+ u32 prev_instruct_adr; | |
}; | |
#ifdef GDB_STUB | |
@@ -317,4 +317,17 @@ static INLINE char *decodeIntruction(boo | |
return strdup(txt); | |
} | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+#include "lua-engine.h" | |
+#endif | |
+ | |
+static inline bool TEST_COND(u32 cond, u32 inst, armcpu_t *cpu) | |
+{ | |
+ bool c = ((arm_cond_table[((cpu->CPSR.val >> 24) & 0xf0)|(cond)]) & (1 << (inst))); | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ LogCond(cpu->instruct_adr, c); | |
+#endif | |
+ return c; | |
+} | |
+ | |
#endif | |
diff -upr src-orig/lua-engine.cpp src-my/lua-engine.cpp | |
--- src-orig/lua-engine.cpp 2010-09-18 13:44:46.000000000 +0900 | |
+++ src-my/lua-engine.cpp 2010-09-20 13:47:39.078125000 +0900 | |
@@ -11,6 +11,7 @@ | |
#include "GPU_osd.h" | |
#include "saves.h" | |
#include "emufile.h" | |
+#include "Disassembler.h" | |
#if defined(WIN32) && !defined(WXPORT) | |
#include "main.h" | |
#include "windows.h" | |
@@ -154,6 +155,9 @@ static const char* luaCallIDStrings [] = | |
"CALL_HOTKEY_14", | |
"CALL_HOTKEY_15", | |
"CALL_HOTKEY_16", | |
+ | |
+ "CALL_ENTERFUNCTION", | |
+ "CALL_BYTES_PATTERN", | |
}; | |
static const int _makeSureWeHaveTheRightNumberOfStrings [sizeof(luaCallIDStrings)/sizeof(*luaCallIDStrings) == LUACALL_COUNT ? 1 : 0]; | |
@@ -402,6 +406,275 @@ DEFINE_LUA_FUNCTION(input_registerhotkey | |
} | |
} | |
+DEFINE_LUA_FUNCTION(emu_registerenterfunc, "func") | |
+{ | |
+ if (!lua_isnil(L,1)) | |
+ luaL_checktype(L, 1, LUA_TFUNCTION); | |
+ lua_settop(L,1); | |
+ lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ENTERFUNCTION]); | |
+ lua_insert(L,1); | |
+ lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ENTERFUNCTION]); | |
+ StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); | |
+ return 1; | |
+} | |
+ | |
+struct INSN_ADDR_AND_VAL { | |
+ u32 addr; | |
+ u32 val; | |
+ | |
+ bool operator<(const INSN_ADDR_AND_VAL& x) const { | |
+ return memcmp(this, &x, sizeof(INSN_ADDR_AND_VAL)) < 0; | |
+ } | |
+ | |
+ bool operator==(const INSN_ADDR_AND_VAL& x) const { | |
+ return memcmp(this, &x, sizeof(INSN_ADDR_AND_VAL)) == 0; | |
+ } | |
+ | |
+}; | |
+ | |
+typedef std::map<INSN_ADDR_AND_VAL, std::vector<bool> > LOGCOND_RESULT_T; | |
+ | |
+bool logCondMode = false; | |
+static struct { | |
+ std::string filename; | |
+ int max; | |
+ LOGCOND_RESULT_T result; | |
+} logCondState; | |
+ | |
+ | |
+void printfToOutput(const char* fmt, ...); | |
+ | |
+DEFINE_LUA_FUNCTION(emu_start_log_cond, "filename,max") | |
+{ | |
+ const char *filename = luaL_checkstring(L,1); | |
+ int max = luaL_checkinteger(L,2); | |
+ logCondMode = true; | |
+ logCondState.filename = filename; | |
+ logCondState.max = max; | |
+ logCondState.result.clear(); | |
+ printfToOutput("start_log_cond:%s", filename); | |
+ return 0; | |
+} | |
+ | |
+DEFINE_LUA_FUNCTION(emu_end_log_cond, "") | |
+{ | |
+ logCondMode = false; | |
+ FILE *fp = fopen(logCondState.filename.c_str(), "wb"); | |
+ LOGCOND_RESULT_T::iterator it = logCondState.result.begin(); | |
+ for (; it != logCondState.result.end(); ++ it) { | |
+ INSN_ADDR_AND_VAL key = (*it).first; | |
+ std::vector<bool> &v = (*it).second; | |
+ fprintf(fp, "%.8x(%.8x):", key.addr, key.val); | |
+ for (int i = 0; i < v.size(); i ++) { | |
+ if (v[i]) { | |
+ fprintf(fp, "T"); | |
+ } else { | |
+ fprintf(fp, "F"); | |
+ } | |
+ } | |
+ fprintf(fp, "\n"); | |
+ } | |
+ fclose(fp); | |
+ logCondState.filename = ""; | |
+ logCondState.max = 0; | |
+ logCondState.result.clear(); | |
+ printfToOutput("end_log_cond"); | |
+ return 0; | |
+} | |
+ | |
+void LogCondInner(u32 addr, bool cond) | |
+{ | |
+ INSN_ADDR_AND_VAL key; | |
+ key.addr = addr; | |
+ key.val = _MMU_read32<ARMCPU_ARM9>(addr); | |
+ LOGCOND_RESULT_T::iterator it = logCondState.result.find(key); | |
+ if (it == logCondState.result.end()) { | |
+ std::vector<bool> v; | |
+ v.push_back(cond); | |
+ logCondState.result[key] = v; | |
+ } else { | |
+ std::vector<bool> &v = (*it).second; | |
+ if (v.size() < logCondState.max) { | |
+ v.push_back(cond); | |
+ } | |
+ } | |
+} | |
+ | |
+typedef std::map<INSN_ADDR_AND_VAL, std::vector<u32> > LOGRETURN_RESULT_T; | |
+ | |
+bool logReturnMode = false; | |
+static struct { | |
+ std::string filename; | |
+ int max; | |
+ LOGRETURN_RESULT_T result; | |
+} logReturnState; | |
+ | |
+DEFINE_LUA_FUNCTION(emu_start_log_return, "filename,max") | |
+{ | |
+ const char *filename = luaL_checkstring(L,1); | |
+ int max = luaL_checkinteger(L,2); | |
+ logReturnMode = true; | |
+ logReturnState.filename = filename; | |
+ logReturnState.max = max; | |
+ logReturnState.result.clear(); | |
+ printfToOutput("start_log_return:%s", filename); | |
+ return 0; | |
+} | |
+ | |
+DEFINE_LUA_FUNCTION(emu_end_log_return, "") | |
+{ | |
+ logReturnMode = false; | |
+ FILE *fp = fopen(logReturnState.filename.c_str(), "wb"); | |
+ LOGRETURN_RESULT_T::iterator it = logReturnState.result.begin(); | |
+ for (; it != logReturnState.result.end(); ++ it) { | |
+ INSN_ADDR_AND_VAL key = (*it).first; | |
+ std::vector<u32> &v = (*it).second; | |
+ fprintf(fp, "%.8x(%.8x):", key.addr, key.val); | |
+ for (int i = 0; i < v.size(); i ++) { | |
+ if (i > 0) fprintf(fp, ","); | |
+ fprintf(fp, "%.8x", v[i]); | |
+ } | |
+ fprintf(fp, "\n"); | |
+ } | |
+ fclose(fp); | |
+ logReturnState.filename = ""; | |
+ logReturnState.max = 0; | |
+ logReturnState.result.clear(); | |
+ printfToOutput("end_log_return"); | |
+ return 0; | |
+} | |
+ | |
+void LogReturnInner(u32 addr, u32 val) | |
+{ | |
+ INSN_ADDR_AND_VAL key; | |
+ key.addr = addr; | |
+ key.val = _MMU_read32<ARMCPU_ARM9>(addr); | |
+ LOGRETURN_RESULT_T::iterator it = logReturnState.result.find(key); | |
+ if (it == logReturnState.result.end()) { | |
+ std::vector<u32> v; | |
+ v.push_back(val); | |
+ logReturnState.result[key] = v; | |
+ } else { | |
+ std::vector<u32> &v = (*it).second; | |
+ if (v.size() < logReturnState.max) { | |
+ v.push_back(val); | |
+ } | |
+ } | |
+} | |
+ | |
+static char *str_tolower(char *txt) { | |
+ for (int i = 0; txt[i] != '\0'; i ++) { | |
+ txt[i] = tolower(txt[i]); | |
+ } | |
+ return txt; | |
+} | |
+ | |
+static void fix_arm_disasm(u32 addr, u32 ins, char *txt) | |
+{ | |
+ str_tolower(txt); | |
+ if ((ins & 0x0FF00000) == 0x05900000 && REG_POS(ins,16) == 15) { // OP_LDR_P_IMM_OFF | |
+ u32 val = _MMU_read32<ARMCPU_ARM9>(addr + 8 + (int)(ins&0x7FF)); | |
+ sprintf(txt + strlen(txt), " ; %.8x", val); | |
+ } | |
+ if ((ins & 0x0FF00000) == 0x05100000 && REG_POS(ins,16) == 15) { // OP_LDR_M_IMM_OFF | |
+ u32 val = _MMU_read32<ARMCPU_ARM9>(addr + 8 - (int)(ins&0x7FF)); | |
+ sprintf(txt + strlen(txt), " ; %.8x", val); | |
+ } | |
+} | |
+ | |
+static void fix_thumb_disasm(u32 addr, u32 ins, char *txt) | |
+{ | |
+ str_tolower(txt); | |
+ if ((ins & 0xf800) == 0x4800) { // OP_LDR_PCREL | |
+ u32 val = _MMU_read32<ARMCPU_ARM9>((addr + 4 & 0xFFFFFFFC) + (int)((ins&0xFF)<<2)); | |
+ sprintf(txt + strlen(txt), " ; %.8x", val); | |
+ } | |
+} | |
+ | |
+#define SIGNEXTEND_24(i) (((s32)i<<8)>>8) | |
+#define SIGNEEXT_IMM11(i) (((i)&0x7FF) | (BIT10(i) * 0xFFFFF800)) | |
+ | |
+static u32 get_jump_destionation_arm(u32 addr, u32 ins) | |
+{ | |
+ if ((ins & 0x0f000000) == 0x0a000000 && CONDITION(ins)!=0xF) { // OP_B | |
+ return addr+(SIGNEXTEND_24(ins)<<2)+8; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static u32 get_jump_destionation_thumb(u32 addr, u32 ins) | |
+{ | |
+ if (0xd000 <= ins && ins <= 0xdeff) { // OP_B_COND | |
+ return addr+(((s32)((signed char)(ins&0xFF)))<<1)+4; | |
+ } | |
+ if (0xe000 <= ins && ins <= 0xe7ff) { // OP_B_UNCOND | |
+ return addr+(SIGNEEXT_IMM11(ins)<<1)+4; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static void gen_insn_referred(std::vector<bool> &referred, u32 start_addr, u32 end_addr, bool is_thumb) | |
+{ | |
+ int insn_size = is_thumb ? 2 : 4; | |
+ referred.resize((end_addr - start_addr) / insn_size, false); | |
+ for (u32 addr = start_addr; addr < end_addr; addr += insn_size) { | |
+ u32 dest_addr; | |
+ if (is_thumb) { | |
+ dest_addr = get_jump_destionation_thumb(addr, _MMU_read16<ARMCPU_ARM9>(addr)); | |
+ } else { | |
+ dest_addr = get_jump_destionation_arm(addr, _MMU_read32<ARMCPU_ARM9>(addr)); | |
+ } | |
+ if (dest_addr != 0 && start_addr <= dest_addr && dest_addr < end_addr) { | |
+ referred[(dest_addr - start_addr) / insn_size] = true; | |
+ } | |
+ } | |
+} | |
+ | |
+static void OutputDisasm(const char *filename, int start_addr, int len, bool is_thumb) | |
+{ | |
+ FILE *fp = fopen(filename, "wb"); | |
+ char txt[100]; | |
+ std::vector<bool> referred; | |
+ u32 end_addr = start_addr + len; | |
+ gen_insn_referred(referred, start_addr, end_addr, is_thumb); | |
+ | |
+ for (u32 addr = start_addr, i = 0; addr < end_addr; addr += is_thumb ? 2 : 4, i ++) { | |
+ u32 ins, dest_addr; | |
+ if (is_thumb) { | |
+ ins = _MMU_read16<ARMCPU_ARM9>(addr); | |
+ des_thumb_instructions_set[ins>>6](addr, ins, txt); | |
+ fix_thumb_disasm(addr, ins, txt); | |
+ dest_addr = get_jump_destionation_thumb(addr, ins); | |
+ } else { | |
+ ins = _MMU_read32<ARMCPU_ARM9>(addr); | |
+ des_arm_instructions_set[INSTRUCTION_INDEX(ins)](addr, ins, txt); | |
+ fix_arm_disasm(addr, ins, txt); | |
+ dest_addr = get_jump_destionation_arm(addr, ins); | |
+ } | |
+ char c = (dest_addr != 0 && dest_addr < addr) ? '*' : referred[i] ? '|' : ':'; | |
+ fprintf(fp, "%c%08X %0*X %s\n", c, addr, is_thumb ? 4 : 8, ins, txt); | |
+ } | |
+ fclose(fp); | |
+} | |
+ | |
+DEFINE_LUA_FUNCTION(emu_output_disasm_arm, "filename,addr,len") | |
+{ | |
+ const char *filename = luaL_checkstring(L,1); | |
+ int addr = luaL_checkinteger(L,2); | |
+ int len = luaL_checkinteger(L,3); | |
+ OutputDisasm(filename, addr, len, false); | |
+ return 0; | |
+} | |
+ | |
+DEFINE_LUA_FUNCTION(emu_output_disasm_thumb, "filename,addr,len") | |
+{ | |
+ const char *filename = luaL_checkstring(L,1); | |
+ int addr = luaL_checkinteger(L,2); | |
+ int len = luaL_checkinteger(L,3); | |
+ OutputDisasm(filename, addr, len, true); | |
+ return 0; | |
+} | |
+ | |
static int doPopup(lua_State* L, const char* deftype, const char* deficon) | |
{ | |
const char* str = toCString(L,1); | |
@@ -1827,6 +2100,9 @@ registerPointerMap arm9PointerMap [] = { | |
RPM_ENTRY("r15", NDS_ARM9.R[15]) | |
RPM_ENTRY("cpsr", NDS_ARM9.CPSR.val) | |
RPM_ENTRY("spsr", NDS_ARM9.SPSR.val) | |
+ RPM_ENTRY("prev_insn_addr", NDS_ARM9.prev_instruct_adr) | |
+ RPM_ENTRY("curr_insn_addr", NDS_ARM9.instruct_adr) | |
+ RPM_ENTRY("next_insn_addr", NDS_ARM9.next_instruction) | |
{} | |
}; | |
registerPointerMap arm7PointerMap [] = { | |
@@ -1848,6 +2124,9 @@ registerPointerMap arm7PointerMap [] = { | |
RPM_ENTRY("r15", NDS_ARM7.R[15]) | |
RPM_ENTRY("cpsr", NDS_ARM7.CPSR.val) | |
RPM_ENTRY("spsr", NDS_ARM7.SPSR.val) | |
+ RPM_ENTRY("prev_insn_addr", NDS_ARM7.prev_instruct_adr) | |
+ RPM_ENTRY("curr_insn_addr", NDS_ARM7.instruct_adr) | |
+ RPM_ENTRY("next_insn_addr", NDS_ARM7.next_instruction) | |
{} | |
}; | |
@@ -1930,6 +2209,62 @@ DEFINE_LUA_FUNCTION(memory_setregister, | |
return 0; | |
} | |
+BYTES_PATTERN_WATCH_STATE bytesPatternWatchState = {false, std::vector<u8>(), 0}; | |
+ | |
+DEFINE_LUA_FUNCTION(memory_register_bytes_pattern, "bytes,func") | |
+{ | |
+ lua_settop(L,2); | |
+ int bytes_index = 1, func_index = 2; | |
+ luaL_checktype(L, bytes_index, LUA_TTABLE); | |
+ if (lua_isnil(L,func_index)) { | |
+ bytesPatternWatchState.enabled = false; | |
+ bytesPatternWatchState.bytes.clear(); | |
+ bytesPatternWatchState.last_val = 0; | |
+ } else { | |
+ luaL_checktype(L, func_index, LUA_TFUNCTION); | |
+ | |
+ int len = lua_objlen(L, bytes_index); | |
+ if (len == 0) { | |
+ luaL_error(L, "memory.register_bytes_pattern: #bytes == 0"); | |
+ } | |
+ | |
+ bytesPatternWatchState.enabled = true; | |
+ bytesPatternWatchState.bytes.clear(); | |
+ bytesPatternWatchState.bytes.reserve(len); | |
+ int arrayValIndex = lua_gettop(L) + 1; | |
+ for (int i = 0; i < len; i ++) { | |
+ lua_rawgeti(L, bytes_index, i + 1); | |
+ int val = lua_tointeger(L, arrayValIndex) & 0xff; | |
+ lua_pop(L, 1); | |
+ bytesPatternWatchState.bytes.push_back(val); | |
+ } | |
+ bytesPatternWatchState.last_val = bytesPatternWatchState.bytes[len - 1]; | |
+ | |
+ } | |
+ | |
+ // stack = {bytes, func} | |
+ lua_replace(L,1); // stack = {func} | |
+ lua_getfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_ENTERFUNCTION]); // stack = {func, prev_func} | |
+ lua_insert(L,1); // stack = {prev_func, func} | |
+ lua_setfield(L, LUA_REGISTRYINDEX, luaCallIDStrings[LUACALL_BYTES_PATTERN]); // stack = {prev_func} | |
+ StopScriptIfFinished(luaStateToUIDMap[L->l_G->mainthread]); | |
+ return 1; | |
+} | |
+ | |
+void CheckBytesPatternInner(u32 addr) | |
+{ | |
+ int len = bytesPatternWatchState.bytes.size(); | |
+ addr -= len - 1; | |
+ for (int i = 0; i < len; i ++) { | |
+ if (bytesPatternWatchState.bytes[i] != _MMU_read08<ARMCPU_ARM9>(addr+i)) { | |
+ return; | |
+ } | |
+ } | |
+ std::vector<int> args; | |
+ args.push_back(addr); | |
+ CallRegisteredLuaFunctionsWithArgs(LUACALL_BYTES_PATTERN, args); | |
+} | |
+ | |
DEFINE_LUA_FUNCTION(state_create, "[location]") | |
{ | |
if(lua_isnumber(L,1)) | |
@@ -4135,6 +4470,13 @@ static const struct luaL_reg emulib [] = | |
{"reset", emu_reset}, | |
// alternative names | |
// {"openrom", emu_loadrom}, | |
+ {"registerenterfunc", emu_registerenterfunc}, | |
+ {"start_log_cond", emu_start_log_cond}, | |
+ {"end_log_cond", emu_end_log_cond}, | |
+ {"start_log_return", emu_start_log_return}, | |
+ {"end_log_return", emu_end_log_return}, | |
+ {"output_disasm_arm", emu_output_disasm_arm}, | |
+ {"output_disasm_thumb", emu_output_disasm_thumb}, | |
{NULL, NULL} | |
}; | |
static const struct luaL_reg guilib [] = | |
@@ -4219,6 +4561,8 @@ static const struct luaL_reg memorylib [ | |
{"registerrun", memory_registerexec}, | |
{"registerexecute", memory_registerexec}, | |
+ {"register_bytes_pattern", memory_register_bytes_pattern}, | |
+ | |
{NULL, NULL} | |
}; | |
static const struct luaL_reg joylib [] = | |
@@ -4576,6 +4920,8 @@ void RunLuaScriptFile(int uid, const cha | |
{ | |
if(luaContextInfo.find(uid) == luaContextInfo.end()) | |
return; | |
+ std::string dirname = string(filenameCStr) + "/.."; | |
+ SetCurrentDirectory(dirname.c_str()); | |
StopLuaScript(uid); | |
LuaContextInfo& info = *luaContextInfo[uid]; | |
@@ -5042,7 +5388,7 @@ bool AnyLuaActive() | |
return false; | |
} | |
-void CallRegisteredLuaFunctions(LuaCallID calltype) | |
+void CallRegisteredLuaFunctionsWithArgs(LuaCallID calltype, const std::vector<int> &args) | |
{ | |
assert((unsigned int)calltype < (unsigned int)LUACALL_COUNT); | |
const char* idstring = luaCallIDStrings[calltype]; | |
@@ -5079,7 +5425,10 @@ void CallRegisteredLuaFunctions(LuaCallI | |
bool wasRunning = info.running; | |
info.running = true; | |
RefreshScriptSpeedStatus(); | |
- int errorcode = lua_pcall(L, 0, 0, 0); | |
+ for (int i = 0; i < args.size(); i ++) { | |
+ lua_pushinteger(L, args[i]); | |
+ } | |
+ int errorcode = lua_pcall(L, args.size(), 0, 0); | |
info.running = wasRunning; | |
RefreshScriptSpeedStatus(); | |
if (errorcode) | |
@@ -5103,6 +5452,12 @@ void CallRegisteredLuaFunctions(LuaCallI | |
} | |
} | |
+void CallRegisteredLuaFunctions(LuaCallID calltype) | |
+{ | |
+ std::vector<int> args; | |
+ CallRegisteredLuaFunctionsWithArgs(calltype, args); | |
+} | |
+ | |
void CallRegisteredLuaSaveFunctions(int savestateNumber, LuaSaveData& saveData) | |
{ | |
const char* idstring = luaCallIDStrings[LUACALL_BEFORESAVE]; | |
diff -upr src-orig/lua-engine.h src-my/lua-engine.h | |
--- src-orig/lua-engine.h 2009-10-17 00:46:36.000000000 +0900 | |
+++ src-my/lua-engine.h 2010-09-20 13:47:36.015625000 +0900 | |
@@ -2,6 +2,8 @@ | |
#define LUA_SCRIPT_H | |
#include "types.h" | |
+#include <vector> | |
+#include <algorithm> | |
void OpenLuaContext(int uid, void(*print)(int uid, const char* str) = 0, void(*onstart)(int uid) = 0, void(*onstop)(int uid, bool statusOK) = 0); | |
void RunLuaScriptFile(int uid, const char* filename); | |
@@ -37,8 +39,12 @@ enum LuaCallID | |
LUACALL_SCRIPT_HOTKEY_15, | |
LUACALL_SCRIPT_HOTKEY_16, | |
+ LUACALL_ENTERFUNCTION, | |
+ LUACALL_BYTES_PATTERN, | |
+ | |
LUACALL_COUNT | |
}; | |
+void CallRegisteredLuaFunctionsWithArgs(LuaCallID calltype, const std::vector<int> &args); | |
void CallRegisteredLuaFunctions(LuaCallID calltype); | |
enum LuaMemHookType | |
@@ -93,9 +99,6 @@ void DontWorryLua(); | |
-#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. | |
@@ -200,6 +203,44 @@ FORCEINLINE void CallRegisteredLuaMemHoo | |
} | |
} | |
+extern bool logCondMode; | |
+ | |
+void LogCondInner(u32 addr, bool cond); | |
+ | |
+FORCEINLINE void LogCond(u32 addr, bool cond) | |
+{ | |
+ if (logCondMode) { | |
+ LogCondInner(addr, cond); | |
+ } | |
+} | |
+ | |
+extern bool logReturnMode; | |
+ | |
+void LogReturnInner(u32 addr, u32 val); | |
+ | |
+FORCEINLINE void LogReturn(u32 addr, u32 val) | |
+{ | |
+ if (logReturnMode) { | |
+ LogReturnInner(addr, val); | |
+ } | |
+} | |
+ | |
+struct BYTES_PATTERN_WATCH_STATE { | |
+ bool enabled; | |
+ std::vector<u8> bytes; | |
+ u8 last_val; | |
+}; | |
+extern BYTES_PATTERN_WATCH_STATE bytesPatternWatchState; | |
+ | |
+void CheckBytesPatternInner(u32 addr); | |
+ | |
+FORCEINLINE void CheckBytesPattern(u32 addr, u8 val) | |
+{ | |
+ if (!bytesPatternWatchState.enabled) return; | |
+ if (val == bytesPatternWatchState.last_val) { | |
+ CheckBytesPatternInner(addr); | |
+ } | |
+} | |
#endif | |
diff -upr src-orig/thumb_instructions.cpp src-my/thumb_instructions.cpp | |
--- src-orig/thumb_instructions.cpp 2010-07-01 13:25:18.000000000 +0900 | |
+++ src-my/thumb_instructions.cpp 2010-09-20 14:29:15.109375000 +0900 | |
@@ -858,6 +858,11 @@ TEMPLATE static u32 FASTCALL OP_PUSH_LR | |
u32 adr = cpu->R[13] - 4; | |
u32 c = 0, j; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ if (PROCNUM == 0) { | |
+ CallRegisteredLuaFunctions(LUACALL_ENTERFUNCTION); | |
+ } | |
+#endif | |
WRITE32(cpu->mem_if->data, adr, cpu->R[14]); | |
c += MMU_memAccessCycles<PROCNUM,32,MMU_AD_WRITE>(adr); | |
adr -= 4; | |
@@ -904,6 +909,10 @@ TEMPLATE static u32 FASTCALL OP_POP_PC( | |
u32 c = 0, j; | |
u32 v = 0; | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ LogReturn(cpu->instruct_adr, cpu->R[0]); | |
+#endif | |
+ | |
for(j = 0; j<8; j++) | |
if(BIT_N(i, j)) | |
{ | |
@@ -1056,7 +1065,7 @@ TEMPLATE static u32 FASTCALL OP_SWI_THU | |
TEMPLATE static u32 FASTCALL OP_B_COND(const u32 i) | |
{ | |
- if(!TEST_COND((i>>8)&0xF, 0, cpu->CPSR)) | |
+ if(!TEST_COND((i>>8)&0xF, 0, cpu)) | |
return 1; | |
cpu->R[15] += (u32)((s8)(i&0xFF))<<1; | |
@@ -1126,6 +1135,12 @@ TEMPLATE static u32 FASTCALL OP_BX_THUM | |
cpu->next_instruction = cpu->R[15]; | |
} | |
#else | |
+#if defined(HAVE_LUA) && defined(ENABLE_ADVANCEMENT_HOOK) | |
+ if (REG_POS(i, 3) == 14) | |
+ { | |
+ LogReturn(cpu->instruct_adr, cpu->R[0]); | |
+ } | |
+#endif | |
u32 Rm = cpu->R[REG_POS(i, 3)]; | |
//----- ARM_REF: | |
//----- Register 15 can be specified for <Rm>. If this is done, R15 is read as normal for Thumb code, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment