Skip to content

Instantly share code, notes, and snippets.

@oupo
Created September 20, 2010 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oupo/587467 to your computer and use it in GitHub Desktop.
Save oupo/587467 to your computer and use it in GitHub Desktop.
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