Merge pull request #19609 from hrydgard/imgui-debugger
Some checks are pending
Build / build-windows (ARM64) (push) Waiting to run
Build / build-windows (x64) (push) Waiting to run
Build / build-uwp (push) Waiting to run
Build / test-windows (push) Blocked by required conditions
Build / build (./b.sh --headless --unittest --fat --no-png --no-sdl2, clang, clang++, test, macos, macos-latest) (push) Waiting to run
Build / build (./b.sh --headless --unittest, clang, clang++, test, clang-normal, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --headless --unittest, gcc, g++, gcc-normal, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --ios, clang, clang++, ios, ios, macos-latest) (push) Waiting to run
Build / build (./b.sh --libretro_android ppsspp_libretro, clang, clang++, android, android-libretro, ubuntu-latest) (push) Waiting to run
Build / build (./b.sh --qt, gcc, g++, qt, qt, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=arm64-v8a OPENXR=1, clang, clang++, android, android-vr, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=arm64-v8a UNITTEST=1 HEADLESS=1, clang, clang++, android, android-arm64, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=armeabi-v7a UNITTEST=1 HEADLESS=1, clang, clang++, android, android-arm32, ubuntu-latest) (push) Waiting to run
Build / build (cd android && ./ab.sh -j2 APP_ABI=x86_64 UNITTEST=1 HEADLESS=1, clang, clang++, android, android-x86_64, ubuntu-latest) (push) Waiting to run
Build / build (make -C libretro -f Makefile -j2, clang, clang++, libretro, clang-libretro, ubuntu-latest) (push) Waiting to run
Build / build (make -C libretro -f Makefile -j2, gcc, g++, libretro, gcc-libretro, ubuntu-latest) (push) Waiting to run
Build / test (macos-latest) (push) Blocked by required conditions
Build / test (ubuntu-latest) (push) Blocked by required conditions
Build / build_test_headless_alpine (push) Waiting to run
Generate Docker Layer / build (push) Waiting to run

ImGui debugger
This commit is contained in:
Henrik Rydgård 2024-11-07 12:53:47 +01:00 committed by GitHub
commit ace7cae79a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 1787 additions and 53 deletions

View File

@ -175,7 +175,7 @@ option(USE_LIBNX "Set to ON to build for Switch(libnx)" OFF)
option(USE_FFMPEG "Build with FFMPEG support" ON)
option(USE_DISCORD "Build with Discord support" ON)
option(USE_MINIUPNPC "Build with miniUPnPc support" ON)
option(USE_ARMIPS "Build with armips support in API/debugger" ON)
option(USE_ARMIPS "Build with armips support in API/debuggerdebugger" ON)
option(USE_SYSTEM_SNAPPY "Dynamically link against system snappy" ${USE_SYSTEM_SNAPPY})
option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG})
option(USE_SYSTEM_LIBZIP "Dynamically link against system libzip" ${USE_SYSTEM_LIBZIP})
@ -1519,6 +1519,10 @@ endif()
list(APPEND NativeAppSource
android/jni/TestRunner.cpp
UI/ImDebugger/ImDebugger.cpp
UI/ImDebugger/ImDebugger.h
UI/ImDebugger/ImDisasmView.cpp
UI/ImDebugger/ImDisasmView.h
UI/DiscordIntegration.cpp
UI/NativeApp.cpp
UI/BackgroundAudio.h

View File

@ -28,43 +28,48 @@ class DebugInterface {
public:
virtual int getInstructionSize(int instruction) {return 1;}
virtual bool isAlive() {return true;}
virtual bool isBreakpoint(unsigned int address) {return false;}
virtual void setBreakpoint(unsigned int address){}
virtual void clearBreakpoint(unsigned int address){}
virtual void clearAllBreakpoints() {}
virtual void toggleBreakpoint(unsigned int address){}
virtual unsigned int readMemory(unsigned int address){return 0;}
virtual unsigned int getPC() {return 0;}
virtual bool isAlive() = 0;
virtual bool isBreakpoint(unsigned int address) = 0;
virtual void setBreakpoint(unsigned int address) = 0;
virtual void clearBreakpoint(unsigned int address) = 0;
virtual void clearAllBreakpoints() = 0;
virtual void toggleBreakpoint(unsigned int address) = 0;
virtual unsigned int readMemory(unsigned int address) {return 0;}
virtual unsigned int getPC() = 0;
virtual void setPC(unsigned int address) {}
virtual void step() {}
virtual void runToBreakpoint() {}
virtual int getColor(unsigned int address){return 0xFFFFFFFF;}
virtual int getColor(unsigned int address, bool darkMode) const {return darkMode ? 0xFF101010 : 0xFFFFFFFF;}
virtual std::string getDescription(unsigned int address) {return "";}
virtual bool initExpression(const char* exp, PostfixExpression& dest) { return false; };
virtual bool parseExpression(PostfixExpression& exp, u32& dest) { return false; };
virtual u32 GetHi() { return 0; };
virtual u32 GetLo() { return 0; };
virtual u32 GetHi() = 0;
virtual u32 GetLo() = 0;
virtual u32 GetLLBit() = 0;
virtual void SetHi(u32 val) { };
virtual void SetLo(u32 val) { };
virtual const char *GetName() = 0;
virtual u32 GetGPR32Value(int reg) {return 0;}
virtual void SetGPR32Value(int reg) {}
virtual u32 GetGPR32Value(int reg) = 0;
virtual void SetGPR32Value(int reg, u32 value) = 0;
virtual float GetFPR32Value(int reg) { return -1.0f; }
virtual float GetVPR32Value(int reg) { return -1.0f; }
virtual u32 GetPC() = 0;
virtual void SetPC(u32 _pc) = 0;
virtual u32 GetLR() {return GetPC();}
virtual void DisAsm(u32 pc, char *out, size_t outSize) {
snprintf(out, outSize, "[%08x] UNKNOWN", pc);
}
virtual u32 GetLR() = 0;
virtual void DisAsm(u32 pc, char *out, size_t outSize) = 0;
// More stuff for debugger
virtual int GetNumCategories() {return 0;}
virtual int GetNumRegsInCategory(int cat) {return 0;}
virtual const char *GetCategoryName(int cat) {return 0;}
virtual std::string GetRegName(int cat, int index) { return ""; }
virtual int GetNumCategories() = 0;
virtual int GetNumRegsInCategory(int cat) = 0;
virtual const char *GetCategoryName(int cat) = 0;
virtual std::string GetRegName(int cat, int index) = 0;
virtual void PrintRegValue(int cat, int index, char *out, size_t outSize) {
snprintf(out, outSize, "%08X", GetGPR32Value(index));
}
virtual u32 GetRegValue(int cat, int index) {return 0;}
virtual u32 GetRegValue(int cat, int index) = 0;
virtual void SetRegValue(int cat, int index, u32 value) {}
};

View File

@ -162,6 +162,7 @@ private:
// This is indexed by the end address of the module.
std::map<u32, const ModuleEntry> activeModuleEnds;
// Module ID, index
typedef std::pair<int, u32> SymbolKey;
// These are indexed by the module id and relative address in the module.

View File

@ -100,7 +100,7 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
} else {
json.writeNull("macroEncoding");
}
int c = currentDebugMIPS->getColor(addr) & 0x00FFFFFF;
int c = currentDebugMIPS->getColor(addr, false) & 0x00FFFFFF;
json.writeString("backgroundColor", StringFromFormat("#%02x%02x%02x", c & 0xFF, (c >> 8) & 0xFF, c >> 16));
json.writeString("name", l.name);
json.writeString("params", l.params);

View File

@ -651,6 +651,8 @@ void __DisplayFlip(int cyclesLate) {
if (fbReallyDirty) {
DisplayFireActualFlip();
}
} else {
WARN_LOG(Log::sceDisplay, "Core_NextFrame returned false");
}
}

View File

@ -243,15 +243,21 @@ void MIPSDebugInterface::toggleBreakpoint(unsigned int address)
}
int MIPSDebugInterface::getColor(unsigned int address)
{
int colors[6] = {0xe0FFFF,0xFFe0e0,0xe8e8FF,0xFFe0FF,0xe0FFe0,0xFFFFe0};
int n=g_symbolMap->GetFunctionNum(address);
if (n==-1) return 0xFFFFFF;
return colors[n%6];
int MIPSDebugInterface::getColor(unsigned int address, bool darkMode) const {
int colors[6] = { 0xe0FFFF, 0xFFe0e0, 0xe8e8FF, 0xFFe0FF, 0xe0FFe0, 0xFFFFe0 };
int colorsDark[6] = { ~0xe0FFFF, ~0xFFe0e0, ~0xe8e8FF, ~0xFFe0FF, ~0xe0FFe0, ~0xFFFFe0 };
int n = g_symbolMap->GetFunctionNum(address);
if (n == -1) {
return DebugInterface::getColor(address, darkMode);
} else if (darkMode) {
return colorsDark[n % ARRAY_SIZE(colorsDark)];
} else {
return colors[n % ARRAY_SIZE(colors)];
}
}
std::string MIPSDebugInterface::getDescription(unsigned int address)
{
std::string MIPSDebugInterface::getDescription(unsigned int address) {
return g_symbolMap->GetDescription(address);
}

View File

@ -40,7 +40,7 @@ public:
void setPC(unsigned int address) override { cpu->pc = address; }
void step() override {}
void runToBreakpoint() override;
int getColor(unsigned int address) override;
int getColor(unsigned int address, bool darkMode) const override;
std::string getDescription(unsigned int address) override;
bool initExpression(const char* exp, PostfixExpression& dest) override;
bool parseExpression(PostfixExpression& exp, u32& dest) override;
@ -48,6 +48,9 @@ public:
//overridden functions
const char *GetName() override;
u32 GetGPR32Value(int reg) override { return cpu->r[reg]; }
float GetFPR32Value(int reg) override { return cpu->f[reg]; }
void SetGPR32Value(int reg, u32 value) override { cpu->r[reg] = value; }
u32 GetPC() override { return cpu->pc; }
u32 GetLR() override { return cpu->r[MIPS_REG_RA]; }
void DisAsm(u32 pc, char *out, size_t outSize) override;
@ -76,6 +79,10 @@ public:
return cpu->hi;
}
u32 GetLLBit() override {
return cpu->llBit;
}
u32 GetLo() override {
return cpu->lo;
}

View File

@ -73,8 +73,9 @@ using namespace std::placeholders;
#include "Core/Debugger/SymbolMap.h"
#include "Core/RetroAchievements.h"
#include "Core/SaveState.h"
#include "UI/ImDebugger/ImDebugger.h"
#include "Core/HLE/__sceAudio.h"
#include "Core/HLE/proAdhoc.h"
// #include "Core/HLE/proAdhoc.h"
#include "Core/HW/Display.h"
#include "UI/BackgroundAudio.h"
@ -1240,6 +1241,9 @@ UI::EventReturn EmuScreen::OnResume(UI::EventParams &params) {
return UI::EVENT_DONE;
}
// To avoid including proAdhoc.h, which includes a lot of stuff.
int GetChatMessageCount();
void EmuScreen::update() {
using namespace UI;
@ -1635,18 +1639,20 @@ ScreenRenderFlags EmuScreen::render(ScreenRenderMode mode) {
if (imguiVisible_ && !imguiInited_) {
imguiInited_ = true;
imDebugger_ = std::make_unique<ImDebugger>();
ImGui_ImplThin3d_Init(draw);
}
if (imguiVisible_ && imguiInited_) {
_dbg_assert_(imDebugger_);
ImGui_ImplPlatform_NewFrame();
ImGui_ImplThin3d_NewFrame(draw, ui_draw2d.GetDrawMatrix());
// Draw imgui on top. For now, all we have is the demo window.
ImGui::NewFrame();
ImGui::ShowDemoWindow(nullptr);
ImGui::Render();
imDebugger_->Frame(currentDebugMIPS);
ImGui::Render();
ImGui_ImplThin3d_RenderDrawData(ImGui::GetDrawData(), draw);
}
return flags;

View File

@ -29,6 +29,8 @@
#include "Core/KeyMap.h"
#include "Core/ControlMapper.h"
#include "UI/ImDebugger/ImDebugger.h"
struct AxisInput;
class AsyncImageFileView;
@ -129,6 +131,8 @@ private:
ControlMapper controlMapper_;
std::unique_ptr<ImDebugger> imDebugger_ = nullptr;
bool imguiInited_ = false;
bool imguiVisible_ = false;
};

View File

@ -0,0 +1,234 @@
#include "ext/imgui/imgui_internal.h"
#include "Common/StringUtils.h"
#include "Core/Core.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/Breakpoints.h"
#include "Core/MIPS/MIPSDebugInterface.h"
#include "Core/MIPS/MIPSTables.h"
#include "Core/Debugger/SymbolMap.h"
#include "Core/MemMap.h"
#include "Common/System/Request.h"
#include "UI/ImDebugger/ImDebugger.h"
void DrawRegisterView(MIPSDebugInterface *mipsDebug, bool *open) {
if (!ImGui::Begin("Registers", open)) {
ImGui::End();
return;
}
if (ImGui::BeginTabBar("RegisterGroups", ImGuiTabBarFlags_None)) {
if (ImGui::BeginTabItem("GPR")) {
if (ImGui::BeginTable("gpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) {
ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
auto gprLine = [&](const char *regname, int value) {
ImGui::TableSetColumnIndex(0);
ImGui::Text("%s", regname);
ImGui::TableSetColumnIndex(1);
ImGui::Text("%08x", value);
if (value >= -1000000 && value <= 1000000) {
ImGui::TableSetColumnIndex(2);
ImGui::Text("%d", value);
}
ImGui::TableNextRow();
};
for (int i = 0; i < 32; i++) {
gprLine(mipsDebug->GetRegName(0, i).c_str(), mipsDebug->GetGPR32Value(i));
}
gprLine("hi", mipsDebug->GetHi());
gprLine("lo", mipsDebug->GetLo());
gprLine("pc", mipsDebug->GetPC());
gprLine("ll", mipsDebug->GetLLBit());
ImGui::EndTable();
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("FPR")) {
if (ImGui::BeginTable("fpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) {
ImGui::TableSetupColumn("regname", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("value_i", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
for (int i = 0; i < 32; i++) {
float fvalue = mipsDebug->GetFPR32Value(i);
u32 fivalue;
memcpy(&fivalue, &fvalue, sizeof(fivalue));
ImGui::TableSetColumnIndex(0);
ImGui::Text("%s", mipsDebug->GetRegName(1, i).c_str());
ImGui::TableSetColumnIndex(1);
ImGui::Text("%0.7f", fvalue);
ImGui::TableSetColumnIndex(2);
ImGui::Text("%08x", fivalue);
ImGui::TableNextRow();
}
ImGui::EndTable();
}
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("VPR")) {
ImGui::Text("TODO");
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
}
void ImDebugger::Frame(MIPSDebugInterface *mipsDebug) {
// Snapshot the coreState to avoid inconsistency.
const CoreState coreState = ::coreState;
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("Debug")) {
if (coreState == CoreState::CORE_STEPPING) {
if (ImGui::MenuItem("Run")) {
Core_Resume();
}
if (ImGui::MenuItem("Step Into", "F11")) {
Core_RequestSingleStep(CPUStepType::Into, 1);
}
if (ImGui::MenuItem("Step Over", "F10")) {
Core_RequestSingleStep(CPUStepType::Over, 1);
}
if (ImGui::MenuItem("Step Out", "Shift+F11")) {
Core_RequestSingleStep(CPUStepType::Out, 1);
}
} else {
if (ImGui::MenuItem("Break")) {
Core_Break("Menu:Break");
}
}
ImGui::Separator();
if (ImGui::MenuItem("Toggle Breakpoint")) {
// TODO
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Window")) {
ImGui::Checkbox("Dear ImGUI Demo", &demoOpen_);
ImGui::Checkbox("CPU debugger", &disasmOpen_);
ImGui::Checkbox("Registers", &regsOpen_);
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
if (demoOpen_) {
ImGui::ShowDemoWindow(&demoOpen_);
}
if (disasmOpen_) {
disasm_.Draw(mipsDebug, &disasmOpen_, coreState);
}
if (regsOpen_) {
DrawRegisterView(mipsDebug, &regsOpen_);
}
}
void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState coreState) {
char title[256];
snprintf(title, sizeof(title), "%s - Disassembly", "Allegrex MIPS");
disasmView_.setDebugger(mipsDebug);
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, open, ImGuiWindowFlags_NoNavInputs)) {
ImGui::End();
return;
}
if (ImGui::IsWindowFocused()) {
// Process stepping keyboard shortcuts.
if (ImGui::IsKeyPressed(ImGuiKey_F10)) {
Core_RequestSingleStep(CPUStepType::Over, 0);
}
if (ImGui::IsKeyPressed(ImGuiKey_F11)) {
Core_RequestSingleStep(CPUStepType::Into, 0);
}
}
ImGui::BeginDisabled(coreState != CORE_STEPPING);
if (ImGui::SmallButton("Run")) {
Core_Resume();
}
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::BeginDisabled(coreState != CORE_RUNNING);
if (ImGui::SmallButton("Pause")) {
Core_Break("Pause");
}
ImGui::EndDisabled();
ImGui::SameLine();
if (ImGui::SmallButton("Step Into")) {
u32 stepSize = disasmView_.getInstructionSizeAt(mipsDebug->GetPC());
Core_RequestSingleStep(CPUStepType::Into, stepSize);
}
ImGui::SameLine();
if (ImGui::SmallButton("Step Over")) {
Core_RequestSingleStep(CPUStepType::Over, 0);
}
ImGui::SameLine();
if (ImGui::SmallButton("Step Out")) {
Core_RequestSingleStep(CPUStepType::Out, 0);
}
ImGui::SameLine();
if (ImGui::SmallButton("Goto PC")) {
disasmView_.gotoPC();
}
ImGui::SameLine();
ImGui::Checkbox("Follow PC", &disasmView_.followPC_);
ImGui::SetNextItemWidth(100);
if (ImGui::InputScalar("Go to addr: ", ImGuiDataType_U32, &gotoAddr_, NULL, NULL, "%08X", ImGuiInputTextFlags_EnterReturnsTrue)) {
disasmView_.setCurAddress(gotoAddr_);
disasmView_.scrollAddressIntoView();
}
if (ImGui::BeginTable("main", 2)) {
ImGui::TableSetupColumn("left", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("right", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImVec2 sz = ImGui::GetContentRegionAvail();
if (ImGui::BeginListBox("##symbols", ImVec2(150.0, sz.y - ImGui::GetTextLineHeightWithSpacing() * 2))) {
if (symCache_.empty()) {
symCache_ = g_symbolMap->GetAllSymbols(SymbolType::ST_FUNCTION);
}
ImGuiListClipper clipper;
clipper.Begin((int)symCache_.size(), -1);
while (clipper.Step()) {
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
if (ImGui::Selectable(symCache_[i].name.c_str(), false)) {
disasmView_.setCurAddress(symCache_[i].address);
disasmView_.scrollAddressIntoView();
}
}
}
clipper.End();
ImGui::EndListBox();
}
ImGui::TableSetColumnIndex(1);
disasmView_.Draw(ImGui::GetWindowDrawList());
ImGui::EndTable();
ImGui::Text("%s", disasmView_.StatusBarText().c_str());
}
ImGui::End();
}

View File

@ -0,0 +1,61 @@
#pragma once
#include <vector>
#include <string>
#include <set>
#include "ext/imgui/imgui.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"
#include "Core/Core.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/DebugInterface.h"
#include "UI/ImDebugger/ImDisasmView.h"
// This is the main state container of the whole Dear ImGUI-based in-game cross-platform debugger.
//
// Code conventions for ImGUI in PPSSPP
// * If windows/objects need state, prefix the class name with Im and just store straight in parent struct
class MIPSDebugInterface;
// Corresponds to the CDisasm dialog
class ImDisasmWindow {
public:
void Draw(MIPSDebugInterface *mipsDebug, bool *open, CoreState coreState);
private:
// We just keep the state directly in the window. Can refactor later.
enum {
INVALID_ADDR = 0xFFFFFFFF,
};
u32 gotoAddr_ = 0x1000;
// Symbol cache
std::vector<SymbolEntry> symCache_;
ImDisasmView disasmView_;
};
class ImLuaConsole {
public:
// Stub
};
struct ImDebugger {
void Frame(MIPSDebugInterface *mipsDebug);
ImDisasmWindow disasm_;
ImLuaConsole luaConsole_;
// Open variables.
bool disasmOpen_ = true;
bool demoOpen_ = false;
bool regsOpen_ = true;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,174 @@
#pragma once
#include <vector>
#include <string>
#include <set>
#include "ext/imgui/imgui.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"
#include "Core/Debugger/DisassemblyManager.h"
#include "Core/Debugger/DebugInterface.h"
// Corresponds to CtrlDisAsmView
// TODO: Fold out common code.
class ImDisasmView {
public:
ImDisasmView();
~ImDisasmView();
// Public variables bounds to imgui checkboxes
bool followPC_ = true;
void Draw(ImDrawList *drawList);
void PopupMenu();
void ScrollRelative(int amount);
void onChar(int c);
void onKeyDown(ImGuiKey key);
void onMouseDown(int x, int y, int button);
void onMouseUp(int x, int y, int button);
void onMouseMove(int x, int y, int button);
void scrollAddressIntoView();
bool curAddressIsVisible();
void ScanVisibleFunctions();
void clearFunctions() { manager.clear(); };
void getOpcodeText(u32 address, char* dest, int bufsize);
u32 yToAddress(int y);
void setDebugger(DebugInterface *deb) {
if (debugger != deb) {
debugger = deb;
curAddress_ = debugger->getPC();
manager.setCpu(deb);
}
}
DebugInterface *getDebugger() {
return debugger;
}
void scrollStepping(u32 newPc);
u32 getInstructionSizeAt(u32 address);
void gotoAddr(unsigned int addr) {
if (positionLocked_ != 0)
return;
u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_);
u32 newAddress = manager.getStartAddress(addr);
if (newAddress < windowStart_ || newAddress >= windowEnd) {
windowStart_ = manager.getNthPreviousAddress(newAddress, visibleRows_ / 2);
}
setCurAddress(newAddress);
ScanVisibleFunctions();
}
void gotoPC() {
gotoAddr(debugger->getPC());
}
u32 getSelection() {
return curAddress_;
}
void setShowMode(bool s) {
showHex_ = s;
}
void toggleBreakpoint(bool toggleEnabled = false);
void editBreakpoint();
void setCurAddress(u32 newAddress, bool extend = false) {
newAddress = manager.getStartAddress(newAddress);
const u32 after = manager.getNthNextAddress(newAddress, 1);
curAddress_ = newAddress;
selectRangeStart_ = extend ? std::min(selectRangeStart_, newAddress) : newAddress;
selectRangeEnd_ = extend ? std::max(selectRangeEnd_, after) : after;
updateStatusBarText();
}
void LockPosition() {
positionLocked_++;
}
void UnlockPosition() {
positionLocked_--;
_assert_(positionLocked_ >= 0);
}
// Check these every frame!
const std::string &StatusBarText() const {
return statusBarText_;
}
bool SymbolMapReloaded() {
bool retval = mapReloaded_;
mapReloaded_ = false;
return retval;
}
private:
enum class CopyInstructionsMode {
OPCODES,
DISASM,
ADDRESSES,
};
struct Rect {
float left;
float top;
float right;
float bottom;
};
void assembleOpcode(u32 address, const std::string &defaultText);
std::string disassembleRange(u32 start, u32 size);
void disassembleToFile();
void search(bool continueSearch);
void followBranch();
void calculatePixelPositions();
bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData);
void updateStatusBarText();
void drawBranchLine(ImDrawList *list, ImDisasmView::Rect rc, std::map<u32, float> &addressPositions, const BranchLine &line);
void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode);
void NopInstructions(u32 startAddr, u32 endAddr);
std::set<std::string> getSelectedLineArguments();
void drawArguments(ImDrawList *list, ImDisasmView::Rect rc, const DisassemblyLineInfo &line, int x, int y, ImColor textColor, const std::set<std::string> &currentArguments);
DisassemblyManager manager;
u32 curAddress_ = 0;
u32 selectRangeStart_ = 0;
u32 selectRangeEnd_ = 0;
float rowHeight_ = 0.f;
float charWidth_ = 0.f;
bool bpPopup_ = false;
bool hasFocus_ = true;
bool showHex_ = false;
DebugInterface *debugger = nullptr;
u32 windowStart_ = 0;
int visibleRows_ = 1;
bool displaySymbols_ = true;
struct {
int addressStart;
int opcodeStart;
int argumentsStart;
int arrowsStart;
} pixelPositions_;
std::vector<u32> jumpStack_;
std::string searchQuery_;
int matchAddress_;
bool searching_ = false;
bool keyTaken = false;
bool mapReloaded_ = false;
int positionLocked_ = 0;
int lastSteppingCount_ = 0;
std::string statusBarText_;
};

View File

@ -51,6 +51,8 @@
<ClCompile Include="GameScreen.cpp" />
<ClCompile Include="GameSettingsScreen.cpp" />
<ClCompile Include="GPUDriverTestScreen.cpp" />
<ClCompile Include="ImDebugger\ImDebugger.cpp" />
<ClCompile Include="ImDebugger\ImDisasmView.cpp" />
<ClCompile Include="JitCompareScreen.cpp" />
<ClCompile Include="JoystickHistoryView.cpp" />
<ClCompile Include="MainScreen.cpp" />
@ -91,6 +93,8 @@
<ClInclude Include="GameSettingsScreen.h" />
<ClInclude Include="CwCheatScreen.h" />
<ClInclude Include="GPUDriverTestScreen.h" />
<ClInclude Include="ImDebugger\ImDebugger.h" />
<ClInclude Include="ImDebugger\ImDisasmView.h" />
<ClInclude Include="JitCompareScreen.h" />
<ClInclude Include="JoystickHistoryView.h" />
<ClInclude Include="MainScreen.h" />

View File

@ -98,6 +98,12 @@
<ClCompile Include="JitCompareScreen.cpp">
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="ImDebugger\ImDebugger.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
<ClCompile Include="ImDebugger\ImDisasmView.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@ -196,6 +202,12 @@
<ClInclude Include="JitCompareScreen.h">
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="ImDebugger\ImDebugger.h">
<Filter>ImDebugger</Filter>
</ClInclude>
<ClInclude Include="ImDebugger\ImDisasmView.h">
<Filter>ImDebugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">
@ -204,5 +216,8 @@
<Filter Include="Views">
<UniqueIdentifier>{071baa63-c681-4ad6-945b-e126645d1b55}</UniqueIdentifier>
</Filter>
<Filter Include="ImDebugger">
<UniqueIdentifier>{fda6bc55-1386-4650-a274-44fac9605ea3}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -1023,4 +1023,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -126,6 +126,8 @@
<ClInclude Include="..\..\UI\GameScreen.h" />
<ClInclude Include="..\..\UI\GameSettingsScreen.h" />
<ClInclude Include="..\..\UI\GPUDriverTestScreen.h" />
<ClInclude Include="..\..\UI\ImDebugger\ImDebugger.h" />
<ClInclude Include="..\..\UI\ImDebugger\ImDisasmView.h" />
<ClInclude Include="..\..\UI\InstallZipScreen.h" />
<ClInclude Include="..\..\UI\JitCompareScreen.h" />
<ClInclude Include="..\..\UI\JoystickHistoryView.h" />
@ -166,6 +168,8 @@
<ClCompile Include="..\..\UI\GameScreen.cpp" />
<ClCompile Include="..\..\UI\GameSettingsScreen.cpp" />
<ClCompile Include="..\..\UI\GPUDriverTestScreen.cpp" />
<ClCompile Include="..\..\UI\ImDebugger\ImDebugger.cpp" />
<ClCompile Include="..\..\UI\ImDebugger\ImDisasmView.cpp" />
<ClCompile Include="..\..\UI\InstallZipScreen.cpp" />
<ClCompile Include="..\..\UI\JitCompareScreen.cpp" />
<ClCompile Include="..\..\UI\JoystickHistoryView.cpp" />

View File

@ -39,6 +39,12 @@
<ClCompile Include="..\..\UI\DebugOverlay.cpp" />
<ClCompile Include="..\..\UI\DriverManagerScreen.cpp" />
<ClCompile Include="..\..\UI\JitCompareScreen.cpp" />
<ClCompile Include="..\..\UI\ImDebugger\ImDebugger.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
<ClCompile Include="..\..\UI\ImDebugger\ImDisasmView.cpp">
<Filter>ImDebugger</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@ -79,5 +85,16 @@
<ClInclude Include="..\..\UI\DebugOverlay.h" />
<ClInclude Include="..\..\UI\DriverManagerScreen.h" />
<ClInclude Include="..\..\UI\JitCompareScreen.h" />
<ClInclude Include="..\..\UI\ImDebugger\ImDebugger.h">
<Filter>ImDebugger</Filter>
</ClInclude>
<ClInclude Include="..\..\UI\ImDebugger\ImDisasmView.h">
<Filter>ImDebugger</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="ImDebugger">
<UniqueIdentifier>{4013cb89-6145-451c-9cb1-d63d01f66bd5}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -60,7 +60,7 @@ void CtrlDisAsmView::deinit()
//UnregisterClass(szClassName, hInst)
}
void CtrlDisAsmView::scanFunctions()
void CtrlDisAsmView::scanVisibleFunctions()
{
manager.analyze(windowStart,manager.getNthNextAddress(windowStart,visibleRows)-windowStart);
}
@ -322,7 +322,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, const std::string &defaultText)
Reporting::NotifyDebugger();
if (result == true)
{
scanFunctions();
scanVisibleFunctions();
if (address == curAddress)
gotoAddr(manager.getNthNextAddress(curAddress,1));
@ -527,7 +527,7 @@ void CtrlDisAsmView::onPaint(WPARAM wParam, LPARAM lParam)
addressPositions[address] = rowY1;
// draw background
COLORREF backgroundColor = whiteBackground ? 0xFFFFFF : debugger->getColor(address);
COLORREF backgroundColor = whiteBackground ? 0xFFFFFF : debugger->getColor(address, false);
COLORREF textColor = 0x000000;
if (isInInterval(address,line.totalSize,debugger->getPC()))
@ -641,7 +641,7 @@ void CtrlDisAsmView::onVScroll(WPARAM wParam, LPARAM lParam)
return;
}
scanFunctions();
scanVisibleFunctions();
redraw();
}
@ -750,11 +750,11 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam)
break;
case VK_UP:
scrollWindow(-1);
scanFunctions();
scanVisibleFunctions();
break;
case VK_DOWN:
scrollWindow(1);
scanFunctions();
scanVisibleFunctions();
break;
case VK_NEXT:
setCurAddress(manager.getNthPreviousAddress(windowEnd,1),KeyDownAsync(VK_SHIFT));
@ -836,7 +836,7 @@ void CtrlDisAsmView::scrollAddressIntoView()
else if (curAddress >= windowEnd)
windowStart = manager.getNthPreviousAddress(curAddress,visibleRows-1);
scanFunctions();
scanVisibleFunctions();
}
bool CtrlDisAsmView::curAddressIsVisible()

View File

@ -100,7 +100,7 @@ public:
void scrollAddressIntoView();
bool curAddressIsVisible();
void redraw();
void scanFunctions();
void scanVisibleFunctions();
void clearFunctions() { manager.clear(); };
void getOpcodeText(u32 address, char* dest, int bufsize);
@ -135,7 +135,7 @@ public:
}
setCurAddress(newAddress);
scanFunctions();
scanVisibleFunctions();
redraw();
}
void gotoPC()
@ -162,7 +162,7 @@ public:
else
windowStart = manager.getNthNextAddress(windowStart,lines);
scanFunctions();
scanVisibleFunctions();
redraw();
}

View File

@ -576,8 +576,8 @@ void CtrlRegisterList::onMouseMove(WPARAM wParam, LPARAM lParam, int button)
int CtrlRegisterList::yToIndex(int y)
{
// int ydiff=y-rect.bottom/2-rowHeight/2;
// ydiff=(int)(floorf((float)ydiff / (float)rowHeight))+1;
// int ydiff=y-rect.bottom/2-rowHeight_/2;
// ydiff=(int)(floorf((float)ydiff / (float)rowHeight_))+1;
// return curAddress + ydiff * align;
int n = (y/rowHeight) - 1;
if (n<0) n=0;

View File

@ -707,7 +707,7 @@ void CDisasm::SetDebugMode(bool _bDebug, bool switchPC)
if (switchPC)
ptr->gotoPC();
ptr->scanFunctions();
ptr->scanVisibleFunctions();
}
else
{

View File

@ -295,7 +295,7 @@ void MainThreadFunc() {
}
}
} else {
while (GetUIState() != UISTATE_EXIT) {
while (GetUIState() != UISTATE_EXIT) { // && GetUIState() != UISTATE_EXCEPTION
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
// This way they can load a new game.
if (!Core_IsActive())

View File

@ -875,6 +875,8 @@ LOCAL_SRC_FILES := \
$(SRC)/android/jni/AndroidVulkanContext.cpp \
$(SRC)/android/jni/AndroidAudio.cpp \
$(SRC)/android/jni/OpenSLContext.cpp \
$(SRC)/UI/ImDebugger/ImDebugger.cpp \
$(SRC)/UI/ImDebugger/ImDisasmView.cpp \
$(SRC)/UI/AudioCommon.cpp \
$(SRC)/UI/BackgroundAudio.cpp \
$(SRC)/UI/DiscordIntegration.cpp \

View File

@ -8,7 +8,7 @@
#include "imgui_impl_platform.h"
void ImGui_ImplPlatform_KeyEvent(const KeyInput &key) {
ImGuiIO& io = ImGui::GetIO();
ImGuiIO &io = ImGui::GetIO();
if (key.flags & KEY_DOWN) {
// Specially handle scroll events and any other special keys.
@ -88,6 +88,7 @@ void ImGui_ImplPlatform_NewFrame() {
io.DisplaySize = ImVec2(g_display.pixel_xres, g_display.pixel_yres);
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
io.DeltaTime = now - lastTime;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
lastTime = now;
}