Better support for Debugger.

Add ability to set breakpoints with mouse.


Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2021-05-16 18:48:18 +01:00
parent 329c19c8d9
commit 8d21b68af0
5 changed files with 149 additions and 30 deletions

View file

@ -124,7 +124,7 @@ namespace sa2
const ImVec2 uv0(0, 1);
const ImVec2 uv1(1, 0);
const float menuBarHeight = mySettings.drawMenuBar();
const float menuBarHeight = mySettings.drawMenuBar(this);
if (mySettings.windowed)
{

View file

@ -176,7 +176,7 @@ namespace
{
ImGui::EndCombo();
}
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, false);
ImGui::PopItemFlag();
}
}
@ -202,7 +202,7 @@ namespace sa2
if (ImGui::Checkbox("Debugger", &myShowDebugger) && myShowDebugger)
{
DebugBegin();
frame->ChangeMode(MODE_DEBUG);
}
ImGui::SameLine(); HelpMarker("Show Apple CPU.");
@ -694,7 +694,7 @@ namespace sa2
}
}
float ImGuiSettings::drawMenuBar()
float ImGuiSettings::drawMenuBar(SDLFrame* frame)
{
float menuBarHeight;
@ -707,7 +707,7 @@ namespace sa2
ImGui::MenuItem("Memory", nullptr, &myShowMemory);
if (ImGui::MenuItem("Debugger", nullptr, &myShowDebugger) && myShowDebugger)
{
DebugBegin();
frame->ChangeMode(MODE_DEBUG);
}
ImGui::EndMenu();
}
@ -756,10 +756,12 @@ namespace sa2
void ImGuiSettings::drawDisassemblyTable()
{
const ImGuiTableFlags flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_ScrollY;
if (ImGui::BeginTable("Disassembly", 8, flags))
if (ImGui::BeginTable("Disassembly", 9, flags))
{
ImGui::PushStyleCompact();
// weigths proportional to column width (including header)
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
ImGui::TableSetupColumn("", 0, 1);
ImGui::TableSetupColumn("Address", 0, 7);
ImGui::TableSetupColumn("Opcode", 0, 8);
ImGui::TableSetupColumn("Symbol", 0, 10);
@ -785,20 +787,60 @@ namespace sa2
IM_ASSERT(row == clipper.DisplayStart && "Clipper position mismatch");
for (; row < clipper.DisplayEnd; ++row)
{
ImGui::PushID(nAddress);
DisasmLine_t line;
const char* pSymbol = FindSymbolFromAddress(nAddress);
const int bDisasmFormatFlags = GetDisassemblyLine(nAddress, line);
ImGui::TableNextRow();
bool breakpointActive;
bool breakpointEnabled;
GetBreakpointInfo(nAddress, breakpointActive, breakpointEnabled);
float red = 0.0;
int state = 0;
if (breakpointEnabled)
{
red = 0.5;
state = 1;
}
else if (breakpointActive)
{
red = 0.25;
state = -1;
}
ImGui::TableNextColumn();
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, g_nAppMode != MODE_DEBUG);
if (ImGui::CheckBoxTristate("", &state))
{
if (!breakpointActive && state == 1)
{
std::string command = std::string("bpx ") + line.sAddress;
debuggerCommand(command.c_str());
}
else
{
changeBreakpoint(nAddress, state == 1);
}
}
ImGui::PopItemFlag();
if (nAddress == regs.pc)
{
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(0, 0, 1, 1));
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(red, 0, 1, 1));
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, currentBgColor);
}
else if (nAddress == g_nDisasmCurAddress)
{
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(0, 0, 0.5, 1));
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(red, 0, 0.5, 1));
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, currentBgColor);
}
else if (breakpointActive || breakpointEnabled)
{
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(red, 0, 0, 1));
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, currentBgColor);
}
@ -842,8 +884,10 @@ namespace sa2
}
nAddress += line.nOpbyte;
ImGui::PopID();
}
}
ImGui::PopStyleCompact();
ImGui::EndTable();
}
}
@ -926,26 +970,19 @@ namespace sa2
if (ImGui::Button("Step"))
{
frame->ChangeMode(MODE_STEPPING);
frame->Execute(myStepCycles);
frame->ChangeMode(MODE_DEBUG);
frame->Execute(0);
}
ImGui::SameLine();
ImGui::PushItemWidth(150);
ImGui::DragInt("cycles", &myStepCycles, 0.2f, 0, 256, "%d");
ImGui::PopItemWidth();
if ((ImGui::SameLine(), ImGui::Button("Run")))
{
frame->ChangeMode(MODE_RUNNING);
}
if ((ImGui::SameLine(), ImGui::Button("Pause")))
{
frame->ChangeMode(MODE_PAUSED);
}
if ((ImGui::SameLine(), ImGui::Button("Debug")))
{
frame->ChangeMode(MODE_DEBUG);
}
if ((ImGui::SameLine(), ImGui::Button("Continue")))
{
frame->ChangeMode(MODE_RUNNING);
}
ImGui::SameLine();
ImGui::Text("%016llu - %04X", g_nCumulativeCycles, regs.pc);
@ -977,19 +1014,27 @@ namespace sa2
ImGui::EndTabBar();
}
ImGui::EndChild();
if (ImGui::InputText("Prompt", myInputBuffer, IM_ARRAYSIZE(myInputBuffer), ImGuiInputTextFlags_EnterReturnsTrue))
if (g_nAppMode == MODE_DEBUG)
{
for (const char *ch = myInputBuffer; *ch; ++ch)
if (ImGui::InputText("Prompt", myInputBuffer, IM_ARRAYSIZE(myInputBuffer), ImGuiInputTextFlags_EnterReturnsTrue))
{
DebuggerInputConsoleChar(*ch);
debuggerCommand(myInputBuffer);
myInputBuffer[0] = 0;
ImGui::SetKeyboardFocusHere(-1);
}
DebuggerProcessKey(VK_RETURN);
myScrollConsole = true;
myInputBuffer[0] = 0;
ImGui::SetKeyboardFocusHere(-1);
}
}
ImGui::End();
}
void ImGuiSettings::debuggerCommand(const char * s)
{
for (; *s; ++s)
{
DebuggerInputConsoleChar(*s);
}
DebuggerProcessKey(VK_RETURN);
myScrollConsole = true;
}
}

View file

@ -14,7 +14,7 @@ namespace sa2
{
public:
void show(SDLFrame* frame);
float drawMenuBar();
float drawMenuBar(SDLFrame* frame);
bool windowed = false;
@ -29,7 +29,6 @@ namespace sa2
bool myScrollConsole = true;
char myInputBuffer[CONSOLE_WIDTH] = "";
int myStepCycles = 0;
int mySpeakerVolume;
int myMockingboardVolume;
@ -45,6 +44,8 @@ namespace sa2
void drawDisassemblyTable();
void drawConsole();
void debuggerCommand(const char * s);
};
}

View file

@ -3,10 +3,15 @@
#include "Registry.h"
#include "Harddisk.h"
#include "Core.h"
#include "Debugger/Debug.h"
#include "Tfe/tfe.h"
#include "frontends/sdl/imgui/settingshelper.h"
#include "frontends/sdl/imgui/gles.h"
#include "imgui_internal.h"
namespace
{
const std::map<SS_CARDTYPE, std::string> cards =
@ -196,4 +201,62 @@ namespace sa2
REGSAVE(TEXT(REGVALUE_UTHERNET_ACTIVE), tfe_enabled);
}
void changeBreakpoint(const DWORD nAddress, const bool enableAndSet)
{
// see _BWZ_RemoveOne
for (Breakpoint_t & bp : g_aBreakpoints)
{
if (bp.bSet && bp.nLength && (nAddress >= bp.nAddress) && (nAddress < bp.nAddress + bp.nLength))
{
bp.bSet = enableAndSet;
bp.bEnabled = enableAndSet;
if (!enableAndSet)
{
bp.nLength = 0;
--g_nBreakpoints;
}
}
}
}
}
namespace ImGui
{
bool CheckBoxTristate(const char* label, int* v_tristate)
{
bool ret;
if (*v_tristate == -1)
{
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
bool b = false;
ret = ImGui::Checkbox(label, &b);
if (ret)
*v_tristate = 1;
ImGui::PopItemFlag();
}
else
{
bool b = (*v_tristate != 0);
ret = ImGui::Checkbox(label, &b);
if (ret)
*v_tristate = (int)b;
}
return ret;
}
void PushStyleCompact()
{
ImGuiStyle& style = ImGui::GetStyle();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
}
void PopStyleCompact()
{
ImGui::PopStyleVar(2);
}
}

View file

@ -29,4 +29,14 @@ namespace sa2
void setVideoStyle(Video & video, const VideoStyle_e style, const bool enabled);
void saveTFEEnabled(const int enabled);
void changeBreakpoint(const DWORD nAddress, const bool enableAndSet);
}
namespace ImGui
{
bool CheckBoxTristate(const char* label, int* v_tristate);
void PushStyleCompact();
void PopStyleCompact();
}