Merge pull request #1552 from shygoo2/cpu-log-tool1
[Debugger] Add CPU Log, Break and show log/commands window on CPU errors
This commit is contained in:
commit
94a8f1928b
|
@ -20,10 +20,11 @@ __interface CDebugger
|
|||
virtual void OpenScriptsWindow(void) = 0;
|
||||
virtual void OpenSymbolsWindow(void) = 0;
|
||||
virtual void OpenDMALogWindow(void) = 0;
|
||||
virtual void OpenCPULogWindow(void) = 0;
|
||||
virtual void OpenStackTraceWindow(void) = 0;
|
||||
virtual void OpenStackViewWindow(void) = 0;
|
||||
virtual void TLBChanged(void) = 0;
|
||||
virtual void FrameDrawn(void) = 0;
|
||||
virtual void FrameDrawn(void) = 0;
|
||||
virtual void WaitForStep(void) = 0;
|
||||
virtual bool ExecutionBP(uint32_t address) = 0;
|
||||
virtual bool ReadBP8(uint32_t address) = 0;
|
||||
|
|
|
@ -298,32 +298,29 @@ void CInterpreterCPU::ExecuteCPU()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (isDebugging())
|
||||
if (CDebugSettings::HaveDebugger())
|
||||
{
|
||||
if (HaveExecutionBP() && g_Debugger->ExecutionBP(PROGRAM_COUNTER))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
|
||||
if (isStepping())
|
||||
{
|
||||
g_Debugger->WaitForStep();
|
||||
|
||||
if (SkipOp())
|
||||
{
|
||||
// Skip command if instructed by the debugger
|
||||
g_Settings->SaveBool(Debugger_SkipOp, false);
|
||||
PROGRAM_COUNTER += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CDebugSettings::HaveDebugger())
|
||||
{
|
||||
g_Debugger->CPUStepStarted();
|
||||
bool bSkip = SkipOp();
|
||||
|
||||
if (SkipOp())
|
||||
if (!bSkip)
|
||||
{
|
||||
g_Debugger->CPUStepStarted();
|
||||
bSkip = SkipOp();
|
||||
}
|
||||
|
||||
if (bSkip)
|
||||
{
|
||||
// Skip command if instructed by the debugger
|
||||
g_Settings->SaveBool(Debugger_SkipOp, false);
|
||||
PROGRAM_COUNTER += 4;
|
||||
continue;
|
||||
|
|
|
@ -339,6 +339,8 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory)
|
|||
AddHandler(Debugger_ReadBPExists, new CSettingTypeTempBool(false));
|
||||
AddHandler(Debugger_WaitingForStep, new CSettingTypeTempBool(false));
|
||||
AddHandler(Debugger_AutoRefreshMemoryView, new CSettingTypeApplication("Debugger", "Auto Refresh Memory View", true));
|
||||
AddHandler(Debugger_CPULoggingEnabled, new CSettingTypeApplication("Debugger", "Enable CPU Logging", false));
|
||||
AddHandler(Debugger_CPULogBufferSize, new CSettingTypeApplication("Debugger", "CPU Log Buffer Size", (uint32_t)1024));
|
||||
AddHandler(Debugger_DebugLanguage, new CSettingTypeApplication("Debugger", "Debug Language", false));
|
||||
AddHandler(Debugger_ShowDivByZero, new CSettingTypeApplication("Debugger", "Show Div by zero", false));
|
||||
AddHandler(Debugger_AppLogFlush, new CSettingTypeApplication("Logging", "Log Auto Flush", (uint32_t)false));
|
||||
|
|
|
@ -28,6 +28,7 @@ bool CDebugSettings::m_HaveExecutionBP = false;
|
|||
bool CDebugSettings::m_HaveWriteBP = false;
|
||||
bool CDebugSettings::m_HaveReadBP = false;
|
||||
bool CDebugSettings::m_bShowPifRamErrors = false;
|
||||
bool CDebugSettings::m_bCPULoggingEnabled = false;
|
||||
|
||||
CDebugSettings::CDebugSettings()
|
||||
{
|
||||
|
@ -47,6 +48,7 @@ CDebugSettings::CDebugSettings()
|
|||
g_Settings->RegisterChangeCB(Debugger_ReadBPExists, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->RegisterChangeCB(Debugger_WaitingForStep, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->RegisterChangeCB(Debugger_ShowPifErrors, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->RegisterChangeCB(Debugger_CPULoggingEnabled, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
|
||||
RefreshSettings();
|
||||
}
|
||||
|
@ -68,6 +70,7 @@ CDebugSettings::~CDebugSettings()
|
|||
g_Settings->UnregisterChangeCB(Debugger_WriteBPExists, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->UnregisterChangeCB(Debugger_WaitingForStep, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->UnregisterChangeCB(Debugger_ShowPifErrors, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
g_Settings->UnregisterChangeCB(Debugger_CPULoggingEnabled, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +88,7 @@ void CDebugSettings::RefreshSettings()
|
|||
m_HaveWriteBP = m_HaveDebugger && g_Settings->LoadBool(Debugger_WriteBPExists);
|
||||
m_HaveReadBP = m_HaveDebugger && g_Settings->LoadBool(Debugger_ReadBPExists);
|
||||
m_bShowPifRamErrors = m_HaveDebugger && g_Settings->LoadBool(Debugger_ShowPifErrors);
|
||||
m_bCPULoggingEnabled = m_HaveDebugger && g_Settings->LoadBool(Debugger_CPULoggingEnabled);
|
||||
|
||||
m_Debugging = m_HaveDebugger && (m_HaveExecutionBP || m_WaitingForStep || m_HaveWriteBP || m_HaveReadBP);
|
||||
}
|
|
@ -31,6 +31,7 @@ public:
|
|||
static inline bool HaveWriteBP(void) { return m_HaveWriteBP; }
|
||||
static inline bool HaveReadBP(void) { return m_HaveReadBP; }
|
||||
static inline bool bShowPifRamErrors(void) { return m_bShowPifRamErrors; }
|
||||
static inline bool bCPULoggingEnabled(void) { return m_bCPULoggingEnabled; }
|
||||
|
||||
private:
|
||||
static void StaticRefreshSettings(CDebugSettings * _this)
|
||||
|
@ -53,6 +54,7 @@ private:
|
|||
static bool m_HaveWriteBP;
|
||||
static bool m_HaveReadBP;
|
||||
static bool m_bShowPifRamErrors;
|
||||
static bool m_bCPULoggingEnabled;
|
||||
|
||||
static int32_t m_RefCount;
|
||||
static bool m_Registered;
|
||||
|
|
|
@ -253,6 +253,8 @@ enum SettingID
|
|||
Debugger_ReadBPExists,
|
||||
Debugger_WaitingForStep,
|
||||
Debugger_AutoRefreshMemoryView,
|
||||
Debugger_CPULoggingEnabled,
|
||||
Debugger_CPULogBufferSize,
|
||||
|
||||
//Trace
|
||||
Debugger_TraceMD5,
|
||||
|
|
|
@ -70,6 +70,8 @@
|
|||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="UserInterface\Debugger\CPULog.cpp" />
|
||||
<ClCompile Include="UserInterface\Debugger\Debugger-CPULogView.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="Multilanguage\LanguageSelector.cpp" />
|
||||
<ClCompile Include="Plugins\PluginList.cpp" />
|
||||
|
@ -130,6 +132,8 @@
|
|||
<ClCompile Include="UserInterface\WTLControls\PartialGroupBox.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="UserInterface\Debugger\CPULog.h" />
|
||||
<ClInclude Include="UserInterface\Debugger\Debugger-CPULogView.h" />
|
||||
<ClInclude Include="N64System\Debugger\OpInfo.h" />
|
||||
<ClInclude Include="Multilanguage\LanguageSelector.h" />
|
||||
<ClInclude Include="N64System.h" />
|
||||
|
|
|
@ -222,6 +222,12 @@
|
|||
<ClCompile Include="UserInterface\EnhancementConfig.cpp">
|
||||
<Filter>Source Files\User Interface Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface\Debugger\CPULog.cpp">
|
||||
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UserInterface\Debugger\Debugger-CPULogView.cpp">
|
||||
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="UserInterface\resource.h">
|
||||
|
@ -425,6 +431,12 @@
|
|||
<ClInclude Include="UserInterface\EnhancementConfig.h">
|
||||
<Filter>Header Files\User Interface Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UserInterface\Debugger\CPULog.h">
|
||||
<Filter>Header Files\User Interface Headers\Debugger Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UserInterface\Debugger\Debugger-CPULogView.h">
|
||||
<Filter>Header Files\User Interface Headers\Debugger Headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="res\divider.cur">
|
||||
|
|
|
@ -71,6 +71,7 @@ void RegisterUISettings (void)
|
|||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_MemoryDumpPos), new CSettingTypeApplication("Debugger UI", "Memory Dump Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_MemorySearchPos), new CSettingTypeApplication("Debugger UI", "Memory Search Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_DMALogPos), new CSettingTypeApplication("Debugger UI", "DMA Log Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_CPULogPos), new CSettingTypeApplication("Debugger UI", "CPU Log Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_ScriptsPos), new CSettingTypeApplication("Debugger UI", "Scripts Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_StackPos), new CSettingTypeApplication("Debugger UI", "Stack Pos", Default_None));
|
||||
g_Settings->AddHandler((SettingID)(FirstUISettings + DebuggerUI_StackTracePos), new CSettingTypeApplication("Debugger UI", "Stack Trace Pos", Default_None));
|
||||
|
|
|
@ -68,6 +68,7 @@ enum UISettingID
|
|||
DebuggerUI_MemoryDumpPos,
|
||||
DebuggerUI_MemorySearchPos,
|
||||
DebuggerUI_DMALogPos,
|
||||
DebuggerUI_CPULogPos,
|
||||
DebuggerUI_ScriptsPos,
|
||||
DebuggerUI_StackPos,
|
||||
DebuggerUI_StackTracePos,
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
#include "CPULog.h"
|
||||
|
||||
#include <Project64-core/N64System/Mips/OpCodeName.h>
|
||||
|
||||
CCPULog::CCPULog(size_t size) :
|
||||
m_bMaxed(false),
|
||||
m_Index(0)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
m_Size = size;
|
||||
}
|
||||
else if (!g_Settings->LoadBool(Debugger_CPULoggingEnabled))
|
||||
{
|
||||
m_Size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Size = g_Settings->LoadDword(Debugger_CPULogBufferSize);
|
||||
}
|
||||
|
||||
if (m_Size == 0)
|
||||
{
|
||||
m_Array = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_Array = new CPUState[m_Size];
|
||||
}
|
||||
|
||||
CCPULog::~CCPULog(void)
|
||||
{
|
||||
if (m_Array != NULL)
|
||||
{
|
||||
delete[] m_Array;
|
||||
m_Array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CCPULog::PushState()
|
||||
{
|
||||
if (m_Array == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Index == m_Size)
|
||||
{
|
||||
m_Index = 0;
|
||||
m_bMaxed = true;
|
||||
}
|
||||
|
||||
CPUState* state = &m_Array[m_Index++];
|
||||
|
||||
state->pc = g_Reg->m_PROGRAM_COUNTER;
|
||||
state->opcode = R4300iOp::m_Opcode;
|
||||
|
||||
memcpy(state->gpr, g_Reg->m_GPR, sizeof(g_Reg->m_GPR));
|
||||
state->gprHi = g_Reg->m_HI;
|
||||
state->gprLo = g_Reg->m_LO;
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
state->fpr[i] = *g_Reg->m_FPR_S[i];
|
||||
}
|
||||
|
||||
state->fpcr = g_Reg->m_FPCR[31];
|
||||
}
|
||||
|
||||
size_t CCPULog::GetCount(void)
|
||||
{
|
||||
if (m_bMaxed)
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
return m_Index;
|
||||
}
|
||||
|
||||
size_t CCPULog::GetSize(void)
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
CPUState* CCPULog::GetEntry(size_t index)
|
||||
{
|
||||
if (m_Array == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (m_bMaxed)
|
||||
{
|
||||
if (index >= m_Size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return &m_Array[(m_Index + index) % m_Size];
|
||||
}
|
||||
|
||||
if (index >= m_Index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &m_Array[index];
|
||||
}
|
||||
|
||||
void CCPULog::Reset()
|
||||
{
|
||||
size_t newSize;
|
||||
|
||||
if (!g_Settings->LoadBool(Debugger_CPULoggingEnabled))
|
||||
{
|
||||
newSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
newSize = g_Settings->LoadDword(Debugger_CPULogBufferSize);
|
||||
}
|
||||
|
||||
m_Index = 0;
|
||||
m_bMaxed = false;
|
||||
|
||||
if (m_Size != newSize)
|
||||
{
|
||||
m_Size = newSize;
|
||||
|
||||
if (m_Array != NULL)
|
||||
{
|
||||
delete[] m_Array;
|
||||
m_Array = NULL;
|
||||
}
|
||||
|
||||
if (m_Size != 0)
|
||||
{
|
||||
m_Array = new CPUState[m_Size];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCPULog* CCPULog::Clone(void)
|
||||
{
|
||||
if (m_Array == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CCPULog *clone = new CCPULog(m_Size);
|
||||
clone->m_bMaxed = m_bMaxed;
|
||||
clone->m_Index = m_Index;
|
||||
memcpy(clone->m_Array, m_Array, sizeof(CPUState) * m_Size);
|
||||
return clone;
|
||||
}
|
||||
|
||||
void CCPULog::DumpToFile(const char* path)
|
||||
{
|
||||
FILE* fp = fopen(path, "wb");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = GetCount();
|
||||
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
CPUState* state = GetEntry(i);
|
||||
|
||||
char *tokctx;
|
||||
|
||||
char* szCommand = (char*)R4300iOpcodeName(state->opcode.Hex, state->pc);
|
||||
char* szCmdName = strtok_s((char*)szCommand, "\t", &tokctx);
|
||||
char* szCmdArgs = strtok_s(NULL, "\t", &tokctx);
|
||||
|
||||
if (szCmdArgs == NULL)
|
||||
{
|
||||
szCmdArgs = "";
|
||||
}
|
||||
|
||||
fprintf(fp, "%08X: %08X %s %s\n", state->pc, state->opcode, szCmdName, szCmdArgs);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdafx.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t pc;
|
||||
OPCODE opcode;
|
||||
MIPS_DWORD gpr[32];
|
||||
MIPS_DWORD gprHi;
|
||||
MIPS_DWORD gprLo;
|
||||
float fpr[32];
|
||||
uint32_t fpcr;
|
||||
} CPUState;
|
||||
|
||||
class CCPULog
|
||||
{
|
||||
size_t m_Size;
|
||||
bool m_bMaxed;
|
||||
size_t m_Index;
|
||||
CPUState* m_Array;
|
||||
|
||||
public:
|
||||
CCPULog(size_t size = 0);
|
||||
~CCPULog(void);
|
||||
void PushState(void);
|
||||
size_t GetCount(void);
|
||||
size_t GetSize(void);
|
||||
CPUState* GetEntry(size_t index);
|
||||
void Reset(void);
|
||||
CCPULog* Clone(void);
|
||||
void DumpToFile(const char* path);
|
||||
};
|
|
@ -0,0 +1,426 @@
|
|||
#include "stdafx.h"
|
||||
#include "DebuggerUI.h"
|
||||
#include "CPULog.h"
|
||||
|
||||
#include "Debugger-CPULogView.h"
|
||||
#include <Project64-core/N64System/Mips/OpCodeName.h>
|
||||
|
||||
CDebugCPULogView* CDebugCPULogView::_this = NULL;
|
||||
HHOOK CDebugCPULogView::hWinMessageHook = NULL;
|
||||
|
||||
CDebugCPULogView::CDebugCPULogView(CDebuggerUI* debugger) :
|
||||
CDebugDialog<CDebugCPULogView>(debugger),
|
||||
m_CPULogCopy(NULL),
|
||||
m_LogStartIndex(0),
|
||||
m_RowHeight(13)
|
||||
{
|
||||
}
|
||||
|
||||
CDebugCPULogView::~CDebugCPULogView()
|
||||
{
|
||||
if (m_CPULogCopy != NULL)
|
||||
{
|
||||
delete m_CPULogCopy;
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
DlgResize_Init(false, true);
|
||||
DlgToolTip_Init();
|
||||
DlgSavePos_Init(DebuggerUI_CPULogPos);
|
||||
|
||||
m_CPUListView.Attach(GetDlgItem(IDC_CPU_LIST));
|
||||
m_StateInfoEdit.Attach(GetDlgItem(IDC_STATEINFO_EDIT));
|
||||
m_EnabledChk.Attach(GetDlgItem(IDC_CHK_ENABLE));
|
||||
m_BuffSizeEdit.Attach(GetDlgItem(IDC_BUFFSIZE_EDIT));
|
||||
m_Scrollbar.Attach(GetDlgItem(IDC_SCRL_BAR));
|
||||
m_ExportBtn.Attach(GetDlgItem(IDC_BTN_EXPORT));
|
||||
|
||||
m_CPUListView.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
|
||||
m_CPUListView.ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0);
|
||||
m_CPUListView.AddColumn("PC", 0);
|
||||
m_CPUListView.AddColumn("Command", 1);
|
||||
m_CPUListView.AddColumn("Parameters", 2);
|
||||
m_CPUListView.SetColumnWidth(0, 65);
|
||||
m_CPUListView.SetColumnWidth(1, 60);
|
||||
m_CPUListView.SetColumnWidth(2, 120);
|
||||
|
||||
bool bLoggingEnabled = g_Settings->LoadBool(Debugger_CPULoggingEnabled);
|
||||
uint32_t bufferSize = g_Settings->LoadDword(Debugger_CPULogBufferSize);
|
||||
|
||||
m_EnabledChk.SetCheck(bLoggingEnabled);
|
||||
|
||||
m_BuffSizeEdit.SetDisplayType(CEditNumber32::DisplayDec);
|
||||
m_BuffSizeEdit.SetValue(bufferSize);
|
||||
m_BuffSizeEdit.EnableWindow(!bLoggingEnabled);
|
||||
|
||||
RefreshList(true);
|
||||
|
||||
m_ExportBtn.EnableWindow(false);
|
||||
|
||||
if (!bLoggingEnabled && m_CPULogCopy != NULL)
|
||||
{
|
||||
m_ExportBtn.EnableWindow(true);
|
||||
}
|
||||
|
||||
_this = this;
|
||||
DWORD dwThreadID = ::GetCurrentThreadId();
|
||||
hWinMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, NULL, dwThreadID);
|
||||
|
||||
LoadWindowPos();
|
||||
WindowCreated();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnDestroy(void)
|
||||
{
|
||||
m_CPUListView.Detach();
|
||||
m_StateInfoEdit.Detach();
|
||||
m_EnabledChk.Detach();
|
||||
m_BuffSizeEdit.Detach();
|
||||
m_Scrollbar.Detach();
|
||||
m_ExportBtn.Detach();
|
||||
|
||||
if (m_CPULogCopy != NULL)
|
||||
{
|
||||
delete m_CPULogCopy;
|
||||
m_CPULogCopy = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CDebugCPULogView::HookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
MSG *pMsg = (MSG*)lParam;
|
||||
|
||||
switch (pMsg->message)
|
||||
{
|
||||
case WM_MOUSEWHEEL:
|
||||
_this->InterceptMouseWheel(pMsg->wParam, pMsg->lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (nCode < 0)
|
||||
{
|
||||
return CallNextHookEx(hWinMessageHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL& /*bHandled*/)
|
||||
{
|
||||
switch (wID)
|
||||
{
|
||||
case IDOK:
|
||||
EndDialog(0);
|
||||
break;
|
||||
case IDCANCEL:
|
||||
EndDialog(0);
|
||||
break;
|
||||
case IDC_CHK_ENABLE:
|
||||
ToggleLoggingEnabled();
|
||||
break;
|
||||
case IDC_BTN_EXPORT:
|
||||
Export();
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnListItemChanged(NMHDR* pNMHDR)
|
||||
{
|
||||
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
|
||||
int nItem = pIA->iItem;
|
||||
|
||||
ShowRegStates(m_LogStartIndex + nItem);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnListDblClicked(NMHDR* pNMHDR)
|
||||
{
|
||||
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
|
||||
int nItem = pIA->iItem;
|
||||
|
||||
CPUState* state = m_CPULogCopy->GetEntry(m_LogStartIndex + nItem);
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_Debugger->Debug_ShowCommandsLocation(state->pc, true);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnMeasureItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
|
||||
{
|
||||
if (wParam == IDC_CPU_LIST)
|
||||
{
|
||||
CClientDC dc(m_hWnd);
|
||||
dc.SelectFont(GetFont());
|
||||
TEXTMETRIC tm;
|
||||
dc.GetTextMetrics(&tm);
|
||||
|
||||
m_RowHeight = tm.tmHeight + tm.tmExternalLeading;
|
||||
|
||||
MEASUREITEMSTRUCT* lpMeasureItem = (MEASUREITEMSTRUCT*)lParam;
|
||||
lpMeasureItem->itemHeight = m_RowHeight;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CDebugCPULogView::OnScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
|
||||
{
|
||||
WORD type = LOWORD(wParam);
|
||||
HWND hScrollbar = (HWND)lParam;
|
||||
WORD scrlId = ::GetDlgCtrlID(hScrollbar);
|
||||
|
||||
SCROLLINFO scrollInfo;
|
||||
scrollInfo.cbSize = sizeof(SCROLLINFO);
|
||||
scrollInfo.fMask = SIF_ALL;
|
||||
|
||||
::GetScrollInfo(hScrollbar, SB_CTL, &scrollInfo);
|
||||
|
||||
int newPos;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SB_LINEUP: newPos = scrollInfo.nPos - 1; break;
|
||||
case SB_LINEDOWN: newPos = scrollInfo.nPos + 1; break;
|
||||
case SB_THUMBTRACK: newPos = scrollInfo.nTrackPos; break;
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
m_LogStartIndex = newPos;
|
||||
::SetScrollPos(hScrollbar, SB_CTL, m_LogStartIndex, TRUE);
|
||||
|
||||
if (scrlId == IDC_SCRL_BAR)
|
||||
{
|
||||
RefreshList(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CDebugCPULogView::InterceptMouseWheel(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int nScroll = -((short)HIWORD(wParam) / WHEEL_DELTA);
|
||||
|
||||
if (MouseHovering(IDC_CPU_LIST) || MouseHovering(IDC_SCRL_BAR))
|
||||
{
|
||||
// scroll results list
|
||||
int scrollPos = m_Scrollbar.GetScrollPos();
|
||||
int m_ListStartIndex = scrollPos + nScroll;
|
||||
m_Scrollbar.SetScrollPos(m_ListStartIndex);
|
||||
RefreshList(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugCPULogView::OnExitSizeMove(void)
|
||||
{
|
||||
RefreshList(false);
|
||||
SaveWindowPos();
|
||||
}
|
||||
|
||||
void CDebugCPULogView::ToggleLoggingEnabled(void)
|
||||
{
|
||||
bool bEnableLogging = m_EnabledChk.GetCheck();
|
||||
|
||||
m_BuffSizeEdit.EnableWindow(!bEnableLogging);
|
||||
|
||||
g_Settings->SaveBool(Debugger_CPULoggingEnabled, bEnableLogging);
|
||||
|
||||
if (bEnableLogging)
|
||||
{
|
||||
uint32_t newSize = m_BuffSizeEdit.GetValue();
|
||||
g_Settings->SaveDword(Debugger_CPULogBufferSize, newSize);
|
||||
m_Debugger->CPULog()->Reset();
|
||||
m_ExportBtn.EnableWindow(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
RefreshList(true);
|
||||
m_ExportBtn.EnableWindow(m_CPULogCopy != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CDebugCPULogView::RefreshList(bool bUpdateBuffer)
|
||||
{
|
||||
if (bUpdateBuffer)
|
||||
{
|
||||
if (m_CPULogCopy != NULL)
|
||||
{
|
||||
delete m_CPULogCopy;
|
||||
}
|
||||
|
||||
m_CPULogCopy = m_Debugger->CPULog()->Clone();
|
||||
}
|
||||
|
||||
if (m_CPULogCopy == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
size_t count = m_CPULogCopy->GetCount();
|
||||
size_t numVisibleRows = GetNumVisibleRows(m_CPUListView);
|
||||
|
||||
bool bCanDisplayAll = (numVisibleRows >= count);
|
||||
int scrollRangeMax = bCanDisplayAll ? 0 : count - numVisibleRows;
|
||||
|
||||
m_Scrollbar.SetScrollRange(0, scrollRangeMax, false);
|
||||
m_Scrollbar.EnableWindow(!bCanDisplayAll);
|
||||
|
||||
if (bUpdateBuffer)
|
||||
{
|
||||
m_LogStartIndex = scrollRangeMax;
|
||||
m_Scrollbar.SetScrollPos(m_LogStartIndex, true);
|
||||
}
|
||||
|
||||
size_t start = m_Scrollbar.GetScrollPos();
|
||||
size_t end = start + numVisibleRows;
|
||||
|
||||
if (end > count)
|
||||
{
|
||||
end = count;
|
||||
}
|
||||
|
||||
m_CPUListView.SetRedraw(FALSE);
|
||||
m_CPUListView.DeleteAllItems();
|
||||
|
||||
int nItem = 0;
|
||||
|
||||
for (size_t i = start; i < end; i++)
|
||||
{
|
||||
CPUState* state = m_CPULogCopy->GetEntry(i);
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
char szPC[9];
|
||||
sprintf(szPC, "%08X", state->pc);
|
||||
|
||||
char *tokctx;
|
||||
|
||||
char* szCommand = (char*)R4300iOpcodeName(state->opcode.Hex, state->pc);
|
||||
char* szCmdName = strtok_s((char*)szCommand, "\t", &tokctx);
|
||||
char* szCmdArgs = strtok_s(NULL, "\t", &tokctx);
|
||||
|
||||
m_CPUListView.AddItem(nItem, 0, szPC);
|
||||
m_CPUListView.AddItem(nItem, 1, szCmdName);
|
||||
m_CPUListView.AddItem(nItem, 2, szCmdArgs);
|
||||
|
||||
nItem++;
|
||||
}
|
||||
|
||||
m_CPUListView.SetRedraw(TRUE);
|
||||
|
||||
ShowRegStates(count - 1);
|
||||
}
|
||||
|
||||
void CDebugCPULogView::ShowRegStates(size_t stateIndex)
|
||||
{
|
||||
CPUState* state = m_CPULogCopy->GetEntry(stateIndex);
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char szRegStates[2048];
|
||||
char* out = szRegStates;
|
||||
|
||||
out += sprintf(out, "PC: %08X\r\n\r\n", state->pc);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int regl = i, regr = i + 16;
|
||||
out += sprintf(out, "%s: %08X %08X %s: %08X %08X\r\n",
|
||||
CRegName::GPR[regl], state->gpr[regl].UW[1], state->gpr[regl].UW[0],
|
||||
CRegName::GPR[regr], state->gpr[regr].UW[1], state->gpr[regr].UW[0]);
|
||||
}
|
||||
|
||||
out += sprintf(out, "HI: %08X %08X LO: %08X %08X\r\n\r\n",
|
||||
state->gprHi.UW[1], state->gprHi.UW[0],
|
||||
state->gprLo.UW[1], state->gprLo.UW[0]);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
int regl = i, regr = i + 16;
|
||||
out += sprintf(out, "%-3s: %08X %-3s: %08X\r\n",
|
||||
CRegName::FPR[regl], *(uint32_t*)&state->fpr[regl],
|
||||
CRegName::FPR[regr], *(uint32_t*)&state->fpr[regr]);
|
||||
}
|
||||
|
||||
out += sprintf(out, "FPCR: %08X\r\n", state->fpcr);
|
||||
|
||||
m_StateInfoEdit.SetWindowTextA(szRegStates);
|
||||
}
|
||||
|
||||
void CDebugCPULogView::Export(void)
|
||||
{
|
||||
if (m_CPULogCopy == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OPENFILENAME openfilename;
|
||||
char filePath[255];
|
||||
char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
|
||||
|
||||
memset(&filePath, 0, sizeof(filePath));
|
||||
memset(&openfilename, 0, sizeof(openfilename));
|
||||
|
||||
sprintf(filePath, "CPULOG.txt");
|
||||
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)m_hWnd;
|
||||
openfilename.lpstrFilter = "CPU Log (*.*)\0*.*;\0";
|
||||
openfilename.lpstrFile = filePath;
|
||||
openfilename.lpstrInitialDir = "Logs";
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
openfilename.Flags = OFN_HIDEREADONLY;
|
||||
|
||||
if (GetSaveFileName(&openfilename))
|
||||
{
|
||||
m_CPULogCopy->DumpToFile(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
// util
|
||||
|
||||
int CDebugCPULogView::GetNumVisibleRows(CListViewCtrl& list)
|
||||
{
|
||||
CHeaderCtrl header = list.GetHeader();
|
||||
CRect listRect, headRect;
|
||||
list.GetWindowRect(&listRect);
|
||||
header.GetWindowRect(&headRect);
|
||||
int innerHeight = listRect.Height() - headRect.Height();
|
||||
return (innerHeight / m_RowHeight);
|
||||
}
|
||||
|
||||
bool CDebugCPULogView::MouseHovering(WORD ctrlId, int xMargin, int yMargin)
|
||||
{
|
||||
CRect rect;
|
||||
POINT pointerPos;
|
||||
|
||||
::GetWindowRect(GetDlgItem(ctrlId), &rect);
|
||||
::GetCursorPos(&pointerPos);
|
||||
|
||||
return (
|
||||
pointerPos.x >= rect.left - xMargin &&
|
||||
pointerPos.x <= rect.right + xMargin &&
|
||||
pointerPos.y >= rect.top - yMargin &&
|
||||
pointerPos.y <= rect.bottom + yMargin);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "DebuggerUI.h"
|
||||
|
||||
class CDebugCPULogView :
|
||||
public CDebugDialog<CDebugCPULogView>,
|
||||
public CDialogResize<CDebugCPULogView>,
|
||||
public CToolTipDialog<CDebugCPULogView>
|
||||
{
|
||||
public:
|
||||
enum { IDD = IDD_Debugger_CPULog };
|
||||
|
||||
CDebugCPULogView(CDebuggerUI * debugger);
|
||||
virtual ~CDebugCPULogView(void);
|
||||
|
||||
void RefreshList(bool bUpdateBuffer = true);
|
||||
|
||||
private:
|
||||
CCPULog* m_CPULogCopy;
|
||||
|
||||
int m_RowHeight;
|
||||
int m_LogStartIndex;
|
||||
|
||||
CListViewCtrl m_CPUListView;
|
||||
CEdit m_StateInfoEdit;
|
||||
CEditNumber32 m_BuffSizeEdit;
|
||||
CButton m_EnabledChk;
|
||||
CScrollBar m_Scrollbar;
|
||||
CButton m_ExportBtn;
|
||||
|
||||
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
|
||||
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled);
|
||||
LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
|
||||
LRESULT OnListDblClicked(NMHDR* pNMHDR);
|
||||
LRESULT OnListItemChanged(NMHDR* pNMHDR);
|
||||
LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/);
|
||||
LRESULT OnScroll(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/);
|
||||
void OnExitSizeMove(void);
|
||||
LRESULT OnDestroy(void);
|
||||
|
||||
|
||||
void InterceptMouseWheel(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static CDebugCPULogView* _this;
|
||||
static HHOOK hWinMessageHook;
|
||||
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void ToggleLoggingEnabled(void);
|
||||
void ShowRegStates(size_t stateIndex);
|
||||
void Export(void);
|
||||
|
||||
int GetNumVisibleRows(CListViewCtrl& list);
|
||||
bool MouseHovering(WORD ctrlId, int xMargin = 0, int yMargin = 0);
|
||||
|
||||
BEGIN_MSG_MAP_EX(CDebugCPULogView)
|
||||
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
|
||||
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
|
||||
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
|
||||
NOTIFY_HANDLER_EX(IDC_CPU_LIST, NM_DBLCLK, OnListDblClicked)
|
||||
NOTIFY_HANDLER_EX(IDC_CPU_LIST, LVN_ITEMCHANGED, OnListItemChanged)
|
||||
MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
|
||||
MESSAGE_HANDLER(WM_VSCROLL, OnScroll)
|
||||
MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
|
||||
CHAIN_MSG_MAP(CDialogResize<CDebugCPULogView>)
|
||||
END_MSG_MAP()
|
||||
|
||||
BEGIN_DLGRESIZE_MAP(CDebugCPULogView)
|
||||
DLGRESIZE_CONTROL(IDC_CPU_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
|
||||
DLGRESIZE_CONTROL(IDC_REGSTATES_GRP, DLSZ_MOVE_X | DLSZ_SIZE_Y)
|
||||
DLGRESIZE_CONTROL(IDC_STATEINFO_EDIT, DLSZ_MOVE_X | DLSZ_SIZE_Y)
|
||||
DLGRESIZE_CONTROL(IDC_SCRL_BAR, DLSZ_SIZE_Y)
|
||||
END_DLGRESIZE_MAP()
|
||||
|
||||
BEGIN_TOOLTIP_MAP()
|
||||
TOOLTIP(IDC_BUFFSIZE_EDIT, "Maximum number of states to keep (1024 = 416kB)") // sizeof(CPUState)
|
||||
END_TOOLTIP_MAP()
|
||||
};
|
|
@ -13,6 +13,7 @@
|
|||
#include "DebuggerUI.h"
|
||||
#include "ScriptHook.h"
|
||||
|
||||
#include "CPULog.h"
|
||||
#include "DMALog.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
|
@ -31,7 +32,9 @@ CDebuggerUI::CDebuggerUI() :
|
|||
m_StackTrace(NULL),
|
||||
m_StackView(NULL),
|
||||
m_DMALogView(NULL),
|
||||
m_CPULogView(NULL),
|
||||
m_DMALog(NULL),
|
||||
m_CPULog(NULL),
|
||||
m_StepEvent(false)
|
||||
{
|
||||
g_Debugger = this;
|
||||
|
@ -40,6 +43,7 @@ CDebuggerUI::CDebuggerUI() :
|
|||
m_ScriptSystem = new CScriptSystem(this);
|
||||
|
||||
m_DMALog = new CDMALog();
|
||||
m_CPULog = new CCPULog();
|
||||
|
||||
CSymbols::InitializeCriticalSection();
|
||||
g_Settings->RegisterChangeCB(GameRunning_InReset, this, (CSettings::SettingChangedFunc)GameReset);
|
||||
|
@ -60,7 +64,9 @@ CDebuggerUI::~CDebuggerUI(void)
|
|||
delete m_MemorySearch;
|
||||
delete m_StackTrace;
|
||||
delete m_DMALogView;
|
||||
delete m_CPULogView;
|
||||
delete m_DMALog;
|
||||
delete m_CPULog;
|
||||
|
||||
CSymbols::DeleteCriticalSection();
|
||||
}
|
||||
|
@ -155,6 +161,12 @@ void CDebuggerUI::Debug_Reset(void)
|
|||
delete m_DMALogView;
|
||||
m_DMALogView = NULL;
|
||||
}
|
||||
if (m_CPULogView)
|
||||
{
|
||||
m_CPULogView->HideWindow();
|
||||
delete m_CPULogView;
|
||||
m_CPULogView = NULL;
|
||||
}
|
||||
if (m_StackTrace)
|
||||
{
|
||||
m_StackTrace->HideWindow();
|
||||
|
@ -323,6 +335,15 @@ void CDebuggerUI::OpenDMALogWindow(void)
|
|||
m_DMALogView->ShowWindow();
|
||||
}
|
||||
|
||||
void CDebuggerUI::OpenCPULogWindow(void)
|
||||
{
|
||||
if (m_CPULogView == NULL)
|
||||
{
|
||||
m_CPULogView = new CDebugCPULogView(this);
|
||||
}
|
||||
m_CPULogView->ShowWindow();
|
||||
}
|
||||
|
||||
void CDebuggerUI::OpenStackTraceWindow(void)
|
||||
{
|
||||
if (m_StackTrace == NULL)
|
||||
|
@ -357,6 +378,14 @@ void CDebuggerUI::Debug_RefreshStackTraceWindow(void)
|
|||
}
|
||||
}
|
||||
|
||||
void CDebuggerUI::Debug_RefreshCPULogWindow(void)
|
||||
{
|
||||
if (m_CPULogView != NULL)
|
||||
{
|
||||
m_CPULogView->RefreshList();
|
||||
}
|
||||
}
|
||||
|
||||
CBreakpoints* CDebuggerUI::Breakpoints()
|
||||
{
|
||||
return m_Breakpoints;
|
||||
|
@ -377,6 +406,11 @@ CDMALog* CDebuggerUI::DMALog()
|
|||
return m_DMALog;
|
||||
}
|
||||
|
||||
CCPULog* CDebuggerUI::CPULog()
|
||||
{
|
||||
return m_CPULog;
|
||||
}
|
||||
|
||||
// thread safe LW_PAddr
|
||||
// does not trigger application breakpoint if paddr is invalid
|
||||
bool CDebuggerUI::DebugLW_PAddr(uint32_t paddr, uint32_t& value)
|
||||
|
@ -570,20 +604,69 @@ void CDebuggerUI::TLBChanged()
|
|||
Debug_RefreshTLBWindow();
|
||||
}
|
||||
|
||||
// Exception handling - break on exception vector and show cpu log on certain errors
|
||||
void CDebuggerUI::HandleCPUException(void)
|
||||
{
|
||||
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
|
||||
int exc = g_Reg->CAUSE_REGISTER & 0x7C;
|
||||
|
||||
// ignore interrupt, syscall, coprocessor unusable, watch
|
||||
if (exc != EXC_INT && exc != EXC_SYSCALL && exc != EXC_CPU && exc != EXC_WATCH)
|
||||
{
|
||||
if (CDebugSettings::bCPULoggingEnabled())
|
||||
{
|
||||
g_Debugger->OpenCPULogWindow();
|
||||
}
|
||||
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CDebuggerUI::HandleCartToRamDMA(void)
|
||||
{
|
||||
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||
|
||||
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
|
||||
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
|
||||
uint32_t dmaLen = opInfo.GetStoreValueUnsigned() + 1;
|
||||
|
||||
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
|
||||
|
||||
// break if write breakpoint exists anywhere in target buffer
|
||||
if (m_Breakpoints->WriteBPExistsInChunk(dmaRamAddr, dmaLen))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Called from the interpreter core at the beginning of every CPU step
|
||||
void CDebuggerUI::CPUStepStarted()
|
||||
{
|
||||
uint32_t PROGRAM_COUNTER = g_Reg->m_PROGRAM_COUNTER;
|
||||
uint32_t JumpToLocation = R4300iOp::m_JumpToLocation;
|
||||
|
||||
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(PROGRAM_COUNTER);
|
||||
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(PROGRAM_COUNTER, R4300iOp::m_Opcode.Hex);
|
||||
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(PROGRAM_COUNTER);
|
||||
|
||||
// Memory breakpoints
|
||||
|
||||
uint32_t pc = g_Reg->m_PROGRAM_COUNTER;
|
||||
COpInfo opInfo(R4300iOp::m_Opcode);
|
||||
|
||||
if (opInfo.IsStoreCommand())
|
||||
{
|
||||
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||
|
||||
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
|
||||
{
|
||||
// Memory is locked, skip op
|
||||
g_Settings->SaveBool(Debugger_SkipOp, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_ScriptSystem->HookCPUExec()->InvokeByAddressInRange(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
m_ScriptSystem->HookCPUExecOpcode()->InvokeByAddressInRange_MaskedOpcode(pc, R4300iOp::m_Opcode.Hex);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
m_ScriptSystem->HookCPUGPRValue()->InvokeByAddressInRange_GPRValue(pc);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
// Memory events, pi cart -> ram dma
|
||||
if (opInfo.IsLoadStoreCommand()) // Read and write instructions
|
||||
{
|
||||
uint32_t memoryAddress = opInfo.GetLoadStoreAddress();
|
||||
|
@ -591,53 +674,35 @@ void CDebuggerUI::CPUStepStarted()
|
|||
if (opInfo.IsLoadCommand()) // Read instructions
|
||||
{
|
||||
m_ScriptSystem->HookCPURead()->InvokeByAddressInRange(memoryAddress);
|
||||
if (SkipOp()) { return; }
|
||||
}
|
||||
else // Write instructions
|
||||
{
|
||||
m_ScriptSystem->HookCPUWrite()->InvokeByAddressInRange(memoryAddress);
|
||||
if (SkipOp()) { return; }
|
||||
|
||||
// Catch cart -> rdram dma
|
||||
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG
|
||||
{
|
||||
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
|
||||
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
|
||||
uint32_t dmaLen = opInfo.GetStoreValueUnsigned() + 1;
|
||||
|
||||
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
|
||||
|
||||
if (m_Breakpoints->WriteBPExistsInChunk(dmaRamAddr, dmaLen))
|
||||
{
|
||||
goto breakpoint_hit;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Breakpoints->MemLockExists(memoryAddress, opInfo.NumBytesToStore()))
|
||||
{
|
||||
g_Settings->SaveBool(Debugger_SkipOp, true);
|
||||
HandleCartToRamDMA();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isStepping())
|
||||
if (pc == 0x80000000 || pc == 0x80000080 ||
|
||||
pc == 0xA0000100 || pc == 0x80000180)
|
||||
{
|
||||
return;
|
||||
HandleCPUException();
|
||||
}
|
||||
|
||||
if (R4300iOp::m_NextInstruction != JUMP)
|
||||
if (bCPULoggingEnabled())
|
||||
{
|
||||
goto breakpoint_hit;
|
||||
m_CPULog->PushState();
|
||||
|
||||
if (isStepping())
|
||||
{
|
||||
Debug_RefreshCPULogWindow();
|
||||
}
|
||||
}
|
||||
|
||||
if (JumpToLocation == PROGRAM_COUNTER + 4)
|
||||
{
|
||||
// Only pause on delay slots when branch isn't taken
|
||||
goto breakpoint_hit;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
breakpoint_hit:
|
||||
g_Settings->SaveBool(Debugger_SteppingOps, true);
|
||||
}
|
||||
|
||||
void CDebuggerUI::CPUStep()
|
||||
|
|
|
@ -13,5 +13,6 @@
|
|||
#include "Debugger-AddBreakpoint.h"
|
||||
#include "Debugger-AddSymbol.h"
|
||||
#include "Debugger-DMALogView.h"
|
||||
#include "Debugger-CPULogView.h"
|
||||
#include "Debugger-StackView.h"
|
||||
#include "Debugger-StackTrace.h"
|
|
@ -150,6 +150,12 @@ public:
|
|||
return (m_OpCode.op <= R4300i_LWU || (m_OpCode.op >= R4300i_LL && m_OpCode.op <= R4300i_LD));
|
||||
}
|
||||
|
||||
inline bool IsStoreCommand()
|
||||
{
|
||||
return (m_OpCode.op >= R4300i_SB && m_OpCode.op <= R4300i_SWR ||
|
||||
m_OpCode.op >= R4300i_SC && m_OpCode.op <= R4300i_SD);
|
||||
}
|
||||
|
||||
bool IsStackShift()
|
||||
{
|
||||
return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29;
|
||||
|
|
|
@ -21,9 +21,11 @@ class CDebugCommandsView;
|
|||
class CDebugScripts;
|
||||
class CDebugSymbols;
|
||||
class CDebugDMALogView;
|
||||
class CDebugCPULogView;
|
||||
class CDebugStackView;
|
||||
class CDebugStackTrace;
|
||||
|
||||
class CCPULog;
|
||||
class CDMALog;
|
||||
class CBreakpoints;
|
||||
class CScriptSystem;
|
||||
|
@ -57,6 +59,8 @@ public:
|
|||
void Debug_RefreshStackWindow(void);
|
||||
void Debug_RefreshStackTraceWindow(void);
|
||||
void OpenDMALogWindow(void);
|
||||
void OpenCPULogWindow(void);
|
||||
void Debug_RefreshCPULogWindow(void);
|
||||
|
||||
bool ExecutionBP(uint32_t address);
|
||||
bool ReadBP8(uint32_t address);
|
||||
|
@ -74,6 +78,7 @@ public:
|
|||
CScriptSystem* ScriptSystem();
|
||||
CDebugScripts* ScriptConsole();
|
||||
CDMALog* DMALog();
|
||||
CCPULog* CPULog();
|
||||
|
||||
static void GameReset(CDebuggerUI * _this);
|
||||
static void SteppingOpsChanged(CDebuggerUI * _this);
|
||||
|
@ -88,8 +93,8 @@ protected:
|
|||
void FrameDrawn(void);
|
||||
|
||||
private:
|
||||
CDebuggerUI(const CDebuggerUI&); // Disable copy constructor
|
||||
CDebuggerUI& operator=(const CDebuggerUI&); // Disable assignment
|
||||
CDebuggerUI(const CDebuggerUI&); // Disable copy constructor
|
||||
CDebuggerUI& operator=(const CDebuggerUI&); // Disable assignment
|
||||
|
||||
CDumpMemory * m_MemoryDump;
|
||||
CDebugMemoryView * m_MemoryView;
|
||||
|
@ -99,13 +104,17 @@ private:
|
|||
CDebugScripts * m_Scripts;
|
||||
CDebugSymbols * m_Symbols;
|
||||
CDebugDMALogView * m_DMALogView;
|
||||
CDebugCPULogView * m_CPULogView;
|
||||
CDebugStackTrace * m_StackTrace;
|
||||
CDebugStackView * m_StackView;
|
||||
|
||||
CBreakpoints * m_Breakpoints;
|
||||
CScriptSystem * m_ScriptSystem;
|
||||
CDMALog * m_DMALog;
|
||||
CCPULog * m_CPULog;
|
||||
|
||||
SyncEvent m_StepEvent;
|
||||
|
||||
void HandleCPUException(void);
|
||||
void HandleCartToRamDMA(void);
|
||||
};
|
||||
|
|
|
@ -52,9 +52,9 @@ CMainMenu::CMainMenu(CMainGui * hMainWindow) :
|
|||
m_ChangeSettingList.push_back(Debugger_TraceUserInterface);
|
||||
m_ChangeSettingList.push_back(Debugger_AppLogFlush);
|
||||
m_ChangeSettingList.push_back(Game_CurrentSaveState);
|
||||
m_ChangeSettingList.push_back(Setting_CurrentLanguage);
|
||||
m_ChangeSettingList.push_back(Setting_Enhancement);
|
||||
|
||||
m_ChangeSettingList.push_back(Setting_CurrentLanguage);
|
||||
m_ChangeSettingList.push_back(Setting_Enhancement);
|
||||
|
||||
for (UISettingList::const_iterator iter = m_ChangeUISettingList.begin(); iter != m_ChangeUISettingList.end(); iter++)
|
||||
{
|
||||
g_Settings->RegisterChangeCB((SettingID)(FirstUISettings + *iter), this, (CSettings::SettingChangedFunc)SettingsChanged);
|
||||
|
@ -513,6 +513,7 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
|
|||
case ID_DEBUGGER_SCRIPTS: g_Debugger->OpenScriptsWindow(); break;
|
||||
case ID_DEBUGGER_SYMBOLS: g_Debugger->OpenSymbolsWindow(); break;
|
||||
case ID_DEBUGGER_DMALOG: g_Debugger->OpenDMALogWindow(); break;
|
||||
case ID_DEBUGGER_CPULOG: g_Debugger->OpenCPULogWindow(); break;
|
||||
case ID_DEBUGGER_STACKTRACE: g_Debugger->OpenStackTraceWindow(); break;
|
||||
case ID_DEBUGGER_STACKVIEW: g_Debugger->OpenStackViewWindow(); break;
|
||||
case ID_CURRENT_SAVE_DEFAULT:
|
||||
|
@ -1149,6 +1150,12 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
|
|||
//Item.SetItemEnabled(CPURunning);
|
||||
DebugMenu.push_back(Item);
|
||||
|
||||
/* Debug - CPU Log
|
||||
*******************/
|
||||
Item.Reset(ID_DEBUGGER_CPULOG, EMPTY_STRING, EMPTY_STDSTR, NULL, L"CPU Log...");
|
||||
//Item.SetItemEnabled(CPURunning);
|
||||
DebugMenu.push_back(Item);
|
||||
|
||||
/* Debug - Stack
|
||||
*******************/
|
||||
Item.Reset(ID_DEBUGGER_STACKVIEW, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Stack...");
|
||||
|
|
|
@ -40,7 +40,7 @@ enum MainMenuID
|
|||
ID_DEBUGGER_TLBENTRIES, ID_DEBUGGER_BREAKPOINTS, ID_DEBUGGER_MEMORY, ID_DEBUGGER_R4300REGISTERS,
|
||||
ID_DEBUGGER_INTERRUPT_SP, ID_DEBUGGER_INTERRUPT_SI, ID_DEBUGGER_INTERRUPT_AI, ID_DEBUGGER_INTERRUPT_VI,
|
||||
ID_DEBUGGER_INTERRUPT_PI, ID_DEBUGGER_INTERRUPT_DP, ID_DEBUGGER_SCRIPTS, ID_DEBUGGER_SYMBOLS, ID_DEBUGGER_DMALOG,
|
||||
ID_DEBUGGER_STACKTRACE, ID_DEBUGGER_STACKVIEW, ID_DEBUG_ENANCEMENT,
|
||||
ID_DEBUGGER_CPULOG, ID_DEBUGGER_STACKTRACE, ID_DEBUGGER_STACKVIEW, ID_DEBUG_ENANCEMENT,
|
||||
|
||||
// App logging
|
||||
ID_DEBUGGER_APPLOG_FLUSH, ID_DEBUGGER_TRACE_MD5, ID_DEBUGGER_TRACE_SETTINGS, ID_DEBUGGER_TRACE_UNKNOWN, ID_DEBUGGER_TRACE_APPINIT,
|
||||
|
|
|
@ -1304,6 +1304,21 @@ BEGIN
|
|||
PUSHBUTTON "Cancel",IDCANCEL,148,193,50,14
|
||||
END
|
||||
|
||||
IDD_Debugger_CPULog DIALOGEX 0, 0, 423, 267
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CAPTION "CPU Log"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
CONTROL "",IDC_CPU_LIST,"SysListView32",LVS_REPORT | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_NOSCROLL | WS_BORDER | WS_TABSTOP,7,23,173,237
|
||||
EDITTEXT IDC_STATEINFO_EDIT,203,29,206,226,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
|
||||
CONTROL "Enable CPU Logging",IDC_CHK_ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,10,78,8
|
||||
GROUPBOX "Registers",IDC_REGSTATES_GRP,197,19,218,241,0,WS_EX_TRANSPARENT
|
||||
EDITTEXT IDC_BUFFSIZE_EDIT,151,8,41,12,ES_AUTOHSCROLL
|
||||
LTEXT "Buffer size:",IDC_STATIC,110,10,37,8
|
||||
SCROLLBAR IDC_SCRL_BAR,181,23,11,237,SBS_VERT
|
||||
PUSHBUTTON "Export",IDC_BTN_EXPORT,360,7,56,13
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -1742,6 +1757,14 @@ BEGIN
|
|||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 207
|
||||
END
|
||||
|
||||
IDD_Debugger_CPULog, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 416
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 260
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
@ -1963,6 +1986,11 @@ BEGIN
|
|||
0
|
||||
END
|
||||
|
||||
IDD_Debugger_CPULog AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
@ -80,7 +80,8 @@
|
|||
#define IDD_Settings_Defaults 201
|
||||
#define IDD_Enhancement_Config 202
|
||||
#define IDD_Enhancement_Edit 203
|
||||
#define VERSION_BUILD 771
|
||||
#define IDD_Debugger_CPULog 204
|
||||
#define VERSION_BUILD 781
|
||||
#define IDC_MENU_ITEM_TEXT 1000
|
||||
#define IDC_CLOSE_BUTTON 1001
|
||||
#define IDC_LIST2 1003
|
||||
|
@ -526,8 +527,8 @@
|
|||
#define IDC_SP_STATIC 1358
|
||||
#define IDC_MEM_BTN 1359
|
||||
#define IDC_CAUSE_TIP 1361
|
||||
#define IDC_EDIT1 1362
|
||||
#define IDC_FCSR_EDIT 1362
|
||||
#define IDC_STATEINFO_EDIT 1362
|
||||
#define IDC_SP00_EDIT 1363
|
||||
#define IDC_SP04_EDIT 1364
|
||||
#define IDC_SP08_EDIT 1365
|
||||
|
@ -617,6 +618,11 @@
|
|||
#define IDC_OVERCLOCK 1451
|
||||
#define IDC_AUTOON 1452
|
||||
#define IDC_ENHANCEMENTNOTES 1453
|
||||
#define IDC_CPU_LIST 1454
|
||||
#define IDC_CHK_ENABLE 1455
|
||||
#define IDC_BUFFSIZE_EDIT 1457
|
||||
#define IDC_REGSTATES_GRP 1458
|
||||
#define IDC_BTN_EXPORT 1461
|
||||
#define ID_POPUP_SHOWINMEMORYVIEWER 40005
|
||||
#define ID_POPUPMENU_PLAYGAMEWITHDISK 40008
|
||||
#define ID_POPUPMENU_ADDSYMBOL 40013
|
||||
|
@ -654,9 +660,9 @@
|
|||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 200
|
||||
#define _APS_NEXT_RESOURCE_VALUE 206
|
||||
#define _APS_NEXT_COMMAND_VALUE 40043
|
||||
#define _APS_NEXT_CONTROL_VALUE 1454
|
||||
#define _APS_NEXT_CONTROL_VALUE 1462
|
||||
#define _APS_NEXT_SYMED_VALUE 102
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue