Skip to content

Commit

Permalink
Added a RAM Watch window to the debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
skidau committed Oct 18, 2014
1 parent d572293 commit 9a650d2
Show file tree
Hide file tree
Showing 15 changed files with 395 additions and 3 deletions.
9 changes: 7 additions & 2 deletions Source/Core/Core/HW/Memmap.cpp
Expand Up @@ -292,17 +292,22 @@ void ReadBigEData(u8 *data, const u32 em_address, const u32 size)
memcpy(data, src, size);
}

std::string GetString(u32 em_address)
std::string GetString(u32 em_address, u32 max_len)
{
std::string str;
char c;

while ((c = Read_U8(em_address)) != '\0')
while ((c = ReadUnchecked_U8(em_address)) != '\0' && (max_len == 0 || max_len > str.length()))
{
str += c;
em_address++;
}

if (str.length() == max_len)
{
str += '\0';
}

return str;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/HW/Memmap.h
Expand Up @@ -118,7 +118,7 @@ void Write_U64_Swap(const u64 _Data, const u32 _Address);
// Useful helper functions, used by ARM JIT
void Write_F64(const double _Data, const u32 _Address);

std::string GetString(u32 em_address);
std::string GetString(u32 em_address, u32 max_len = 0);

void WriteBigEData(const u8 *_pData, const u32 _Address, const size_t size);
void ReadBigEData(u8 *_pDest, const u32 _Address, const u32 size);
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinWX/CMakeLists.txt
Expand Up @@ -42,6 +42,8 @@ set(GUI_SRCS
Debugger/MemoryWindow.cpp
Debugger/RegisterView.cpp
Debugger/RegisterWindow.cpp
Debugger/WatchView.cpp
Debugger/WatchWindow.cpp
FifoPlayerDlg.cpp
Frame.cpp
FrameAui.cpp
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinWX/Debugger/CodeWindow.cpp
Expand Up @@ -52,6 +52,7 @@
#include "DolphinWX/Debugger/DebuggerUIUtil.h"
#include "DolphinWX/Debugger/JitWindow.h"
#include "DolphinWX/Debugger/RegisterWindow.h"
#include "DolphinWX/Debugger/WatchWindow.h"

extern "C" // Bitmaps
{
Expand Down Expand Up @@ -93,6 +94,7 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter
: wxPanel(parent, id, position, size, style, name)
, Parent(parent)
, m_RegisterWindow(nullptr)
, m_WatchWindow(nullptr)
, m_BreakpointWindow(nullptr)
, m_MemoryWindow(nullptr)
, m_JitWindow(nullptr)
Expand Down Expand Up @@ -152,6 +154,7 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event)
Update();
if (codeview) codeview->Center(PC);
if (m_RegisterWindow) m_RegisterWindow->NotifyUpdate();
if (m_WatchWindow) m_WatchWindow->NotifyUpdate();
break;

case IDM_UPDATEBREAKPOINTS:
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinWX/Debugger/CodeWindow.h
Expand Up @@ -19,6 +19,7 @@

class CFrame;
class CRegisterWindow;
class CWatchWindow;
class CBreakPointWindow;
class CMemoryWindow;
class CJitWindow;
Expand Down Expand Up @@ -80,6 +81,7 @@ class CCodeWindow

void ToggleCodeWindow(bool bShow);
void ToggleRegisterWindow(bool bShow);
void ToggleWatchWindow(bool bShow);
void ToggleBreakPointWindow(bool bShow);
void ToggleMemoryWindow(bool bShow);
void ToggleJitWindow(bool bShow);
Expand All @@ -96,6 +98,7 @@ class CCodeWindow

// Sub dialogs
CRegisterWindow* m_RegisterWindow;
CWatchWindow* m_WatchWindow;
CBreakPointWindow* m_BreakpointWindow;
CMemoryWindow* m_MemoryWindow;
CJitWindow* m_JitWindow;
Expand Down
21 changes: 21 additions & 0 deletions Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
Expand Up @@ -51,6 +51,7 @@
#include "DolphinWX/Debugger/JitWindow.h"
#include "DolphinWX/Debugger/MemoryWindow.h"
#include "DolphinWX/Debugger/RegisterWindow.h"
#include "DolphinWX/Debugger/WatchWindow.h"


// Save and load settings
Expand Down Expand Up @@ -421,6 +422,8 @@ void CCodeWindow::OpenPages()
Parent->ToggleLogConfigWindow(true);
if (bShowOnStart[IDM_REGISTERWINDOW - IDM_LOGWINDOW])
ToggleRegisterWindow(true);
if (bShowOnStart[IDM_WATCHWINDOW - IDM_LOGWINDOW])
ToggleWatchWindow(true);
if (bShowOnStart[IDM_BREAKPOINTWINDOW - IDM_LOGWINDOW])
ToggleBreakPointWindow(true);
if (bShowOnStart[IDM_MEMORYWINDOW - IDM_LOGWINDOW])
Expand Down Expand Up @@ -461,6 +464,24 @@ void CCodeWindow::ToggleRegisterWindow(bool bShow)
}
}

void CCodeWindow::ToggleWatchWindow(bool bShow)
{
GetMenuBar()->FindItem(IDM_WATCHWINDOW)->Check(bShow);
if (bShow)
{
if (!m_WatchWindow)
m_WatchWindow = new CWatchWindow(Parent, IDM_WATCHWINDOW);
Parent->DoAddPage(m_WatchWindow,
iNbAffiliation[IDM_WATCHWINDOW - IDM_LOGWINDOW],
Parent->bFloatWindow[IDM_WATCHWINDOW - IDM_LOGWINDOW]);
}
else // Close
{
Parent->DoRemovePage(m_WatchWindow, false);
m_WatchWindow = nullptr;
}
}

void CCodeWindow::ToggleBreakPointWindow(bool bShow)
{
GetMenuBar()->FindItem(IDM_BREAKPOINTWINDOW)->Check(bShow);
Expand Down
194 changes: 194 additions & 0 deletions Source/Core/DolphinWX/Debugger/WatchView.cpp
@@ -0,0 +1,194 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#include <wx/chartype.h>
#include <wx/colour.h>
#include <wx/defs.h>
#include <wx/grid.h>
#include <wx/string.h>
#include <wx/windowid.h>

#include "Common/GekkoDisassembler.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"
#include "DolphinWX/WxUtils.h"
#include "DolphinWX/Debugger/DebuggerUIUtil.h"
#include "DolphinWX/Debugger/WatchView.h"

class wxWindow;

const char *watch_name[1024];
u32 watch_addr[1024];

static const char* GetWatchName(int count)
{
return watch_name[count - 1];
}

static u32 GetWatchAddr(int count)
{
return watch_addr[count - 1];
}

static u32 GetWatchValue(int count)
{
return Memory::ReadUnchecked_U32(watch_addr[count - 1]);
}

static void SetWatchName(int count, const char* value)
{
watch_name[count - 1] = value;
}

static void SetWatchAddr(int count, u32 value)
{
watch_addr[count - 1] = value;
}

static void SetWatchValue(int count, u32 value)
{
Memory::WriteUnchecked_U32(value, GetWatchAddr(count));
}

wxString CWatchTable::GetValue(int row, int col)
{
if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
if (row == 0)
{
// Column Labels
switch (col)
{
case 0: return wxString::Format("Label");
case 1: return wxString::Format("Addr");
case 2: return wxString::Format("Hex");
case 3: return wxString::Format("Dec");
case 4: return wxString::Format("Str");
default: return wxEmptyString;
}
}
else if (row <= num_watches)
{
switch (col)
{
case 0: return wxString::Format("%s", GetWatchName(row));
case 1: return wxString::Format("%08x", GetWatchAddr(row));
case 2: return wxString::Format("%08x", GetWatchValue(row));
case 3: return wxString::Format("%lu", GetWatchValue(row));
case 4:
{
u32 addr = GetWatchAddr(row);
if (Memory::IsRAMAddress(addr))
return wxString::Format("%s", Memory::GetString(addr, 32));
else
return wxEmptyString;
}
default: return wxEmptyString;
}
}
}
return wxEmptyString;
}

void CWatchTable::SetValue(int row, int col, const wxString& strNewVal)
{
u32 newVal = 0;
if (col == 0 || TryParse("0x" + WxStrToStr(strNewVal), &newVal))
{
if (row > 0)
{
if (row > num_watches)
{
num_watches++;
row = num_watches;
}
switch (col)
{
case 0: SetWatchName(row, strNewVal); break;
case 1: SetWatchAddr(row, newVal); break;
case 2: SetWatchValue(row, newVal); break;
default: break;
}
}
}
}

void CWatchTable::UpdateWatch()
{
for (int i = 0; i < num_watches; ++i)
{
m_CachedWatchHasChanged[i] = (m_CachedWatch[i] != GetWatchValue(i));
m_CachedWatch[i] = GetWatchValue(i);
}
}

wxGridCellAttr *CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKind)
{
wxGridCellAttr *attr = new wxGridCellAttr();

attr->SetBackgroundColour(*wxWHITE);
attr->SetFont(DebuggerFont);

switch (col)
{
case 1:
attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER);
break;
case 3:
case 4:
attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER);
break;
default:
attr->SetAlignment(wxALIGN_LEFT, wxALIGN_CENTER);
break;
}

if (row == 0)
{
attr->SetReadOnly(true);
attr->SetBackgroundColour(*wxBLACK);
attr->SetTextColour(*wxWHITE);
}
else
{
bool red = false;
switch (col)
{
case 1: red = m_CachedWatchHasChanged[row]; break;
}

attr->SetTextColour(red ? *wxRED : *wxBLACK);

if (row > (num_watches + 1))
{
attr->SetReadOnly(true);
attr->SetBackgroundColour(*wxLIGHT_GREY);
}
}
attr->IncRef();
return attr;
}

CWatchView::CWatchView(wxWindow *parent, wxWindowID id)
: wxGrid(parent, id)
{
SetTable(new CWatchTable(), true);
SetRowLabelSize(0);
SetColLabelSize(0);
DisableDragRowSize();

if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
AutoSizeColumns();
}
}

void CWatchView::Update()
{
if (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
ForceRefresh();
((CWatchTable *)GetTable())->UpdateWatch();
}
}
52 changes: 52 additions & 0 deletions Source/Core/DolphinWX/Debugger/WatchView.h
@@ -0,0 +1,52 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.

#pragma once

#include <string>
#include <wx/defs.h>
#include <wx/grid.h>
#include <wx/string.h>
#include <wx/windowid.h>

#include "Common/CommonTypes.h"

class wxWindow;

class CWatchTable : public wxGridTableBase
{
enum
{
NUM_SPECIALS = 1,
MAX_SPECIALS = 256,
};

public:
CWatchTable()
{
memset(m_CachedWatch, 0, sizeof(m_CachedWatch));
memset(m_CachedWatchHasChanged, 0, sizeof(m_CachedWatchHasChanged));
}

int GetNumberCols() override { return 5; }
int GetNumberRows() override { return MAX_SPECIALS; }
wxString GetValue(int row, int col) override;
void SetValue(int row, int col, const wxString &) override;
wxGridCellAttr *GetAttr(int, int, wxGridCellAttr::wxAttrKind) override;
void UpdateWatch();

private:
u32 m_CachedWatch[MAX_SPECIALS];
bool m_CachedWatchHasChanged[MAX_SPECIALS];
int num_watches = 0;

DECLARE_NO_COPY_CLASS(CWatchTable);
};

class CWatchView : public wxGrid
{
public:
CWatchView(wxWindow* parent, wxWindowID id);
void Update() override;
};

0 comments on commit 9a650d2

Please sign in to comment.