diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 1912b2d8d..c599ec2b4 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -595,7 +595,7 @@ FORCEINLINE FASTCALL void GPU::_master_setFinal3dColor(int dstX, int srcX) //if the layer underneath is a blend bottom layer, then 3d always alpha blends with it COLOR c2, cfinal; - c2.val = T2ReadWord(dst, passing); + c2.val = HostReadWord(dst, passing); cfinal.bits.red = ((red * alpha) + ((c2.bits.red<<1) * (32 - alpha)))>>6; cfinal.bits.green = ((green * alpha) + ((c2.bits.green<<1) * (32 - alpha)))>>6; @@ -619,7 +619,7 @@ FORCEINLINE FASTCALL void GPU::_master_setFinal3dColor(int dstX, int srcX) } } - T2WriteWord(dst, passing, (final | 0x8000)); + HostWriteWord(dst, passing, (final | 0x8000)); bgPixels[x] = 0; } @@ -655,7 +655,7 @@ FORCEINLINE FASTCALL bool GPU::_master_setFinalBGColor(u16 &color, const u32 x) //perform the special effect switch(FUNC) { - case Blend: if(blend2[bg_under]) color = blend(color,T2ReadWord(currDst, x<<1)); break; + case Blend: if(blend2[bg_under]) color = blend(color,HostReadWord(currDst, x<<1)); break; case Increase: color = currentFadeInColors[color]; break; case Decrease: color = currentFadeOutColors[color]; break; case None: break; @@ -698,7 +698,7 @@ static FORCEINLINE void _master_setFinalOBJColor(GPU *gpu, u8 *dst, u16 color, u if(allowBlend) { - u16 backColor = T2ReadWord(dst,x<<1); + u16 backColor = HostReadWord(dst,x<<1); //this hasn't been tested: this blending occurs without regard to the color effect, //but rather purely from the sprite's alpha if(type == GPU_OBJ_MODE_Bitmap) @@ -707,7 +707,7 @@ static FORCEINLINE void _master_setFinalOBJColor(GPU *gpu, u8 *dst, u16 color, u color = gpu->blend(color,backColor); } - T2WriteWord(dst, x<<1, (color | 0x8000)); + HostWriteWord(dst, x<<1, (color | 0x8000)); gpu->bgPixels[x] = 4; } @@ -738,7 +738,7 @@ FORCEINLINE void GPU::setFinalColorBG(u16 color, const u32 x) if(BACKDROP || draw) //backdrop must always be drawn { - T2WriteWord(currDst, x<<1, color | 0x8000); + HostWriteWord(currDst, x<<1, color | 0x8000); if(!BACKDROP) bgPixels[x] = currBgNum; //lets do this in the backdrop drawing loop, should be faster } } @@ -1300,7 +1300,7 @@ INLINE void render_sprite_BMP (GPU * gpu, u8 spriteNum, u16 l, u8 * dst, u16 * s // alpha bit = invisible if ((color&0x8000)&&(prio0)&&(prio0)&&(prioMode; prioTab[sprX] = prio; @@ -1669,7 +1669,7 @@ void GPU::_spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) if((colour&0x8000) && (prioPaletteIndex; typeTab[sprX] = spriteInfo->Mode; prioTab[sprX] = prio; @@ -1723,7 +1723,7 @@ void GPU::_spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab) sprWin[sprX] = 1; else { - T2WriteWord(dst, (sprX<<1), LE_TO_LOCAL_16(T2ReadWord(pal, colour << 1))); + HostWriteWord(dst, (sprX<<1), LE_TO_LOCAL_16(HostReadWord(pal, colour << 1))); dst_alpha[sprX] = 16; typeTab[sprX] = spriteInfo->Mode; prioTab[sprX] = prio; @@ -2060,7 +2060,7 @@ static void GPU_RenderLine_layer(NDS_Screen * screen, u16 l) { //n.b. - this is clearing the sprite line buffer to the background color, //but it has been changed to write u32 instead of u16 for a little speedup - for(int i = 0; i< 128; ++i) T2WriteLong(spr, i << 2, backdrop_color | (backdrop_color<<16)); + for(int i = 0; i< 128; ++i) HostWriteTwoWords(spr, i << 2, backdrop_color | (backdrop_color<<16)); //zero 06-may-09: I properly supported window color effects for backdrop, but I am not sure //how it interacts with this. I wish we knew why we needed this @@ -2157,7 +2157,7 @@ static void GPU_RenderLine_layer(NDS_Screen * screen, u16 l) for (int i=0; i < item->nbPixelsX; i++) { i16=item->PixelsX[i]; - setFinalColorSpr(gpu, gpu->currDst, T2ReadWord(spr, (i16<<1)), sprAlpha[i16], sprType[i16], i16); + setFinalColorSpr(gpu, gpu->currDst, HostReadWord(spr, (i16<<1)), sprAlpha[i16], sprType[i16], i16); } } } @@ -2170,11 +2170,11 @@ template static void GPU_RenderLine_DispCapture(u16 l) switch(gpu->dispCapCnt.capx) { \ case DISPCAPCNT::_128: \ for (int i = 0; i < 128; i++) \ - T2WriteWord(DST, i << 1, T2ReadWord(SRC, i << 1) | (1<<15)); \ + HostWriteWord(DST, i << 1, HostReadWord(SRC, i << 1) | (1<<15)); \ break; \ case DISPCAPCNT::_256: \ for (int i = 0; i < 256; i++) \ - T2WriteWord(DST, i << 1, T2ReadWord(SRC, i << 1) | (1<<15)); \ + HostWriteWord(DST, i << 1, HostReadWord(SRC, i << 1) | (1<<15)); \ break; \ default: assert(false); \ } @@ -2332,7 +2332,7 @@ template static void GPU_RenderLine_DispCapture(u16 l) g = std::min((u16)31,g); b = std::min((u16)31,b); - T2WriteWord(cap_dst, i << 1, a | (b << 10) | (g << 5) | r); + HostWriteWord(cap_dst, i << 1, a | (b << 10) | (g << 5) | r); } } break; @@ -2591,7 +2591,7 @@ void GPU_RenderLine(NDS_Screen * screen, u16 l, bool skip) u8 * dst = GPU_screen + (screen->offset + l) * 512; for (int i=0; i<256; i++) - T2WriteWord(dst, i << 1, 0x7FFF); + HostWriteWord(dst, i << 1, 0x7FFF); } break; diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index 49a7b8e88..a235f839a 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -372,7 +372,7 @@ static void TextualInputDisplay() { // touch pad { char str [32]; - bool gameTouchOn = nds.isTouch; + BOOL gameTouchOn = nds.isTouch; int gameTouchX = nds.touchX >> 4; int gameTouchY = nds.touchY >> 4; bool physicalTouchOn = NDS_getRawUserInput().touch.isTouch; diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 6696b1c6c..c690d223f 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1448,72 +1448,66 @@ u32 MMU_readFromGC() } -#ifdef MMU_ENABLE_ACL +//INLINE void check_access(u32 adr, u32 access) { +// /* every other mode: sys */ +// access |= 1; +// if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { +// /* is user mode access */ +// access ^= 1 ; +// } +// if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { +// execute = FALSE ; +// } +//} +//INLINE void check_access_write(u32 adr) { +// u32 access = CP15_ACCESS_WRITE; +// check_access(adr, access) +//} +// +//u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access) +//{ +// /* on arm9 we need to check the MPU regions */ +// if (proc == ARMCPU_ARM9) +// check_access(u32 adr, u32 access); +// return MMU_read8(proc,adr); +//} +//u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access) +//{ +// /* on arm9 we need to check the MPU regions */ +// if (proc == ARMCPU_ARM9) +// check_access(u32 adr, u32 access); +// return MMU_read16(proc,adr); +//} +//u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access) +//{ +// /* on arm9 we need to check the MPU regions */ +// if (proc == ARMCPU_ARM9) +// check_access(u32 adr, u32 access); +// return MMU_read32(proc,adr); +//} +// +//void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val) +//{ +// /* check MPU region on ARM9 */ +// if (proc == ARMCPU_ARM9) +// check_access_write(adr); +// MMU_write8(proc,adr,val); +//} +//void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val) +//{ +// /* check MPU region on ARM9 */ +// if (proc == ARMCPU_ARM9) +// check_access_write(adr); +// MMU_write16(proc,adr,val) ; +//} +//void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val) +//{ +// /* check MPU region on ARM9 */ +// if (proc == ARMCPU_ARM9) +// check_access_write(adr); +// MMU_write32(proc,adr,val) ; +//} -INLINE void check_access(u32 adr, u32 access) { - /* every other mode: sys */ - access |= 1; - if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { - /* is user mode access */ - access ^= 1 ; - } - if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { - execute = FALSE ; - } -} -INLINE void check_access_write(u32 adr) { - u32 access = CP15_ACCESS_WRITE; - check_access(adr, access) -} - -u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access) -{ - /* on arm9 we need to check the MPU regions */ - if (proc == ARMCPU_ARM9) - check_access(u32 adr, u32 access); - return MMU_read8(proc,adr); -} -u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access) -{ - /* on arm9 we need to check the MPU regions */ - if (proc == ARMCPU_ARM9) - check_access(u32 adr, u32 access); - return MMU_read16(proc,adr); -} -u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access) -{ - /* on arm9 we need to check the MPU regions */ - if (proc == ARMCPU_ARM9) - check_access(u32 adr, u32 access); - return MMU_read32(proc,adr); -} - -void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val) -{ - /* check MPU region on ARM9 */ - if (proc == ARMCPU_ARM9) - check_access_write(adr); - MMU_write8(proc,adr,val); -} -void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val) -{ - /* check MPU region on ARM9 */ - if (proc == ARMCPU_ARM9) - check_access_write(adr); - MMU_write16(proc,adr,val) ; -} -void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val) -{ - /* check MPU region on ARM9 */ - if (proc == ARMCPU_ARM9) - check_access_write(adr); - MMU_write32(proc,adr,val) ; -} -#endif - -//a stub for memory profiler, if we choose to re-add it -#define PROFILE_PREFETCH 1 -#define profile_memory_access(X,Y,Z) //does some validation on the game's choice of IF value, correcting it if necessary void validateIF_arm9() @@ -4375,7 +4369,6 @@ void FASTCALL MMU_write8(u32 proc, u32 adr, u8 val) if(proc==0) _MMU_ARM9_write08(adr, val); else - _MMU_ARM7_write08(adr,val); } @@ -4386,7 +4379,7 @@ void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer) for(i = 0, curaddr = address; i < size; i++, curaddr++) { - buffer[i] = _MMU_read08(proc,MMU_AT_GPU,curaddr); + buffer[i] = _MMU_read08(proc,MMU_AT_DEBUG,curaddr); } } @@ -4394,82 +4387,66 @@ void FASTCALL MMU_DumpMemBlock(u8 proc, u32 address, u32 size, u8 *buffer) //function pointer handlers for gdb stub stuff static u16 FASTCALL arm9_prefetch16( void *data, u32 adr) { - profile_memory_access( 1, adr, PROFILE_PREFETCH); - return _MMU_read16(adr); + return _MMU_read16(adr); } static u32 FASTCALL arm9_prefetch32( void *data, u32 adr) { - profile_memory_access( 1, adr, PROFILE_PREFETCH); - return _MMU_read32(adr); + return _MMU_read32(adr); } static u8 FASTCALL arm9_read8( void *data, u32 adr) { - profile_memory_access( 1, adr, PROFILE_READ); return _MMU_read08(adr); } static u16 FASTCALL arm9_read16( void *data, u32 adr) { - profile_memory_access( 1, adr, PROFILE_READ); return _MMU_read16(adr); } static u32 FASTCALL arm9_read32( void *data, u32 adr) { - profile_memory_access( 1, adr, PROFILE_READ); return _MMU_read32(adr); } static void FASTCALL arm9_write8(void *data, u32 adr, u8 val) { - profile_memory_access( 1, adr, PROFILE_WRITE); _MMU_write08(adr, val); } static void FASTCALL arm9_write16(void *data, u32 adr, u16 val) { - profile_memory_access( 1, adr, PROFILE_WRITE); _MMU_write16(adr, val); } static void FASTCALL arm9_write32(void *data, u32 adr, u32 val) { - profile_memory_access( 1, adr, PROFILE_WRITE); _MMU_write32(adr, val); } static u16 FASTCALL arm7_prefetch16( void *data, u32 adr) { - profile_memory_access( 0, adr, PROFILE_PREFETCH); - return _MMU_read16(adr); + return _MMU_read16(adr); } static u32 FASTCALL arm7_prefetch32( void *data, u32 adr) { - profile_memory_access( 0, adr, PROFILE_PREFETCH); - return _MMU_read32(adr); + return _MMU_read32(adr); } static u8 FASTCALL arm7_read8( void *data, u32 adr) { - profile_memory_access( 0, adr, PROFILE_READ); return _MMU_read08(adr); } static u16 FASTCALL arm7_read16( void *data, u32 adr) { - profile_memory_access( 0, adr, PROFILE_READ); return _MMU_read16(adr); } static u32 FASTCALL arm7_read32( void *data, u32 adr) { - profile_memory_access( 0, adr, PROFILE_READ); return _MMU_read32(adr); } static void FASTCALL arm7_write8(void *data, u32 adr, u8 val) { - profile_memory_access( 0, adr, PROFILE_WRITE); _MMU_write08(adr, val); } static void FASTCALL arm7_write16(void *data, u32 adr, u16 val) { - profile_memory_access( 0, adr, PROFILE_WRITE); _MMU_write16(adr, val); } static void FASTCALL arm7_write32(void *data, u32 adr, u32 val) { - profile_memory_access( 0, adr, PROFILE_WRITE); _MMU_write32(adr, val); } diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index e925affda..8ee4b8f73 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -28,6 +28,8 @@ #include "mc.h" #include "bits.h" #include "readwrite.h" +#include "debug.h" + #ifdef HAVE_LUA #include "lua-engine.h" #endif @@ -542,11 +544,6 @@ FORCEINLINE void* MMU_gpu_map(u32 vram_addr) } -enum MMU_ACCESS_TYPE -{ - MMU_AT_CODE, MMU_AT_DATA, MMU_AT_GPU, MMU_AT_DMA -}; - template u8 _MMU_read08(u32 addr); template u16 _MMU_read16(u32 addr); template u32 _MMU_read32(u32 addr); @@ -587,11 +584,25 @@ inline void SetupMMU(BOOL debugConsole) { _MMU_MAIN_MEM_MASK32 = _MMU_MAIN_MEM_MASK & ~3; } -//TODO: at one point some of the early access code included this. consider re-adding it - //ARM7 private memory - //if ( (adr & 0x0f800000) == 0x03800000) { - //T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF], - // adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]); + +FORCEINLINE void CheckMemoryDebugEvent(const EDEBUG_EVENT event, const MMU_ACCESS_TYPE type, const u32 procnum, const u32 addr, const u32 size, const u32 val) +{ + if(CheckDebugEvent(event)) + { + DebugEventData.memAccessType = type; + DebugEventData.procnum = procnum; + DebugEventData.addr = addr; + DebugEventData.size = size; + DebugEventData.val = val; + HandleDebugEvent(event); + + if(type == MMU_AT_CODE && event == DEBUG_EVENT_READ) + { + HandleDebugEvent(DEBUG_EVENT_EXECUTE); + } + } +} + //ALERT!!!!!!!!!!!!!! //the following inline functions dont do the 0x0FFFFFFF mask. @@ -599,6 +610,8 @@ inline void SetupMMU(BOOL debugConsole) { FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,8,0); + //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -626,6 +639,8 @@ FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u3 FORCEINLINE u16 _MMU_read16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,16,0); + //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -666,6 +681,8 @@ dunno: FORCEINLINE u32 _MMU_read32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr) { + CheckMemoryDebugEvent(DEBUG_EVENT_READ,AT,PROCNUM,addr,32,0); + //special handling for DMA: read 0 from TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -721,6 +738,8 @@ dunno: 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); + //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -755,6 +774,8 @@ FORCEINLINE void _MMU_write08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u16 val) { + CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,16,val); + //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -789,6 +810,8 @@ FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val) { + CheckMemoryDebugEvent(DEBUG_EVENT_WRITE,AT,PROCNUM,addr,32,val); + //special handling for DMA: discard writes to TCM if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA) { @@ -822,21 +845,21 @@ FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const } -#ifdef MMU_ENABLE_ACL - void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val); - void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val); - void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val); - u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access); - u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access); - u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access); -#else - #define MMU_write8_acl(proc, adr, val) _MMU_write08(adr, val) - #define MMU_write16_acl(proc, adr, val) _MMU_write16(adr, val) - #define MMU_write32_acl(proc, adr, val) _MMU_write32(adr, val) - #define MMU_read8_acl(proc,adr,access) _MMU_read08(adr) - #define MMU_read16_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read16(adr):_MMU_read16(adr)) - #define MMU_read32_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read32(adr):_MMU_read32(adr)) -#endif +//#ifdef MMU_ENABLE_ACL +// void FASTCALL MMU_write8_acl(u32 proc, u32 adr, u8 val); +// void FASTCALL MMU_write16_acl(u32 proc, u32 adr, u16 val); +// void FASTCALL MMU_write32_acl(u32 proc, u32 adr, u32 val); +// u8 FASTCALL MMU_read8_acl(u32 proc, u32 adr, u32 access); +// u16 FASTCALL MMU_read16_acl(u32 proc, u32 adr, u32 access); +// u32 FASTCALL MMU_read32_acl(u32 proc, u32 adr, u32 access); +//#else +// #define MMU_write8_acl(proc, adr, val) _MMU_write08(adr, val) +// #define MMU_write16_acl(proc, adr, val) _MMU_write16(adr, val) +// #define MMU_write32_acl(proc, adr, val) _MMU_write32(adr, val) +// #define MMU_read8_acl(proc,adr,access) _MMU_read08(adr) +// #define MMU_read16_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read16(adr):_MMU_read16(adr)) +// #define MMU_read32_acl(proc,adr,access) ((access==CP15_ACCESS_EXECUTE)?_MMU_read32(adr):_MMU_read32(adr)) +//#endif // Use this macros for reading/writing, so the GDB stub isn't broken #ifdef GDB_STUB diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 133d58db5..6fbfaa2dd 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -60,6 +60,8 @@ CFIRMWARE *firmware = NULL; using std::min; using std::max; +bool singleStep; +bool nds_debug_continuing[2]; int lagframecounter; int LagFrameFlag; int lastLag; @@ -355,7 +357,6 @@ static void loadrom(std::string fname) { int NDS_LoadROM(const char *filename, const char *logicalFilename) { int type = ROM_NDS; - u32 mask; char buf[MAX_PATH]; if (filename == NULL) @@ -1729,6 +1730,9 @@ static /*donotinline*/ std::pair armInnerLoop( { arm9log(); arm9 += armcpu_exec(); + #ifdef DEVELOPER + nds_debug_continuing[0] = false; + #endif } else { @@ -1743,6 +1747,9 @@ static /*donotinline*/ std::pair armInnerLoop( { arm7log(); arm7 += (armcpu_exec()<<1); + #ifdef DEVELOPER + nds_debug_continuing[1] = false; + #endif } else { @@ -1762,11 +1769,28 @@ static /*donotinline*/ std::pair armInnerLoop( return std::make_pair(arm9, arm7); } +void NDS_debug_break() +{ + NDS_ARM9.stalled = NDS_ARM7.stalled = 1; + + //triggers an immediate exit from the cpu loop + NDS_Reschedule(); +} + +void NDS_debug_continue() +{ + NDS_ARM9.stalled = NDS_ARM7.stalled = 0; +} + +void NDS_debug_step() +{ + NDS_debug_continue(); + singleStep = true; +} + template void NDS_exec(s32 nb) { - //TODO - singlestep is broken - LagFrameFlag=1; if((currFrameCounter&63) == 0) @@ -1794,13 +1818,14 @@ void NDS_exec(s32 nb) { for(;;) { - - #ifdef GDB_STUB - //at worst, this will happen once per scanline. - //does it need to be more accurate than that? we think now + //trap the debug-stalled condition + #ifdef DEVELOPER + singleStep = false; + //(gbd stub doesnt yet know how to trigger these immediately by calling reschedule) while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute) { driver->EMU_DebugIdleUpdate(); + nds_debug_continuing[0] = nds_debug_continuing[1] = true; } #endif @@ -1825,13 +1850,28 @@ void NDS_exec(s32 nb) sequencer.reschedule = false; + //cast these down to 32bits so that things run faster on 32bit procs u64 nds_timer_base = nds_timer; s32 arm9 = (s32)(nds_arm9_timer-nds_timer); s32 arm7 = (s32)(nds_arm7_timer-nds_timer); s32 s32next = (s32)(next-nds_timer); + #ifdef DEVELOPER + if(singleStep) + { + s32next = 1; + } + #endif + std::pair arm9arm7 = armInnerLoop(nds_timer_base,s32next,arm9,arm7); + #ifdef DEVELOPER + if(singleStep) + { + NDS_ARM9.stalled = NDS_ARM7.stalled = 1; + } + #endif + arm9 = arm9arm7.first; arm7 = arm9arm7.second; nds_arm7_timer = nds_timer_base+arm7; @@ -1902,6 +1942,8 @@ static void resetUserInput(); bool _HACK_DONT_STOPMOVIE = false; void NDS_Reset() { + singleStep = false; + nds_debug_continuing[0] = nds_debug_continuing[1] = false; u32 src = 0; u32 dst = 0; bool fw_success = false; diff --git a/desmume/src/armcpu.cpp b/desmume/src/armcpu.cpp index c3a63ca5f..18d6232a4 100644 --- a/desmume/src/armcpu.cpp +++ b/desmume/src/armcpu.cpp @@ -200,10 +200,11 @@ int armcpu_new( armcpu_t *armcpu, u32 id) *ctrl_iface_ret = &armcpu->ctrl_iface; - armcpu->stalled = 0; armcpu->post_ex_fn = NULL; #endif + armcpu->stalled = 0; + armcpu_init(armcpu, 0); return 0; @@ -387,7 +388,7 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 4; } #else - armcpu->instruction = MMU_read32_acl(PROCNUM, curInstruction&0xFFFFFFFC,CP15_ACCESS_EXECUTE); + armcpu->instruction = _MMU_read32(curInstruction&0xFFFFFFFC); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 4; armcpu->R[15] = curInstruction + 8; @@ -409,7 +410,7 @@ FORCEINLINE static u32 armcpu_prefetch() armcpu->R[15] = armcpu->next_instruction + 2; } #else - armcpu->instruction = MMU_read16_acl(PROCNUM, curInstruction&0xFFFFFFFE,CP15_ACCESS_EXECUTE); + armcpu->instruction = _MMU_read16(curInstruction&0xFFFFFFFE); armcpu->instruct_adr = curInstruction; armcpu->next_instruction = curInstruction + 2; armcpu->R[15] = curInstruction + 4; diff --git a/desmume/src/armcpu.h b/desmume/src/armcpu.h index 09e324b90..4b4af184d 100644 --- a/desmume/src/armcpu.h +++ b/desmume/src/armcpu.h @@ -176,6 +176,9 @@ typedef struct armcpu_t u32 (* *swi_tab)(); + // flag indicating if the processor is stalled (for debugging) + int stalled; + #ifdef GDB_STUB /** there is a pending irq for the cpu */ int irq_flag; @@ -187,8 +190,6 @@ typedef struct armcpu_t void *post_ex_fn_data; - /** flag indicating if the processor is stalled */ - int stalled; /** the memory interface */ struct armcpu_memory_iface *mem_if; diff --git a/desmume/src/cp15.cpp b/desmume/src/cp15.cpp index c06a0ae36..e9e29ebbe 100644 --- a/desmume/src/cp15.cpp +++ b/desmume/src/cp15.cpp @@ -216,7 +216,7 @@ static void armcp15_maskPrecalc(armcp15_t *armcp15) precalc(7) ; } -INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) +BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) { int i ; if (!(armcp15->ctrl & 1)) return TRUE ; /* protection checking is not enabled */ diff --git a/desmume/src/cp15.h b/desmume/src/cp15.h index a6499ca30..f9a14e4f9 100644 --- a/desmume/src/cp15.h +++ b/desmume/src/cp15.h @@ -78,7 +78,7 @@ BOOL armcp15_load(armcp15_t *armcp15, u8 CRd, u8 adr); BOOL armcp15_store(armcp15_t *armcp15, u8 CRd, u8 adr); BOOL armcp15_moveCP2ARM(armcp15_t *armcp15, u32 * R, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); BOOL armcp15_moveARM2CP(armcp15_t *armcp15, u32 val, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); -INLINE BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access) ; +BOOL armcp15_isAccessAllowed(armcp15_t *armcp15,u32 address,u32 access); #define CP15_ACCESS_WRITE 0 diff --git a/desmume/src/debug.cpp b/desmume/src/debug.cpp index 1daaba928..b22eea789 100644 --- a/desmume/src/debug.cpp +++ b/desmume/src/debug.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2008 Guillaume Duhamel - Copyright (C) 2009 DeSmuME team + Copyright (C) 2009-2010 DeSmuME team This file is part of DeSmuME @@ -27,9 +27,73 @@ #include "armcpu.h" #include "arm_instructions.h" #include "thumb_instructions.h" +#include "cp15.h" +#include "NDSSystem.h" -std::vector Logger::channels; +#ifdef HAVE_LUA +#include "lua-engine.h" +#endif +TDebugEventData DebugEventData; +u32 debugFlag; + +//DEBUG CONFIGURATION +const bool debug_acl = false; + +bool acl_check_access(u32 adr, u32 access) { + //tweak the access value with the execution mode. + //user code is USR and every other mode is SYS. + //this is weird logic, but I didn't want to change.. + access |= 1; + if ((NDS_ARM9.CPSR.val & 0x1F) == 0x10) { + // is user mode access + access ^= 1; + } + if (armcp15_isAccessAllowed((armcp15_t *)NDS_ARM9.coproc[15],adr,access)==FALSE) { + HandleDebugEvent(DEBUG_EVENT_ACL_EXCEPTION); + } + return true; +} + + +void HandleDebugEvent_ACL_Exception() +{ + printf("ACL EXCEPTION!\n"); + emu_halt(); +} + +void HandleDebugEvent_Read() +{ + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_READ); +} + +void HandleDebugEvent_Write() +{ + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_WRITE); +} + +void HandleDebugEvent_Execute() +{ + extern bool nds_debug_continuing[2]; + //HACKY BREAKPOINTS! + //if(!nds_debug_continuing[DebugEventData.procnum]) //dont keep hitting the same breakpoint + //{ + // if((DebugEventData.addr & 0xFFFFFFF0) == 0x02000000) + // { + // void NDS_debug_break(); + // NDS_debug_break(); + // } + //} + if(!debug_acl) return; + if(DebugEventData.procnum != ARMCPU_ARM9) return; //acl only valid on arm9 + acl_check_access(DebugEventData.addr,CP15_ACCESS_EXECUTE); +} + +//------------------------------------------------ DebugStatistics DEBUG_statistics; DebugStatistics::DebugStatistics() @@ -132,10 +196,20 @@ void DebugStatistics::printSequencerExecutionCounters() void DEBUG_reset() { + //for now, just enable all debugging in developer builds +#ifdef DEVELOPER + debugFlag = 1; +#endif + DEBUG_statistics = DebugStatistics(); printf("DEBUG_reset: %08X\n",&DebugStatistics::print); //force a reference to this function } +//---------------------------------------------------- + +std::vector Logger::channels; + + static void defaultCallback(const Logger& logger, const char * message) { logger.getOutput() << message; } @@ -215,7 +289,6 @@ void Logger::log(unsigned int channel, const char * file, unsigned int line, voi void IdeasLog(armcpu_t* cpu) { u32 adr = cpu->R[0]; - printf("EMULOG%c: ",cpu->proc_ID==0?'9':'7'); for(;;) { u8 c = MMU_read8(cpu->proc_ID,adr); adr++; diff --git a/desmume/src/debug.h b/desmume/src/debug.h index d43bbb17d..e9b02581e 100644 --- a/desmume/src/debug.h +++ b/desmume/src/debug.h @@ -1,5 +1,5 @@ /* Copyright (C) 2008 Guillaume Duhamel - Copyright (C) 2009 DeSmuME team + Copyright (C) 2009-2010 DeSmuME team This file is part of DeSmuME @@ -26,6 +26,7 @@ #include #include "types.h" +#include "mem.h" struct DebugStatistics { @@ -138,4 +139,55 @@ public: void IdeasLog(armcpu_t* cpu); +enum EDEBUG_EVENT +{ + DEBUG_EVENT_READ=1, //read from arm9 or arm7 bus, including cpu prefetch + DEBUG_EVENT_WRITE=2, //write on arm9 or arm7 bus + DEBUG_EVENT_EXECUTE=4, //prefetch on arm9 or arm7, triggered after the read event + DEBUG_EVENT_ACL_EXCEPTION=8, //acl exception on arm9 + +}; + +//information about a debug event will be stuffed into here by the generator +struct TDebugEventData +{ + MMU_ACCESS_TYPE memAccessType; + u32 procnum, addr, size, val; +}; + +extern TDebugEventData DebugEventData; + +//bits in here are set according to what debug handlers are installed? +//for now it is just a single bit +extern u32 debugFlag; + +FORCEINLINE bool CheckDebugEvent(EDEBUG_EVENT event) +{ + //for now, debug events are only handled in dev+ builds +#ifndef DEVELOPER + return false; +#endif + + if(!debugFlag) return false; + + return true; +} + +void HandleDebugEvent_Read(); +void HandleDebugEvent_Write(); +void HandleDebugEvent_Execute(); +void HandleDebugEvent_ACL_Exception(); + +inline void HandleDebugEvent(EDEBUG_EVENT event) +{ + switch(event) + { + case DEBUG_EVENT_READ: HandleDebugEvent_Read(); return; + case DEBUG_EVENT_WRITE: HandleDebugEvent_Write(); return; + case DEBUG_EVENT_EXECUTE: HandleDebugEvent_Execute(); return; + case DEBUG_EVENT_ACL_EXCEPTION: HandleDebugEvent_ACL_Exception(); return; + } +} + + #endif diff --git a/desmume/src/mem.h b/desmume/src/mem.h index a94dd6777..7cbb9ccae 100644 --- a/desmume/src/mem.h +++ b/desmume/src/mem.h @@ -1,20 +1,21 @@ -/* Copyright 2005-2006 Guillaume Duhamel - Copyright 2005 Theo Berkau +/* Copyright (C) 2005 Theo Berkau + Copyright (C) 2005-2006 Guillaume Duhamel + Copyright (C) 2010 DeSmuME team - This file is part of Yabause. + This file is part of DeSmuME. - Yabause is free software; you can redistribute it and/or modify + DeSmuME is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - Yabause is distributed in the hope that it will be useful, + DeSmuME is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with Yabause; if not, write to the Free Software + along with DeSmuME; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -25,7 +26,15 @@ #include #include "types.h" -/* Type 1 Memory, faster for byte (8 bits) accesses */ +//this was originally declared in MMU.h but we suffered some organizational problems and had to remove it +enum MMU_ACCESS_TYPE +{ + MMU_AT_CODE, //used for cpu prefetches + MMU_AT_DATA, //used for cpu read/write + MMU_AT_GPU, //used for gpu read/write + MMU_AT_DMA, //used for dma read/write (blocks access to TCM) + MMU_AT_DEBUG, //used for emulator debugging functions (bypasses some debug handling) +}; static INLINE u8 T1ReadByte(u8* const mem, const u32 addr) { @@ -113,46 +122,47 @@ static INLINE void T1WriteLong(u8* const mem, const u32 addr, const u32 val) #endif } -/* Type 2 Memory, faster for word (16 bits) accesses */ -static INLINE u8 T2ReadByte(u8* const mem, const u32 addr) -{ -#ifdef WORDS_BIGENDIAN - return mem[addr ^ 1]; -#else - return mem[addr]; -#endif -} +//static INLINE u8 T2ReadByte(u8* const mem, const u32 addr) +//{ +//#ifdef WORDS_BIGENDIAN +// return mem[addr ^ 1]; +//#else +// return mem[addr]; +//#endif +//} +// -static INLINE u16 T2ReadWord(u8* const mem, const u32 addr) +static INLINE u16 HostReadWord(u8* const mem, const u32 addr) { return *((u16 *) (mem + addr)); } -static INLINE u32 T2ReadLong(u8* const mem, const u32 addr) -{ -#ifdef WORDS_BIGENDIAN - return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr)); -#else - return *((u32 *) (mem + addr)); -#endif -} +// +//static INLINE u32 T2ReadLong(u8* const mem, const u32 addr) +//{ +//#ifdef WORDS_BIGENDIAN +// return *((u16 *) (mem + addr + 2)) << 16 | *((u16 *) (mem + addr)); +//#else +// return *((u32 *) (mem + addr)); +//#endif +//} +// +//static INLINE void T2WriteByte(u8* const mem, const u32 addr, const u8 val) +//{ +//#ifdef WORDS_BIGENDIAN +// mem[addr ^ 1] = val; +//#else +// mem[addr] = val; +//#endif +//} -static INLINE void T2WriteByte(u8* const mem, const u32 addr, const u8 val) -{ -#ifdef WORDS_BIGENDIAN - mem[addr ^ 1] = val; -#else - mem[addr] = val; -#endif -} - -static INLINE void T2WriteWord(u8* const mem, const u32 addr, const u16 val) +static INLINE void HostWriteWord(u8* const mem, const u32 addr, const u16 val) { *((u16 *) (mem + addr)) = val; } -static INLINE void T2WriteLong(u8* const mem, const u32 addr, const u32 val) +static INLINE void HostWriteTwoWords(u8* const mem, const u32 addr, const u32 val) { #ifdef WORDS_BIGENDIAN *((u16 *) (mem + addr + 2)) = val >> 16; diff --git a/desmume/src/windows/CWindow.cpp b/desmume/src/windows/CWindow.cpp index d5de0beb8..8cb857622 100644 --- a/desmume/src/windows/CWindow.cpp +++ b/desmume/src/windows/CWindow.cpp @@ -795,10 +795,16 @@ TOOLSCLASS::~TOOLSCLASS() close(); } -bool TOOLSCLASS::open() +bool TOOLSCLASS::open(bool useThread) { - if (!createThread()) return false; - return true; + if(useThread) + { + if (!createThread()) return false; + else return true; + } + + if(doOpen()) return false; + else return true; } bool TOOLSCLASS::close() @@ -806,11 +812,8 @@ bool TOOLSCLASS::close() return true; } -DWORD TOOLSCLASS::ThreadFunc() +DWORD TOOLSCLASS::doOpen() { - MSG messages; - LOG("Start thread\n"); - GetLastError(); hwnd = CreateDialogW(hInstance, MAKEINTRESOURCEW(idd), NULL, (DLGPROC) dlgproc); @@ -822,16 +825,33 @@ DWORD TOOLSCLASS::ThreadFunc() ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); + + return 0; +} + +void TOOLSCLASS::doClose() +{ + unregClass(); + hwnd = NULL; +} + +DWORD TOOLSCLASS::ThreadFunc() +{ + LOG("Start thread\n"); + + + DWORD ret = doOpen(); + if(ret) return ret; + MSG messages; while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } - unregClass(); - hwnd = NULL; - + doClose(); + closeThread(); return 0; } diff --git a/desmume/src/windows/CWindow.h b/desmume/src/windows/CWindow.h index a2e4da1b6..44f70b204 100644 --- a/desmume/src/windows/CWindow.h +++ b/desmume/src/windows/CWindow.h @@ -289,13 +289,16 @@ private: char class_name[256]; char class_name2[256]; + DWORD doOpen(); + void doClose(); + protected: DWORD ThreadFunc(); public: TOOLSCLASS(HINSTANCE hInst, int IDD, DLGPROC wndproc); virtual ~TOOLSCLASS(); - bool open(); + bool open(bool useThread=true); bool close(); void regClass(LPSTR class_name, WNDPROC wproc, bool SecondReg = false); void unregClass(); diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 44623d37c..a0677e80b 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -1582,7 +1582,7 @@ > @@ -1659,10 +1659,6 @@ RelativePath="..\bios.h" > - - @@ -1759,10 +1755,6 @@ RelativePath="..\driver.h" > - - @@ -1839,6 +1831,38 @@ RelativePath="..\GPU_osd.h" > + + + + + + + + + + + + + + + + diff --git a/desmume/src/windows/disView.cpp b/desmume/src/windows/disView.cpp index ebe0425d7..2e1c3ead4 100644 --- a/desmume/src/windows/disView.cpp +++ b/desmume/src/windows/disView.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2006-2009 DeSmuME team + Copyright (C) 2006-2010 DeSmuME team This file is part of DeSmuME @@ -87,9 +87,9 @@ LRESULT DisViewBox_OnPaint(HWND hwnd, disview_struct *win, WPARAM wParam, LPARAM u32 adr; if (win->autoup||win->autogo) - win->curr_ligne = (win->cpu->instruct_adr >> 2) - (win->curr_ligne % nbligne) ; + win->curr_ligne = (win->cpu->instruct_adr >> 2); adr = win->curr_ligne*4; - + for(i = 0; i < nbligne; ++i) { u32 ins = MMU_read32(win->cpu->proc_ID, adr); @@ -309,6 +309,7 @@ BOOL CALLBACK ViewDisasm_ARM7Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA } case WM_CLOSE : { + EndDialog(hwnd,0); if(DisView7->autoup) { KillTimer(hwnd, IDT_VIEW_DISASM7); @@ -321,7 +322,6 @@ BOOL CALLBACK ViewDisasm_ARM7Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA } DisViewWnd[1] = NULL; //INFO("Close ARM7 disassembler\n"); - PostQuitMessage(0); return 1; } case WM_PAINT: @@ -380,11 +380,17 @@ BOOL CALLBACK ViewDisasm_ARM7Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA DisView7->autoup = TRUE; SetTimer(hwnd, IDT_VIEW_DISASM7, DisView7->autoup_secs*20, (TIMERPROC) NULL); return 1; - case IDC_STEP : // TODO: draw in DD + case IDC_STEP: { - int ndstep; - ndstep = GetDlgItemInt(hwnd, IDC_SETPNUM, NULL, FALSE); - NDS_exec(ndstep); + extern void NDS_debug_step(); + NDS_debug_step(); + } + return 1; + + case IDC_CONTINUE: + { + extern void NDS_debug_continue(); + NDS_debug_continue(); } return 1; case IDC_GO : @@ -553,6 +559,7 @@ BOOL CALLBACK ViewDisasm_ARM9Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA } case WM_CLOSE : { + EndDialog(hwnd,0); if(DisView9->autoup) { KillTimer(hwnd, IDT_VIEW_DISASM9); @@ -565,7 +572,6 @@ BOOL CALLBACK ViewDisasm_ARM9Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA } DisViewWnd[0] = NULL; //INFO("Close ARM9 disassembler\n"); - PostQuitMessage(0); return 1; } case WM_PAINT: @@ -624,11 +630,16 @@ BOOL CALLBACK ViewDisasm_ARM9Proc (HWND hwnd, UINT message, WPARAM wParam, LPARA DisView9->autoup = TRUE; SetTimer(hwnd, IDT_VIEW_DISASM9, DisView9->autoup_secs*20, (TIMERPROC) NULL); return 1; - case IDC_STEP : // TODO: draw in DD + case IDC_STEP: { - int ndstep; - ndstep = GetDlgItemInt(hwnd, IDC_SETPNUM, NULL, FALSE); - NDS_exec(ndstep); + extern void NDS_debug_step(); + NDS_debug_step(); + } + return 1; + case IDC_CONTINUE: + { + extern void NDS_debug_continue(); + NDS_debug_continue(); } return 1; case IDC_GO : diff --git a/desmume/src/windows/inputdx.cpp b/desmume/src/windows/inputdx.cpp index 7c46cb4ab..28b2da3cc 100644 --- a/desmume/src/windows/inputdx.cpp +++ b/desmume/src/windows/inputdx.cpp @@ -2204,8 +2204,6 @@ bool S9xGetState (WORD KeyIdent) void S9xWinScanJoypads () { - u32 PadState; - S9xUpdateJoyState(); for (int J = 0; J < 8; J++) diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 8c643b035..08d8f87ad 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -4727,11 +4727,11 @@ DOKEYDOWN: return 0; case IDM_DISASSEMBLER: ViewDisasm_ARM7->regClass("DesViewBox7",ViewDisasm_ARM7BoxProc); - if (!ViewDisasm_ARM7->open()) + if (!ViewDisasm_ARM7->open(false)) ViewDisasm_ARM7->unregClass(); ViewDisasm_ARM9->regClass("DesViewBox9",ViewDisasm_ARM9BoxProc); - if (!ViewDisasm_ARM9->open()) + if (!ViewDisasm_ARM9->open(false)) ViewDisasm_ARM9->unregClass(); return 0; case IDM_MAP: diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index cab5f2a39..0cace523a 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -16,6 +16,7 @@ #define IDC_AUTO_UPDATE 108 #define IDB_OPEN 108 #define IDM_MEMORY 109 +#define IDC_CONTINUE 109 #define IDM_DISASSEMBLER 110 #define IDB_PAUSE 110 #define IDD_3DSETTINGS 111 diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 4e6f7a3eb..f016d19f4 100644 Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ