@@ -15,6 +15,76 @@
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"

std::size_t PPCDebugInterface::SetWatch(u32 address, const std::string& name)
{
return m_watches.SetWatch(address, name);
}

const Common::Debug::Watch& PPCDebugInterface::GetWatch(std::size_t index) const
{
return m_watches.GetWatch(index);
}

const std::vector<Common::Debug::Watch>& PPCDebugInterface::GetWatches() const
{
return m_watches.GetWatches();
}

void PPCDebugInterface::UnsetWatch(u32 address)
{
m_watches.UnsetWatch(address);
}

void PPCDebugInterface::UpdateWatch(std::size_t index, u32 address, const std::string& name)
{
return m_watches.UpdateWatch(index, address, name);
}

void PPCDebugInterface::UpdateWatchAddress(std::size_t index, u32 address)
{
return m_watches.UpdateWatchAddress(index, address);
}

void PPCDebugInterface::UpdateWatchName(std::size_t index, const std::string& name)
{
return m_watches.UpdateWatchName(index, name);
}

void PPCDebugInterface::EnableWatch(std::size_t index)
{
m_watches.EnableWatch(index);
}

void PPCDebugInterface::DisableWatch(std::size_t index)
{
m_watches.DisableWatch(index);
}

bool PPCDebugInterface::HasEnabledWatch(u32 address) const
{
return m_watches.HasEnabledWatch(address);
}

void PPCDebugInterface::RemoveWatch(std::size_t index)
{
return m_watches.RemoveWatch(index);
}

void PPCDebugInterface::LoadWatchesFromStrings(const std::vector<std::string>& watches)
{
m_watches.LoadFromStrings(watches);
}

std::vector<std::string> PPCDebugInterface::SaveWatchesToStrings() const
{
return m_watches.SaveToStrings();
}

void PPCDebugInterface::ClearWatches()
{
m_watches.Clear();
}

std::string PPCDebugInterface::Disassemble(unsigned int address)
{
// PowerPC::HostRead_U32 seemed to crash on shutdown
@@ -117,11 +187,6 @@ void PPCDebugInterface::ToggleBreakpoint(unsigned int address)
PowerPC::breakpoints.Add(address);
}

void PPCDebugInterface::AddWatch(unsigned int address)
{
PowerPC::watches.Add(address);
}

void PPCDebugInterface::ClearAllMemChecks()
{
PowerPC::memchecks.Clear();
@@ -204,3 +269,10 @@ void PPCDebugInterface::SetPC(unsigned int address)
void PPCDebugInterface::RunToBreakpoint()
{
}

void PPCDebugInterface::Clear()
{
ClearAllBreakpoints();
ClearAllMemChecks();
ClearWatches();
}
@@ -15,6 +15,22 @@ class PPCDebugInterface final : public DebugInterface
{
public:
PPCDebugInterface() {}
// Watches
std::size_t SetWatch(u32 address, const std::string& name = "") override;
const Common::Debug::Watch& GetWatch(std::size_t index) const override;
const std::vector<Common::Debug::Watch>& GetWatches() const override;
void UnsetWatch(u32 address) override;
void UpdateWatch(std::size_t index, u32 address, const std::string& name) override;
void UpdateWatchAddress(std::size_t index, u32 address) override;
void UpdateWatchName(std::size_t index, const std::string& name) override;
void EnableWatch(std::size_t index) override;
void DisableWatch(std::size_t index) override;
bool HasEnabledWatch(u32 address) const override;
void RemoveWatch(std::size_t index) override;
void LoadWatchesFromStrings(const std::vector<std::string>& watches) override;
std::vector<std::string> SaveWatchesToStrings() const override;
void ClearWatches() override;

std::string Disassemble(unsigned int address) override;
std::string GetRawMemoryString(int memory, unsigned int address) override;
int GetInstructionSize(int /*instruction*/) override { return 4; }
@@ -23,7 +39,6 @@ class PPCDebugInterface final : public DebugInterface
void SetBreakpoint(unsigned int address) override;
void ClearBreakpoint(unsigned int address) override;
void ClearAllBreakpoints() override;
void AddWatch(unsigned int address) override;
void ToggleBreakpoint(unsigned int address) override;
void ClearAllMemChecks() override;
bool IsMemCheck(unsigned int address, size_t size = 1) override;
@@ -45,4 +60,9 @@ class PPCDebugInterface final : public DebugInterface
void Patch(unsigned int address, unsigned int value) override;
int GetColor(unsigned int address) override;
std::string GetDescription(unsigned int address) override;

void Clear() override;

private:
Common::Debug::Watches m_watches;
};
@@ -17,6 +17,76 @@ namespace DSP
{
namespace LLE
{
std::size_t DSPDebugInterface::SetWatch(u32 address, const std::string& name)
{
return m_watches.SetWatch(address, name);
}

const Common::Debug::Watch& DSPDebugInterface::GetWatch(std::size_t index) const
{
return m_watches.GetWatch(index);
}

const std::vector<Common::Debug::Watch>& DSPDebugInterface::GetWatches() const
{
return m_watches.GetWatches();
}

void DSPDebugInterface::UnsetWatch(u32 address)
{
m_watches.UnsetWatch(address);
}

void DSPDebugInterface::UpdateWatch(std::size_t index, u32 address, const std::string& name)
{
return m_watches.UpdateWatch(index, address, name);
}

void DSPDebugInterface::UpdateWatchAddress(std::size_t index, u32 address)
{
return m_watches.UpdateWatchAddress(index, address);
}

void DSPDebugInterface::UpdateWatchName(std::size_t index, const std::string& name)
{
return m_watches.UpdateWatchName(index, name);
}

void DSPDebugInterface::EnableWatch(std::size_t index)
{
m_watches.EnableWatch(index);
}

void DSPDebugInterface::DisableWatch(std::size_t index)
{
m_watches.DisableWatch(index);
}

bool DSPDebugInterface::HasEnabledWatch(u32 address) const
{
return m_watches.HasEnabledWatch(address);
}

void DSPDebugInterface::RemoveWatch(std::size_t index)
{
return m_watches.RemoveWatch(index);
}

void DSPDebugInterface::LoadWatchesFromStrings(const std::vector<std::string>& watches)
{
m_watches.LoadFromStrings(watches);
}

std::vector<std::string> DSPDebugInterface::SaveWatchesToStrings() const
{
return m_watches.SaveToStrings();
}

void DSPDebugInterface::ClearWatches()
{
m_watches.Clear();
}

std::string DSPDebugInterface::Disassemble(unsigned int address)
{
// we'll treat addresses as line numbers.
@@ -191,5 +261,10 @@ void DSPDebugInterface::SetPC(unsigned int address)
void DSPDebugInterface::RunToBreakpoint()
{
}

void DSPDebugInterface::Clear()
{
ClearWatches();
}
} // namespace LLE
} // namespace DSP
@@ -18,6 +18,22 @@ class DSPDebugInterface final : public DebugInterface
{
public:
DSPDebugInterface() {}
// Watches
std::size_t SetWatch(u32 address, const std::string& name = "") override;
const Common::Debug::Watch& GetWatch(std::size_t index) const override;
const std::vector<Common::Debug::Watch>& GetWatches() const override;
void UnsetWatch(u32 address) override;
void UpdateWatch(std::size_t index, u32 address, const std::string& name) override;
void UpdateWatchAddress(std::size_t index, u32 address) override;
void UpdateWatchName(std::size_t index, const std::string& name) override;
void EnableWatch(std::size_t index) override;
void DisableWatch(std::size_t index) override;
bool HasEnabledWatch(u32 address) const override;
void RemoveWatch(std::size_t index) override;
void LoadWatchesFromStrings(const std::vector<std::string>& watches) override;
std::vector<std::string> SaveWatchesToStrings() const override;
void ClearWatches() override;

std::string Disassemble(unsigned int address) override;
std::string GetRawMemoryString(int memory, unsigned int address) override;
int GetInstructionSize(int instruction) override { return 1; }
@@ -40,6 +56,11 @@ class DSPDebugInterface final : public DebugInterface
void Patch(unsigned int address, unsigned int value) override;
int GetColor(unsigned int address) override;
std::string GetDescription(unsigned int address) override;

void Clear() override;

private:
Common::Debug::Watches m_watches;
};
} // namespace LLE
} // namespace DSP
@@ -243,83 +243,3 @@ bool TMemCheck::Action(DebugInterface* debug_interface, u32 value, u32 addr, boo
}
return false;
}

bool Watches::IsAddressWatch(u32 address) const
{
return std::any_of(m_watches.begin(), m_watches.end(),
[address](const auto& watch) { return watch.address == address; });
}

Watches::TWatchesStr Watches::GetStrings() const
{
TWatchesStr watch_strings;
for (const TWatch& watch : m_watches)
{
std::stringstream ss;
ss << std::hex << watch.address << " " << watch.name;
watch_strings.push_back(ss.str());
}

return watch_strings;
}

void Watches::AddFromStrings(const TWatchesStr& watch_strings)
{
for (const std::string& watch_string : watch_strings)
{
TWatch watch;
std::stringstream ss;
ss << std::hex << watch_string;
ss >> watch.address;
ss >> std::ws;
std::getline(ss, watch.name);
Add(watch);
}
}

void Watches::Add(const TWatch& watch)
{
if (IsAddressWatch(watch.address))
return;

m_watches.push_back(watch);
}

void Watches::Add(u32 address)
{
// Only add new addresses
if (IsAddressWatch(address))
return;

TWatch watch; // watch settings
watch.is_enabled = true;
watch.address = address;

m_watches.push_back(watch);
}

void Watches::Update(int count, u32 address)
{
m_watches.at(count).address = address;
}

void Watches::UpdateName(int count, const std::string name)
{
m_watches.at(count).name = name;
}

void Watches::Remove(u32 address)
{
const auto iter = std::find_if(m_watches.cbegin(), m_watches.cend(),
[address](const auto& watch) { return watch.address == address; });

if (iter == m_watches.cend())
return;

m_watches.erase(iter);
}

void Watches::Clear()
{
m_watches.clear();
}
@@ -38,13 +38,6 @@ struct TMemCheck
bool Action(DebugInterface* dbg_interface, u32 value, u32 addr, bool write, size_t size, u32 pc);
};

struct TWatch
{
std::string name;
u32 address = 0;
bool is_enabled = false;
};

// Code breakpoints.
class BreakPoints
{
@@ -97,30 +90,3 @@ class MemChecks
private:
TMemChecks m_mem_checks;
};

class Watches
{
public:
using TWatches = std::vector<TWatch>;
using TWatchesStr = std::vector<std::string>;

const TWatches& GetWatches() const { return m_watches; }
TWatchesStr GetStrings() const;
void AddFromStrings(const TWatchesStr& watch_strings);

bool IsAddressWatch(u32 address) const;

// Add watch
void Add(u32 address);
void Add(const TWatch& watch);

void Update(int count, u32 address);
void UpdateName(int count, const std::string name);

// Remove watch
void Remove(u32 address);
void Clear();

private:
TWatches m_watches;
};
@@ -34,7 +34,6 @@ static bool s_cpu_core_base_is_injected = false;
Interpreter* const s_interpreter = Interpreter::getInstance();
static CoreMode s_mode = CoreMode::Interpreter;

Watches watches;
BreakPoints breakpoints;
MemChecks memchecks;
PPCDebugInterface debug_interface;
@@ -135,7 +135,6 @@ static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x10

extern PowerPCState ppcState;

extern Watches watches;
extern BreakPoints breakpoints;
extern MemChecks memchecks;
extern PPCDebugInterface debug_interface;
@@ -117,7 +117,7 @@ void WatchWidget::Update()

m_table->clear();

int size = static_cast<int>(PowerPC::watches.GetWatches().size());
int size = static_cast<int>(PowerPC::debug_interface.GetWatches().size());

m_table->setRowCount(size + 1);

@@ -127,7 +127,7 @@ void WatchWidget::Update()

for (int i = 0; i < size; i++)
{
auto entry = PowerPC::watches.GetWatches().at(i);
auto entry = PowerPC::debug_interface.GetWatch(i);

auto* label = new QTableWidgetItem(QString::fromStdString(entry.name));
auto* address =
@@ -195,7 +195,7 @@ void WatchWidget::OnLoad()
{
IniFile ini;

Watches::TWatchesStr watches;
std::vector<std::string> watches;

if (!ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
false))
@@ -205,8 +205,8 @@ void WatchWidget::OnLoad()

if (ini.GetLines("Watches", &watches, false))
{
PowerPC::watches.Clear();
PowerPC::watches.AddFromStrings(watches);
PowerPC::debug_interface.ClearWatches();
PowerPC::debug_interface.LoadWatchesFromStrings(watches);
}

Update();
@@ -217,7 +217,7 @@ void WatchWidget::OnSave()
IniFile ini;
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
false);
ini.SetLines("Watches", PowerPC::watches.GetStrings());
ini.SetLines("Watches", PowerPC::debug_interface.SaveWatchesToStrings());
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini");
}

@@ -278,7 +278,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
if (item->text().isEmpty())
DeleteWatch(row);
else
PowerPC::watches.UpdateName(row, item->text().toStdString());
PowerPC::debug_interface.UpdateWatchName(row, item->text().toStdString());
break;
// Address
// Hexadecimal
@@ -293,9 +293,9 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
if (good)
{
if (column == 1)
PowerPC::watches.Update(row, value);
PowerPC::debug_interface.UpdateWatchAddress(row, value);
else
PowerPC::HostWrite_U32(value, PowerPC::watches.GetWatches().at(row).address);
PowerPC::HostWrite_U32(value, PowerPC::debug_interface.GetWatch(row).address);
}
else
{
@@ -311,18 +311,16 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)

void WatchWidget::DeleteWatch(int row)
{
PowerPC::watches.Remove(PowerPC::watches.GetWatches().at(row).address);
PowerPC::debug_interface.RemoveWatch(row);
Update();
}

void WatchWidget::AddWatchBreakpoint(int row)
{
emit RequestMemoryBreakpoint(PowerPC::watches.GetWatches().at(row).address);
emit RequestMemoryBreakpoint(PowerPC::debug_interface.GetWatch(row).address);
}

void WatchWidget::AddWatch(QString name, u32 addr)
{
PowerPC::watches.Add(addr);
PowerPC::watches.UpdateName(static_cast<int>(PowerPC::watches.GetWatches().size()) - 1,
name.toStdString());
PowerPC::debug_interface.SetWatch(addr, name.toStdString());
}
@@ -275,7 +275,7 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event)
#endif

case IDM_WATCHADDRESS:
debugger->AddWatch(selection);
debugger->SetWatch(selection);
if (watch_window)
watch_window->NotifyUpdate();
Refresh();
@@ -541,7 +541,7 @@ void CRegisterView::OnPopupMenu(wxCommandEvent& event)
switch (event.GetId())
{
case IDM_WATCHADDRESS:
PowerPC::watches.Add(m_selectedAddress);
PowerPC::debug_interface.SetWatch(m_selectedAddress);
if (watch_window)
watch_window->NotifyUpdate();
Refresh();
@@ -30,12 +30,12 @@ enum

static std::string GetWatchName(int count)
{
return PowerPC::watches.GetWatches().at(count - 1).name;
return PowerPC::debug_interface.GetWatch(count - 1).name;
}

static u32 GetWatchAddr(int count)
{
return PowerPC::watches.GetWatches().at(count - 1).address;
return PowerPC::debug_interface.GetWatch(count - 1).address;
}

static u32 GetWatchValue(int count)
@@ -45,24 +45,23 @@ static u32 GetWatchValue(int count)

static void AddWatchAddr(int count, u32 value)
{
PowerPC::watches.Add(value);
PowerPC::debug_interface.SetWatch(value);
}

static void UpdateWatchAddr(int count, u32 value)
{
PowerPC::watches.Update(count - 1, value);
PowerPC::debug_interface.UpdateWatchAddress(count - 1, value);
}

static void SetWatchName(int count, const std::string& value)
{
if ((count - 1) < (int)PowerPC::watches.GetWatches().size())
if (count - 1 < static_cast<int>(PowerPC::debug_interface.GetWatches().size()))
{
PowerPC::watches.UpdateName(count - 1, value);
PowerPC::debug_interface.UpdateWatchName(count - 1, value);
}
else
{
PowerPC::watches.Add(0);
PowerPC::watches.UpdateName(PowerPC::watches.GetWatches().size() - 1, value);
PowerPC::debug_interface.SetWatch(0, value);
}
}

@@ -94,7 +93,7 @@ static wxString GetValueByRowCol(int row, int col)
return wxEmptyString;
}
}
else if (row <= (int)PowerPC::watches.GetWatches().size())
else if (row <= static_cast<int>(PowerPC::debug_interface.GetWatches().size()))
{
if (Core::IsRunning())
{
@@ -145,10 +144,10 @@ void CWatchTable::SetValue(int row, int col, const wxString& strNewVal)
}
case 1:
{
if (row > (int)PowerPC::watches.GetWatches().size())
if (row > static_cast<int>(PowerPC::debug_interface.GetWatches().size()))
{
AddWatchAddr(row, newVal);
row = (int)PowerPC::watches.GetWatches().size();
row = static_cast<int>(PowerPC::debug_interface.GetWatches().size());
}
else
{
@@ -170,7 +169,7 @@ void CWatchTable::SetValue(int row, int col, const wxString& strNewVal)

void CWatchTable::UpdateWatch()
{
for (int i = 0; i < (int)PowerPC::watches.GetWatches().size(); ++i)
for (int i = 0; i < static_cast<int>(PowerPC::debug_interface.GetWatches().size()); ++i)
{
m_CachedWatchHasChanged[i] = (m_CachedWatch[i] != GetWatchValue(i + 1));
m_CachedWatch[i] = GetWatchValue(i + 1);
@@ -212,7 +211,8 @@ wxGridCellAttr* CWatchTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKin

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

if (row > (int)(PowerPC::watches.GetWatches().size() + 1) || !Core::IsRunning())
if (row > static_cast<int>(PowerPC::debug_interface.GetWatches().size() + 1) ||
!Core::IsRunning())
{
attr->SetReadOnly(true);
attr->SetBackgroundColour(*wxLIGHT_GREY);
@@ -259,14 +259,15 @@ void CWatchView::OnMouseDownR(wxGridEvent& event)
}

wxMenu menu;
if (row != 0 && row != (int)(PowerPC::watches.GetWatches().size() + 1))
if (row != 0 && row != static_cast<int>(PowerPC::debug_interface.GetWatches().size() + 1))
{
// i18n: This kind of "watch" is used for watching emulated memory.
// It's not related to timekeeping devices.
menu.Append(IDM_DELETEWATCH, _("&Delete watch"));
}

if (row != 0 && row != (int)(PowerPC::watches.GetWatches().size() + 1) && (col == 1 || col == 2))
if (row != 0 && row != static_cast<int>(PowerPC::debug_interface.GetWatches().size() + 1) &&
(col == 1 || col == 2))
{
menu.Append(IDM_ADDMEMCHECK, _("Add memory &breakpoint"));
menu.Append(IDM_VIEWMEMORY, _("View &memory"));
@@ -290,7 +291,7 @@ void CWatchView::OnPopupMenu(wxCommandEvent& event)
wxString strNewVal = GetValueByRowCol(m_selectedRow, 1);
if (TryParse("0x" + WxStrToStr(strNewVal), &m_selectedAddress))
{
PowerPC::watches.Remove(m_selectedAddress);
PowerPC::debug_interface.UnsetWatch(m_selectedAddress);
if (watch_window)
watch_window->NotifyUpdate();
Refresh();
@@ -122,7 +122,7 @@ void CWatchWindow::SaveAll()
IniFile ini;
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
false);
ini.SetLines("Watches", PowerPC::watches.GetStrings());
ini.SetLines("Watches", PowerPC::debug_interface.SaveWatchesToStrings());
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini");
}

@@ -134,7 +134,7 @@ void CWatchWindow::Event_LoadAll(wxCommandEvent& WXUNUSED(event))
void CWatchWindow::LoadAll()
{
IniFile ini;
Watches::TWatchesStr watches;
std::vector<std::string> watches;

if (!ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
false))
@@ -144,8 +144,8 @@ void CWatchWindow::LoadAll()

if (ini.GetLines("Watches", &watches, false))
{
PowerPC::watches.Clear();
PowerPC::watches.AddFromStrings(watches);
PowerPC::debug_interface.ClearWatches();
PowerPC::debug_interface.LoadWatchesFromStrings(watches);
}

NotifyUpdate();
@@ -884,9 +884,7 @@ void CFrame::DoStop()

if (m_use_debugger && m_code_window)
{
PowerPC::watches.Clear();
PowerPC::breakpoints.Clear();
PowerPC::memchecks.Clear();
PowerPC::debug_interface.Clear();
if (m_code_window->HasPanel<CBreakPointWindow>())
m_code_window->GetPanel<CBreakPointWindow>()->NotifyUpdate();
g_symbolDB.Clear();