[Debugger] Add CPU Log, break and show log/commands window on CPU errors

This commit is contained in:
shygoo 2019-01-14 03:18:43 -06:00
parent 3eaf7334dd
commit 4d322191c2
22 changed files with 929 additions and 65 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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);
}

View File

@ -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;

View File

@ -253,6 +253,8 @@ enum SettingID
Debugger_ReadBPExists,
Debugger_WaitingForStep,
Debugger_AutoRefreshMemoryView,
Debugger_CPULoggingEnabled,
Debugger_CPULogBufferSize,
//Trace
Debugger_TraceMD5,

View File

@ -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" />

View File

@ -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">

View File

@ -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));

View File

@ -68,6 +68,7 @@ enum UISettingID
DebuggerUI_MemoryDumpPos,
DebuggerUI_MemorySearchPos,
DebuggerUI_DMALogPos,
DebuggerUI_CPULogPos,
DebuggerUI_ScriptsPos,
DebuggerUI_StackPos,
DebuggerUI_StackTracePos,

View File

@ -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);
}

View File

@ -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);
};

View File

@ -0,0 +1,419 @@
#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)
{
}
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(nItem);
return FALSE;
}
LRESULT CDebugCPULogView::OnListDblClicked(NMHDR* pNMHDR)
{
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
int nItem = pIA->iItem;
CPUState* state = m_CPULogCopy->GetEntry(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;
}
::SetScrollPos(hScrollbar, SB_CTL, newPos, 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();
m_Scrollbar.SetScrollPos(scrollPos + nScroll);
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_Scrollbar.SetScrollPos(scrollRangeMax, 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);
}

View File

@ -0,0 +1,77 @@
#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;
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()
};

View File

@ -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()

View File

@ -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"

View File

@ -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;

View File

@ -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);
};

View File

@ -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...");

View File

@ -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,

View File

@ -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
/////////////////////////////////////////////////////////////////////////////
//

View File

@ -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