From 77daf1bad4605a9aac992159c696c4face107880 Mon Sep 17 00:00:00 2001 From: shygoo Date: Sat, 17 Mar 2018 20:14:52 -0500 Subject: [PATCH] [Debugger] Add memory locks feature (interpreter) --- .../N64System/Interpreter/InterpreterCPU.cpp | 7 ++ .../UserInterface/Debugger/Breakpoints.cpp | 47 ++++++++++++++ .../UserInterface/Debugger/Breakpoints.h | 10 +++ .../Debugger/Debugger-Commands.cpp | 4 +- .../Debugger/Debugger-ViewMemory.cpp | 19 +++++- .../UserInterface/Debugger/Debugger.cpp | 28 ++++---- .../Project64/UserInterface/Debugger/OpInfo.h | 65 ++++++++++++++++++- Source/Project64/UserInterface/UIResources.rc | 5 +- Source/Project64/UserInterface/resource.h | 4 +- 9 files changed, 168 insertions(+), 21 deletions(-) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp index 5f84d6a81..d3f838336 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterCPU.cpp @@ -321,6 +321,13 @@ void CInterpreterCPU::ExecuteCPU() if (CDebugSettings::HaveDebugger()) { g_Debugger->CPUStepStarted(); + + if (SkipOp()) + { + g_Settings->SaveBool(Debugger_SkipOp, false); + PROGRAM_COUNTER += 4; + continue; + } } /* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000) diff --git a/Source/Project64/UserInterface/Debugger/Breakpoints.cpp b/Source/Project64/UserInterface/Debugger/Breakpoints.cpp index a77f93485..6fd3bc4df 100644 --- a/Source/Project64/UserInterface/Debugger/Breakpoints.cpp +++ b/Source/Project64/UserInterface/Debugger/Breakpoints.cpp @@ -238,6 +238,21 @@ CBreakpoints::BPSTATE CBreakpoints::WriteBPExists64(uint32_t address) return BP_NOT_SET; } +CBreakpoints::BPSTATE CBreakpoints::WriteBPExistsInChunk(uint32_t address, uint32_t nBytes) +{ + uint32_t endAddr = address + nBytes; + + for (breakpoints_t::iterator breakpoint = m_WriteMem.begin(); breakpoint != m_WriteMem.end(); breakpoint++) + { + uint32_t wbpAddr = breakpoint->first; + if (wbpAddr >= address && wbpAddr < endAddr) + { + return BP_SET; + } + } + return BP_NOT_SET; +} + CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp) { breakpoints_t::const_iterator itr = m_Execution.find(address); @@ -283,3 +298,35 @@ void CBreakpoints::UpdateAlignedWriteBP() m_WriteMem64.insert(breakpoints_t::value_type((itr->first & ~0x7), false)); } } + +void CBreakpoints::ToggleMemLock(uint32_t address) +{ + if (m_MemLocks.count(address) == 0) + { + m_MemLocks.insert(address); + return; + } + m_MemLocks.erase(address); +} + +bool CBreakpoints::MemLockExists(uint32_t address, int nBytes) +{ + for (memlocks_t::const_iterator itr = m_MemLocks.begin(); itr != m_MemLocks.end(); itr++) + { + if (*itr >= address && *itr < (address + nBytes)) + { + return true; + } + } + return false; +} + +void CBreakpoints::ClearMemLocks() +{ + m_MemLocks.clear(); +} + +size_t CBreakpoints::NumMemLocks() +{ + return m_MemLocks.size(); +} diff --git a/Source/Project64/UserInterface/Debugger/Breakpoints.h b/Source/Project64/UserInterface/Debugger/Breakpoints.h index 39ea2dcbc..2e574d8ae 100644 --- a/Source/Project64/UserInterface/Debugger/Breakpoints.h +++ b/Source/Project64/UserInterface/Debugger/Breakpoints.h @@ -19,6 +19,8 @@ public: typedef std::map breakpoints_t; typedef breakpoints_t::const_iterator breakpoint_t; + typedef std::set memlocks_t; + enum BPSTATE { BP_NOT_SET, @@ -40,6 +42,7 @@ public: BPSTATE WriteBPExists16(uint32_t address); BPSTATE WriteBPExists32(uint32_t address); BPSTATE WriteBPExists64(uint32_t address); + BPSTATE WriteBPExistsInChunk(uint32_t address, uint32_t nBytes); BPSTATE ExecutionBPExists(uint32_t address, bool bRemoveTemp = false); bool RBPAdd(uint32_t address); @@ -59,6 +62,11 @@ public: void BPClear(); + void ToggleMemLock(uint32_t address); + bool MemLockExists(uint32_t address, int nBytes); + void ClearMemLocks(void); + size_t NumMemLocks(void); + private: void UpdateAlignedWriteBP(void); void UpdateAlignedReadBP(void); @@ -66,4 +74,6 @@ private: breakpoints_t m_ReadMem, m_ReadMem16, m_ReadMem32, m_ReadMem64; breakpoints_t m_WriteMem, m_WriteMem16, m_WriteMem32, m_WriteMem64; breakpoints_t m_Execution; + + memlocks_t m_MemLocks; }; \ No newline at end of file diff --git a/Source/Project64/UserInterface/Debugger/Debugger-Commands.cpp b/Source/Project64/UserInterface/Debugger/Debugger-Commands.cpp index 4b2e8fdea..9d0c6ae49 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger-Commands.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger-Commands.cpp @@ -583,7 +583,7 @@ void CDebugCommandsView::ShowAddress(uint32_t address, bool top) const char* annotation = NULL; bool bLoadStoreAnnotation = false; - if (OpInfo.IsLoadStore()) + if (OpInfo.IsLoadStoreCommand()) { for (int offset = -4; offset > -24; offset -= 4) { @@ -1413,7 +1413,7 @@ LRESULT CDebugCommandsView::OnCommandListRightClicked(NMHDR* pNMHDR) EnableMenuItem(hPopupMenu, ID_POPUPMENU_FOLLOWJUMP, MF_DISABLED | MF_GRAYED); } - if (m_SelectedOpInfo.IsLoadStore()) + if (m_SelectedOpInfo.IsLoadStoreCommand()) { m_FollowAddress = g_Reg->m_GPR[m_SelectedOpCode.base].UW[0] + (int16_t)m_SelectedOpCode.offset; } diff --git a/Source/Project64/UserInterface/Debugger/Debugger-ViewMemory.cpp b/Source/Project64/UserInterface/Debugger/Debugger-ViewMemory.cpp index 3f4187d02..bb09cc7d4 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger-ViewMemory.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger-ViewMemory.cpp @@ -219,6 +219,14 @@ LRESULT CDebugMemoryView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL& m_Breakpoints->WBPClear(); RefreshMemory(true); break; + case ID_POPUPMENU_TOGGLELOCK: + m_Breakpoints->ToggleMemLock(m_CtxMenuAddr); + RefreshMemory(true); + break; + case ID_POPUPMENU_CLEARLOCKS: + m_Breakpoints->ClearMemLocks(); + RefreshMemory(true); + break; case ID_POPUPMENU_VIEWDISASM: m_Debugger->Debug_ShowCommandsLocation(m_CtxMenuAddr, true); break; @@ -248,6 +256,10 @@ LRESULT CDebugMemoryView::OnMemoryRightClicked(LPNMHDR lpNMHDR) { EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED); } + if (m_Breakpoints->NumMemLocks() == 0) + { + EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARLOCKS, MF_DISABLED | MF_GRAYED); + } POINT mouse; GetCursorPos(&mouse); @@ -725,12 +737,17 @@ void CDebugMemoryView::SelectColors(uint32_t vaddr, bool changed, COLORREF& bgCo CSymbols::LeaveCriticalSection(); + bool bLocked = m_Breakpoints->MemLockExists(vaddr, 1); bool bHaveReadBP = m_Breakpoints->ReadBPExists8(vaddr) == CBreakpoints::BP_SET; bool bHaveWriteBP = m_Breakpoints->WriteBPExists8(vaddr) == CBreakpoints::BP_SET; fgHiColor = RGB(0x00, 0x00, 0x00); - if (bHaveReadBP && bHaveWriteBP) + if (bLocked) + { + bgColor = RGB(0xDD, 0xAA, 0xAA); + } + else if (bHaveReadBP && bHaveWriteBP) { bgColor = RGB(0xAA, 0xDD, 0xDD); } diff --git a/Source/Project64/UserInterface/Debugger/Debugger.cpp b/Source/Project64/UserInterface/Debugger/Debugger.cpp index 7505c5b9b..1b08f6372 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger.cpp @@ -394,14 +394,13 @@ void CDebuggerUI::CPUStepStarted() // Memory breakpoints - OPCODE Opcode = R4300iOp::m_Opcode; - uint32_t op = Opcode.op; + COpInfo opInfo(R4300iOp::m_Opcode); - if (op >= R4300i_LDL && op <= R4300i_SD && op != R4300i_CACHE) // Read and write instructions + if (opInfo.IsLoadStoreCommand()) // Read and write instructions { - uint32_t memoryAddress = g_Reg->m_GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; + uint32_t memoryAddress = opInfo.GetLoadStoreAddress(); - if ((op <= R4300i_LWU || (op >= R4300i_LL && op <= R4300i_LD))) // Read instructions + if (opInfo.IsLoadCommand()) // Read instructions { m_ScriptSystem->HookCPURead()->InvokeByParamInRange(memoryAddress); @@ -419,21 +418,20 @@ void CDebuggerUI::CPUStepStarted() { uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF; uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000; - uint32_t dmaLen = g_Reg->m_GPR[Opcode.rt].UW[0] + 1; - uint32_t endAddr = dmaRamAddr + dmaLen; - + uint32_t dmaLen = opInfo.GetStoreValueUnsigned() + 1; + m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen); - CBreakpoints::breakpoints_t breakpoints = m_Breakpoints->WriteMem(); - for (CBreakpoints::breakpoints_t::iterator breakpoint = breakpoints.begin(); breakpoint != breakpoints.end(); breakpoint++) + if (m_Breakpoints->WriteBPExistsInChunk(dmaRamAddr, dmaLen)) { - uint32_t wbpAddr = breakpoint->first; - if (wbpAddr >= dmaRamAddr && wbpAddr < endAddr) - { - goto breakpoint_hit; - } + goto breakpoint_hit; } } + + if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore())) + { + g_Settings->SaveBool(Debugger_SkipOp, true); + } } } diff --git a/Source/Project64/UserInterface/Debugger/OpInfo.h b/Source/Project64/UserInterface/Debugger/OpInfo.h index bba22f505..685a7887a 100644 --- a/Source/Project64/UserInterface/Debugger/OpInfo.h +++ b/Source/Project64/UserInterface/Debugger/OpInfo.h @@ -20,6 +20,15 @@ public: OPCODE m_OpCode; + COpInfo() + { + } + + inline COpInfo(OPCODE opcode): + m_OpCode(opcode) + { + } + bool IsStaticJump() { // j, jal @@ -131,11 +140,16 @@ public: return false; } - bool IsLoadStore() + inline bool IsLoadStoreCommand() { return (m_OpCode.op >= R4300i_LDL && m_OpCode.op <= R4300i_SD && m_OpCode.op != R4300i_CACHE); } + inline bool IsLoadCommand() + { + return (m_OpCode.op <= R4300i_LWU || (m_OpCode.op >= R4300i_LL && m_OpCode.op <= R4300i_LD)); + } + bool IsStackShift() { return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29; @@ -323,4 +337,53 @@ public: } return false; } + + inline uint32_t GetLoadStoreAddress() + { + return g_Reg->m_GPR[m_OpCode.base].UW[0] + (int16_t)m_OpCode.offset; + } + + inline uint32_t GetStoreValueUnsigned() + { + return g_Reg->m_GPR[m_OpCode.rt].UW[0]; + } + + inline int NumBytesToLoad() + { + switch (m_OpCode.op) + { + case R4300i_LB: + case R4300i_LBU: + return 1; + case R4300i_LH: + case R4300i_LHU: + return 2; + case R4300i_LD: + case R4300i_LDL: + case R4300i_LDR: + case R4300i_LDC1: + return 8; + default: + return 4; + } + } + + inline int NumBytesToStore() + { + switch (m_OpCode.op) + { + case R4300i_SB: + return 1; + case R4300i_SH: + return 2; + case R4300i_SD: + case R4300i_SDL: + case R4300i_SDR: + case R4300i_SDC1: + case R4300i_SDC2: + return 8; + default: + return 4; + } + } }; \ No newline at end of file diff --git a/Source/Project64/UserInterface/UIResources.rc b/Source/Project64/UserInterface/UIResources.rc index ce280bcbe..2badf997c 100644 --- a/Source/Project64/UserInterface/UIResources.rc +++ b/Source/Project64/UserInterface/UIResources.rc @@ -685,7 +685,7 @@ BEGIN PUSHBUTTON "...",IDC_SYMBOLS_BTN,357,1,17,15 PUSHBUTTON "Skip",IDC_SKIP_BTN,376,1,27,15,WS_DISABLED PUSHBUTTON "Step",IDC_STEP_BTN,404,1,27,15,WS_DISABLED - PUSHBUTTON "St.Ovr", IDC_STEPOVER_BTN, 432, 1, 27, 15, WS_DISABLED + PUSHBUTTON "St.Ovr",IDC_STEPOVER_BTN,432,1,27,15,WS_DISABLED PUSHBUTTON "Go",IDC_GO_BTN,460,1,27,15,WS_DISABLED LTEXT "PC",IDC_PC_STATIC,292,24,8,9 EDITTEXT IDC_PC_EDIT,303,22,44,12,ES_UPPERCASE | ES_AUTOHSCROLL,WS_EX_RIGHT @@ -1735,6 +1735,9 @@ BEGIN MENUITEM "Toggle write breakpoint", ID_POPUPMENU_TOGGLEWBP MENUITEM "Clear all breakpoints", ID_POPUPMENU_CLEARALLBPS MENUITEM SEPARATOR + MENUITEM "Toggle lock", ID_POPUPMENU_TOGGLELOCK + MENUITEM "Clear locks", ID_POPUPMENU_CLEARLOCKS + MENUITEM SEPARATOR MENUITEM "View disassembly...", ID_POPUPMENU_VIEWDISASM MENUITEM SEPARATOR MENUITEM "Add symbol...", ID_POPUPMENU_ADDSYMBOL diff --git a/Source/Project64/UserInterface/resource.h b/Source/Project64/UserInterface/resource.h index 5c87a4f7a..e87e9232a 100644 --- a/Source/Project64/UserInterface/resource.h +++ b/Source/Project64/UserInterface/resource.h @@ -621,6 +621,8 @@ #define ID_POPUPMENU_VIEWMEMORY 40036 #define ID_POPUPMENU_TOGGLEBP 40039 #define ID_POPUPMENU_CLEARBPS 40040 +#define ID_POPUPMENU_TOGGLELOCK 40041 +#define ID_POPUPMENU_CLEARLOCKS 40042 #define ID_POPUPMENU_ROMDIRECTORY 40137 #define ID_POPUPMENU_REFRESHROMLIST 40138 #define ID_POPUPMENU_PLAYGAME 40152 @@ -636,7 +638,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 194 -#define _APS_NEXT_COMMAND_VALUE 40041 +#define _APS_NEXT_COMMAND_VALUE 40043 #define _APS_NEXT_CONTROL_VALUE 1445 #define _APS_NEXT_SYMED_VALUE 102 #endif