diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 520da9c502..9a6b58db6a 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -951,6 +951,12 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu ImGui::MenuItem("Callstacks", nullptr, &cfg_.callstackOpen); ImGui::MenuItem("Breakpoints", nullptr, &cfg_.breakpointsOpen); ImGui::MenuItem("Scheduler", nullptr, &cfg_.schedulerOpen); + ImGui::Separator(); + for (int i = 0; i < 4; i++) { + char title[64]; + snprintf(title, sizeof(title), "Memory %d", i + 1); + ImGui::MenuItem("Memory", nullptr, &cfg_.memViewOpen[i]); + } ImGui::EndMenu(); } if (ImGui::BeginMenu("HLE")) { @@ -1074,6 +1080,10 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu DrawSchedulerView(cfg_); } + for (int i = 0; i < 4; i++) { + mem_[i].Draw(mipsDebug, &cfg_.memViewOpen[i], i); + } + // Process UI commands switch (control.command.cmd) { case ImCmd::SHOW_IN_CPU_DISASM: @@ -1086,13 +1096,27 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu } void ImDebugger::Snapshot() { +} +void ImMemWindow::Draw(MIPSDebugInterface *mipsDebug, bool *open, int index) { + char title[256]; + snprintf(title, sizeof(title), "Memory %d", index); + ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); + if (!ImGui::Begin(title, open, ImGuiWindowFlags_NoNavInputs)) { + ImGui::End(); + return; + } + + memView_.setDebugger(mipsDebug); + memView_.Draw(ImGui::GetWindowDrawList()); + + ImGui::End(); } void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, ImConfig &cfg, CoreState coreState) { char title[256]; snprintf(title, sizeof(title), "%s - Disassembly", "Allegrex MIPS"); - + disasmView_.setDebugger(mipsDebug); ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); @@ -1347,6 +1371,11 @@ void ImConfig::SyncConfig(IniFile *ini, bool save) { sync.Sync("geDebuggerOpen", &geDebuggerOpen, false); sync.Sync("geStateOpen", &geStateOpen, false); sync.Sync("schedulerOpen", &schedulerOpen, false); + for (int i = 0; i < 4; i++) { + char name[64]; + snprintf(name, sizeof(name), "memory%dOpen", i + 1); + sync.Sync(name, &memViewOpen[i], false); + } sync.SetSection(ini->GetOrCreateSection("Settings")); sync.Sync("displayLatched", &displayLatched, false); diff --git a/UI/ImDebugger/ImDebugger.h b/UI/ImDebugger/ImDebugger.h index 036b6162ac..c40c6841b1 100644 --- a/UI/ImDebugger/ImDebugger.h +++ b/UI/ImDebugger/ImDebugger.h @@ -16,6 +16,7 @@ #include "Core/Debugger/DebugInterface.h" #include "UI/ImDebugger/ImDisasmView.h" +#include "UI/ImDebugger/ImMemView.h" #include "UI/ImDebugger/ImStructViewer.h" #include "UI/ImDebugger/ImGe.h" @@ -58,6 +59,33 @@ private: char searchTerm_[64]{}; }; +// Corresponds to the CMemView dialog +class ImMemWindow { +public: + void Draw(MIPSDebugInterface *mipsDebug, bool *open, int index); + ImMemView &View() { + return memView_; + } + void DirtySymbolMap() { + symsDirty_ = true; + } + +private: + // We just keep the state directly in the window. Can refactor later. + enum { + INVALID_ADDR = 0xFFFFFFFF, + }; + + // Symbol cache + std::vector symCache_; + bool symsDirty_ = true; + int selectedSymbol_ = -1; + char selectedSymbolName_[128]; + + ImMemView memView_; + char searchTerm_[64]{}; +}; + struct ImConfig { // Defaults for saved settings are set in SyncConfig. @@ -82,6 +110,7 @@ struct ImConfig { bool geDebuggerOpen; bool geStateOpen; bool schedulerOpen; + bool memViewOpen[4]; // HLE explorer settings // bool filterByUsed = true; @@ -139,6 +168,7 @@ private: ImDisasmWindow disasm_; ImGeDebuggerWindow geDebugger_; ImGeStateWindow geStateWindow_; + ImMemWindow mem_[4]; // We support 4 separate instances of the memory viewer. ImStructViewer structViewer_; // Open variables. diff --git a/UI/ImDebugger/ImDisasmView.cpp b/UI/ImDebugger/ImDisasmView.cpp index 48d1a123ce..4bd26b7662 100644 --- a/UI/ImDebugger/ImDisasmView.cpp +++ b/UI/ImDebugger/ImDisasmView.cpp @@ -1,9 +1,9 @@ - #include "ext/imgui/imgui_internal.h" #include "ext/imgui/imgui_impl_thin3d.h" #include "Common/StringUtils.h" #include "Common/Log.h" +#include "Common/Math/geom2d.h" #include "Core/Core.h" #include "Core/Debugger/DebugInterface.h" #include "Core/Debugger/DisassemblyManager.h" @@ -82,24 +82,6 @@ bool ImDisasmView::getDisasmAddressText(u32 address, char* dest, bool abbreviate } } -// TODO: Replace with another impl. -/* -static std::string trimString(std::string input) { - size_t pos = input.find_first_not_of(" \t"); - if (pos != 0 && pos != std::string::npos) { - input = input.erase(0, pos); - } - - pos = input.find_last_not_of(" \t"); - if (pos != std::string::npos) { - size_t size = input.length() - pos - 1; - input = input.erase(pos + 1, size); - } - - return input; -} -*/ - void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) { /* if (!Core_IsStepping()) { @@ -157,7 +139,7 @@ void ImDisasmView::assembleOpcode(u32 address, const std::string &defaultText) { */ } -void ImDisasmView::drawBranchLine(ImDrawList *drawList, Rect rect, std::map &addressPositions, const BranchLine &line) { +void ImDisasmView::drawBranchLine(ImDrawList *drawList, Bounds rect, std::map &addressPositions, const BranchLine &line) { u32 windowEnd = manager.getNthNextAddress(windowStart_, visibleRows_); float topY; @@ -165,7 +147,7 @@ void ImDisasmView::drawBranchLine(ImDrawList *drawList, Rect rect, std::map= windowEnd) { - topY = rect.bottom + 1.0f; + topY = rect.y2() + 1.0f; } else { topY = (float)addressPositions[line.first] + rowHeight_ / 2; } @@ -173,12 +155,12 @@ void ImDisasmView::drawBranchLine(ImDrawList *drawList, Rect rect, std::map= windowEnd) { - bottomY = rect.bottom + 1.0f; + bottomY = rect.y2() + 1.0f; } else { bottomY = (float)addressPositions[line.second] + rowHeight_ / 2; } - if ((topY < 0 && bottomY < 0) || (topY > rect.bottom && bottomY > rect.bottom)) { + if ((topY < 0 && bottomY < 0) || (topY > rect.y2() && bottomY > rect.y2())) { return; } @@ -200,7 +182,7 @@ void ImDisasmView::drawBranchLine(ImDrawList *drawList, Rect rect, std::mapAddLine(ImVec2(rect.left + curX, rect.top + curY), ImVec2(rect.left + (float)x, rect.top + (float)y), pen, 1.0f); + drawList->AddLine(ImVec2(rect.x + curX, rect.y + curY), ImVec2(rect.x + (float)x, rect.y + (float)y), pen, 1.0f); curX = x; curY = y; }; @@ -215,10 +197,10 @@ void ImDisasmView::drawBranchLine(ImDrawList *drawList, Rect rect, std::map rect.bottom) {// second is not visible, but first is + } else if (bottomY > rect.y2()) {// second is not visible, but first is moveTo(x - 2.f, topY); lineTo(x + 2.f, topY); - lineTo(x + 2.f, rect.bottom); + lineTo(x + 2.f, rect.y2()); if (line.type == LINE_UP) { moveTo(x, topY - 4.f); @@ -266,13 +248,13 @@ std::set ImDisasmView::getSelectedLineArguments() { return args; } -void ImDisasmView::drawArguments(ImDrawList *drawList, Rect rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set ¤tArguments) { +void ImDisasmView::drawArguments(ImDrawList *drawList, Bounds rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set ¤tArguments) { if (line.params.empty()) { return; } // Don't highlight the selected lines. if (isInInterval(selectRangeStart_, selectRangeEnd_ - selectRangeStart_, line.info.opcodeAddress)) { - drawList->AddText(ImVec2((float)(rc.left + x), (float)(rc.top + y)), textColor, line.params.data(), line.params.data() + line.params.size()); + drawList->AddText(ImVec2((float)(rc.x + x), (float)(rc.y + y)), textColor, line.params.data(), line.params.data() + line.params.size()); return; } @@ -286,7 +268,7 @@ void ImDisasmView::drawArguments(ImDrawList *drawList, Rect rc, const Disassembl ImColor curColor = textColor; auto Print = [&](std::string_view text) { - drawList->AddText(ImVec2(rc.left + curX, rc.top + curY), curColor, text.data(), text.data() + text.size()); + drawList->AddText(ImVec2(rc.x + curX, rc.y + curY), curColor, text.data(), text.data() + text.size()); ImVec2 sz = ImGui::CalcTextSize(text.data(), text.data() + text.size(), false, -1.0f); curX += sz.x; }; @@ -314,7 +296,7 @@ void ImDisasmView::drawArguments(ImDrawList *drawList, Rect rc, const Disassembl } void ImDisasmView::Draw(ImDrawList *drawList) { - if (!debugger->isAlive()) { + if (!debugger_->isAlive()) { return; } @@ -340,7 +322,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { } ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY); - ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); + const ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); drawList->PushClipRect(canvas_p0, canvas_p1, true); drawList->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(25, 25, 25, 255)); @@ -348,15 +330,15 @@ void ImDisasmView::Draw(ImDrawList *drawList) { drawList->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255)); } - Rect rect; - rect.left = canvas_p0.x; - rect.top = canvas_p0.y; - rect.right = canvas_p1.x; - rect.bottom = canvas_p1.y; + Bounds bounds; + bounds.x = canvas_p0.x; + bounds.y = canvas_p0.y; + bounds.w = canvas_p1.x - canvas_p0.x; + bounds.h = canvas_p1.y - canvas_p0.y; calculatePixelPositions(); - visibleRows_ = (int)((rect.bottom - rect.top + rowHeight_ - 1.f) / rowHeight_); + visibleRows_ = (int)((bounds.h + rowHeight_ - 1.f) / rowHeight_); unsigned int address = windowStart_; std::map addressPositions; @@ -364,7 +346,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { const std::set currentArguments = getSelectedLineArguments(); DisassemblyLineInfo line; - const u32 pc = debugger->GetPC(); + const u32 pc = debugger_->GetPC(); for (int i = 0; i < visibleRows_; i++) { manager.getLine(address, displaySymbols_, line); @@ -375,7 +357,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { addressPositions[address] = rowY1; // draw background - ImColor backgroundColor = ImColor(0xFF000000 | debugger->getColor(address, true)); + ImColor backgroundColor = ImColor(0xFF000000 | debugger_->getColor(address, true)); ImColor textColor = 0xFFFFFFFF; if (isInInterval(address, line.totalSize, pc)) { @@ -391,7 +373,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { } } - drawList->AddRectFilled(ImVec2(rect.left, rect.top + rowY1), ImVec2(rect.right, rect.top + rowY1 + rowHeight_), backgroundColor); + drawList->AddRectFilled(ImVec2(bounds.x, bounds.y + rowY1), ImVec2(bounds.x2(), bounds.y + rowY1 + rowHeight_), backgroundColor); // display breakpoint, if any bool enabled; @@ -405,7 +387,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { char addressText[64]; getDisasmAddressText(address, addressText, true, line.type == DISTYPE_OPCODE); - drawList->AddText(ImVec2(rect.left + pixelPositions_.addressStart, rect.top + rowY1 + 2), textColor, addressText); + drawList->AddText(ImVec2(bounds.x + pixelPositions_.addressStart, bounds.y + rowY1 + 2), textColor, addressText); if (isInInterval(address, line.totalSize, pc)) { // Show the current PC with a little triangle. @@ -421,18 +403,18 @@ void ImDisasmView::Draw(ImDrawList *drawList) { line.params += line.info.conditionMet ? " ; true" : " ; false"; } - drawArguments(drawList, rect, line, pixelPositions_.argumentsStart, rowY1 + 2.f, textColor, currentArguments); + drawArguments(drawList, bounds, line, pixelPositions_.argumentsStart, rowY1 + 2.f, textColor, currentArguments); // The actual opcode. // Should be bold! - drawList->AddText(ImVec2(rect.left + pixelPositions_.opcodeStart, rect.top + rowY1 + 2.f), textColor, line.name.c_str()); + drawList->AddText(ImVec2(bounds.x + pixelPositions_.opcodeStart, bounds.y + rowY1 + 2.f), textColor, line.name.c_str()); address += line.totalSize; } std::vector branchLines = manager.getBranchLines(windowStart_, address - windowStart_); for (size_t i = 0; i < branchLines.size(); i++) { - drawBranchLine(drawList, rect, addressPositions, branchLines[i]); + drawBranchLine(drawList, bounds, addressPositions, branchLines[i]); } ImGuiIO& io = ImGui::GetIO(); @@ -481,7 +463,7 @@ void ImDisasmView::Draw(ImDrawList *drawList) { // INFO_LOG(Log::System, "Clicked %f,%f", mousePos.x, mousePos.y); if (mousePos.x < rowHeight_) { // Left column // Toggle breakpoint at dragAddr_. - debugger->toggleBreakpoint(curAddress_); + debugger_->toggleBreakpoint(curAddress_); bpPopup_ = true; } else { // disasmView_.selectedAddr_ = dragAddr_; @@ -528,7 +510,8 @@ void ImDisasmView::FollowBranch() { } void ImDisasmView::onChar(int c) { - if (keyTaken) return; + if (keyTaken) + return; char str[2]; str[0] = c; @@ -758,14 +741,14 @@ void ImDisasmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructions _assert_msg_((startAddr & 3) == 0, "readMemory() can't handle unaligned reads"); if (mode != CopyInstructionsMode::DISASM) { - int instructionSize = debugger->getInstructionSize(0); + int instructionSize = debugger_->getInstructionSize(0); int count = (endAddr - startAddr) / instructionSize; int space = count * 32; char *temp = new char[space]; char *p = temp, *end = temp + space; for (u32 pos = startAddr; pos < endAddr && p < end; pos += instructionSize) { - u32 data = mode == CopyInstructionsMode::OPCODES ? debugger->readMemory(pos) : pos; + u32 data = mode == CopyInstructionsMode::OPCODES ? debugger_->readMemory(pos) : pos; p += snprintf(p, end - p, "%08X", data); // Don't leave a trailing newline. @@ -812,7 +795,7 @@ void ImDisasmView::PopupMenu() { ImGui::Separator(); if (ImGui::MenuItem("Set PC to here")) { - debugger->SetPC(curAddress_); + debugger_->SetPC(curAddress_); } if (ImGui::MenuItem("Follow branch")) { FollowBranch(); @@ -1112,8 +1095,8 @@ std::string ImDisasmView::disassembleRange(u32 start, u32 size) { // gather all branch targets without labels std::set branchAddresses; - for (u32 i = 0; i < size; i += debugger->getInstructionSize(0)) { - MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger, start + i); + for (u32 i = 0; i < size; i += debugger_->getInstructionSize(0)) { + MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debugger_, start + i); if (info.isBranch && g_symbolMap->GetLabelString(info.branchTarget).empty()) { if (branchAddresses.find(info.branchTarget) == branchAddresses.end()) { diff --git a/UI/ImDebugger/ImDisasmView.h b/UI/ImDebugger/ImDisasmView.h index 00906c45cb..3cbd515720 100644 --- a/UI/ImDebugger/ImDisasmView.h +++ b/UI/ImDebugger/ImDisasmView.h @@ -8,6 +8,7 @@ #include "ext/imgui/imgui.h" #include "Common/CommonTypes.h" +#include "Common/Math/geom2d.h" #include "Core/Debugger/DisassemblyManager.h" #include "Core/Debugger/DebugInterface.h" @@ -43,14 +44,14 @@ public: u32 yToAddress(float y); void setDebugger(DebugInterface *deb) { - if (debugger != deb) { - debugger = deb; - curAddress_ = debugger->GetPC(); + if (debugger_ != deb) { + debugger_ = deb; + curAddress_ = debugger_->GetPC(); manager.setCpu(deb); } } DebugInterface *getDebugger() { - return debugger; + return debugger_; } void scrollStepping(u32 newPc); @@ -70,10 +71,10 @@ public: ScanVisibleFunctions(); } void gotoPC() { - gotoAddr(debugger->GetPC()); + gotoAddr(debugger_->GetPC()); } void gotoLR() { - gotoAddr(debugger->GetLR()); + gotoAddr(debugger_->GetLR()); } u32 getSelection() { return curAddress_; @@ -120,13 +121,6 @@ private: ADDRESSES, }; - struct Rect { - float left; - float top; - float right; - float bottom; - }; - void ProcessKeyboardShortcuts(bool focused); void assembleOpcode(u32 address, const std::string &defaultText); std::string disassembleRange(u32 start, u32 size); @@ -135,11 +129,11 @@ private: void calculatePixelPositions(); bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData); void updateStatusBarText(); - void drawBranchLine(ImDrawList *list, ImDisasmView::Rect rc, std::map &addressPositions, const BranchLine &line); + void drawBranchLine(ImDrawList *list, Bounds rc, std::map &addressPositions, const BranchLine &line); void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode); void NopInstructions(u32 startAddr, u32 endAddr); std::set getSelectedLineArguments(); - void drawArguments(ImDrawList *list, ImDisasmView::Rect rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set ¤tArguments); + void drawArguments(ImDrawList *list, Bounds rc, const DisassemblyLineInfo &line, float x, float y, ImColor textColor, const std::set ¤tArguments); DisassemblyManager manager; u32 curAddress_ = 0; @@ -152,7 +146,7 @@ private: bool hasFocus_ = true; bool showHex_ = false; - DebugInterface *debugger = nullptr; + DebugInterface *debugger_ = nullptr; u32 windowStart_ = 0; int visibleRows_ = 1; diff --git a/UI/ImDebugger/ImMemView.cpp b/UI/ImDebugger/ImMemView.cpp index 406fd0390a..b455b6ec0c 100644 --- a/UI/ImDebugger/ImMemView.cpp +++ b/UI/ImDebugger/ImMemView.cpp @@ -4,6 +4,7 @@ #include #include "ext/imgui/imgui.h" +#include "ext/imgui/imgui_internal.h" #include "ext/imgui/imgui_impl_thin3d.h" #include "ext/xxhash.h" @@ -38,103 +39,58 @@ ImMemView::~ImMemView() {} /* LRESULT CALLBACK ImMemView::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - ImMemView *ccp = ImMemView::getFrom(hwnd); - static bool lmbDown = false, rmbDown = false; - - switch (msg) { - case WM_NCCREATE: - // Allocate a new CustCtrl structure for this window. - ccp = new ImMemView(hwnd); - - // Continue with window creation. - return ccp != NULL; - - // Clean up when the window is destroyed. - case WM_NCDESTROY: - delete ccp; - break; - case WM_SETFONT: - break; - case WM_SIZE: - ccp->redraw(); - break; - case WM_PAINT: - ccp->onPaint(wParam, lParam); - break; - case WM_VSCROLL: - ccp->onVScroll(wParam, lParam); - break; - case WM_MOUSEWHEEL: if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) { ccp->ScrollWindow(-3, GotoModeFromModifiers(false)); } else if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) { ccp->ScrollWindow(3, GotoModeFromModifiers(false)); } - break; - case WM_ERASEBKGND: - return FALSE; - case WM_KEYDOWN: - ccp->onKeyDown(wParam, lParam); - return 0; - case WM_CHAR: - ccp->onChar(wParam, lParam); - return 0; - case WM_KEYUP: - return 0; - case WM_LBUTTONDOWN: SetFocus(hwnd); lmbDown = true; ccp->onMouseDown(wParam, lParam, 1); break; - case WM_RBUTTONDOWN: SetFocus(hwnd); rmbDown = true; ccp->onMouseDown(wParam, lParam, 2); break; - case WM_MOUSEMOVE: ccp->onMouseMove(wParam, lParam, (lmbDown ? 1 : 0) | (rmbDown ? 2 : 0)); break; - case WM_LBUTTONUP: lmbDown = false; ccp->onMouseUp(wParam, lParam, 1); break; - case WM_RBUTTONUP: rmbDown = false; ccp->onMouseUp(wParam, lParam, 2); break; - case WM_SETFOCUS: - SetFocus(hwnd); - ccp->hasFocus_ = true; - ccp->redraw(); - break; - case WM_KILLFOCUS: - ccp->hasFocus_ = false; - ccp->redraw(); - break; - case WM_GETDLGCODE: // we want to process the arrow keys and all characters ourselves - return DLGC_WANTARROWS | DLGC_WANTCHARS | DLGC_WANTTAB; - break; - case WM_TIMER: - // This is actually delayed too, using another timer. That way we won't update twice. - if (wParam == IDT_REDRAW_AUTO && IsWindowVisible(ccp->wnd)) - ccp->redraw(); - - if (wParam == IDT_REDRAW_DELAYED) { - InvalidateRect(hwnd, nullptr, FALSE); - UpdateWindow(hwnd); - ccp->redrawScheduled_ = false; - KillTimer(hwnd, wParam); - } - break; - default: - break; - } - return DefWindowProc(hwnd, msg, wParam, lParam); } */ void ImMemView::Draw(ImDrawList *drawList) { auto memLock = Memory::Lock(); + if (!debugger_->isAlive()) { + return; + } - visibleRows_ = rect_.bottom / rowHeight_; + ImGui_PushFixedFont(); + + rowHeight_ = ImGui::GetTextLineHeightWithSpacing(); + charWidth_ = ImGui::CalcTextSize("W", nullptr, false, -1.0f).x; + + const ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! + const ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); // Resize canvas to what's available + const ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); + + // This will catch our interactions + bool pressed = ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + const bool is_hovered = ImGui::IsItemHovered(); // Hovered + const bool is_active = ImGui::IsItemActive(); // Held + + if (pressed) { + // INFO_LOG(Log::System, "Pressed"); + } + ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY); + + visibleRows_ = canvas_sz.y / rowHeight_; if (displayOffsetScale_) { // visibleRows_ is calculated based on the size of the control, but X rows have already been used for the offsets and are no longer usable visibleRows_ -= offsetSpace; } - ImGui_PushFixedFont(); + Bounds bounds; + bounds.x = canvas_p0.x; + bounds.y = canvas_p0.y; + bounds.w = canvas_p1.x - canvas_p0.x; + bounds.h = canvas_p1.y - canvas_p0.y; - // Background fill - Rectangle(hdc, 0, 0, rect_.right, rect_.bottom); + drawList->PushClipRect(canvas_p0, canvas_p1, true); + drawList->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(25, 25, 25, 255)); if (displayOffsetScale_) - drawOffsetScale(); + drawOffsetScale(drawList); std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, windowStart_, (visibleRows_ + 1) * rowSize_); @@ -151,8 +107,7 @@ void ImMemView::Draw(ImDrawList *drawList) { uint32_t address = windowStart_ + i * rowSize_; snprintf(temp, sizeof(temp), "%08X", address); - setTextColors(0x600000, standardBG); - TextOutA(hdc, addressStartX_, rowY, temp, (int)strlen(temp)); + drawList->AddText(ImVec2(canvas_p0.x + addressStartX_, canvas_p0.y + rowY), IM_COL32(0, 0, 0x60, 0xFF), temp); union { uint32_t words[4]; @@ -189,16 +144,17 @@ void ImMemView::Draw(ImDrawList *drawList) { c = '.'; } - COLORREF hexBGCol = standardBG; - COLORREF hexTextCol = 0x000000; - COLORREF continueBGCol = standardBG; - COLORREF asciiBGCol = standardBG; - COLORREF asciiTextCol = 0x000000; + ImColor standardBG = 0xFF000000; + ImColor continueBGCol = 0xFF000000; + ImColor hexBGCol = 0xFF000000; + ImColor hexTextCol = 0xFFFFFFFF; + ImColor asciiBGCol = 0xFF000000; + ImColor asciiTextCol = 0xFFFFFFFF; int underline = -1; if (address + j >= selectRangeStart_ && address + j < selectRangeEnd_ && !searching_) { if (asciiSelected_) { - hexBGCol = 0xC0C0C0; + hexBGCol = ImColor(0xFFC0C0C0); hexTextCol = 0x000000; asciiBGCol = hasFocus_ ? 0xFF9933 : 0xC0C0C0; asciiTextCol = hasFocus_ ? 0xFFFFFF : 0x000000; @@ -220,35 +176,35 @@ void ImMemView::Draw(ImDrawList *drawList) { hexLen = tagContinues ? 3 : 2; } - setTextColors(hexTextCol, hexBGCol); + ImColor fg = hexTextCol; + ImColor bg = hexBGCol; if (underline >= 0) { - SelectObject(hdc, underline == 0 ? (HGDIOBJ)underlineFont : (HGDIOBJ)font); - TextOutA(hdc, hexX, rowY, &temp[0], 1); - SelectObject(hdc, underline == 0 ? (HGDIOBJ)font : (HGDIOBJ)underlineFont); - TextOutA(hdc, hexX + charWidth_, rowY, &temp[1], 1); - SelectObject(hdc, (HGDIOBJ)font); + // SelectObject(hdc, underline == 0 ? (HGDIOBJ)underlineFont : (HGDIOBJ)font); + drawList->AddText(ImVec2(canvas_p0.x + hexX, canvas_p0.y + rowY), fg, &temp[0], &temp[1]); + // SelectObject(hdc, underline == 0 ? (HGDIOBJ)font : (HGDIOBJ)underlineFont); + drawList->AddText(ImVec2(canvas_p0.x + hexX + charWidth_, canvas_p0.y + rowY), fg, &temp[1]); // If the tag keeps going, draw the BG too. if (continueBGCol != standardBG) { - setTextColors(0x000000, continueBGCol); - TextOutA(hdc, hexX + charWidth_ * 2, rowY, &temp[2], 1); + // setTextColors(0x000000, continueBGCol); + // TextOutA(hdc, hexX + charWidth_ * 2, rowY, &temp[2], 1); } } else { if (continueBGCol != hexBGCol) { - TextOutA(hdc, hexX, rowY, temp, 2); - setTextColors(0x000000, continueBGCol); - TextOutA(hdc, hexX + charWidth_ * 2, rowY, &temp[2], 1); + drawList->AddText(ImVec2(canvas_p0.x + hexX, canvas_p0.y + rowY), fg, &temp[0], &temp[2]); } else { - TextOutA(hdc, hexX, rowY, temp, hexLen); + drawList->AddText(ImVec2(canvas_p0.x + hexX, canvas_p0.y + rowY), fg, &temp[0], &temp[2]); } } - setTextColors(asciiTextCol, asciiBGCol); - TextOutA(hdc, asciiX, rowY, &c, 1); + // setTextColors(asciiTextCol, asciiBGCol); + // TextOutA(hdc, asciiX, rowY, &c, 1); + drawList->AddText(ImVec2(canvas_p0.x + asciiX, canvas_p0.y + rowY), fg, &c, &c + 1); } } ImGui_PopFont(); + drawList->PopClipRect(); } // We don't have a scroll bar - though maybe we should build one. @@ -282,11 +238,13 @@ void ImMemView::ProcessKeyboardShortcuts(bool focused) { if (io.KeyMods & ImGuiMod_Ctrl) { if (ImGui::IsKeyPressed(ImGuiKey_G)) { + /* u32 addr; if (executeExpressionWindow(wnd, debugger_, addr) == false) return; gotoAddr(addr); return; + */ } if (ImGui::IsKeyPressed(ImGuiKey_F)) { search(false); @@ -325,6 +283,7 @@ void ImMemView::onChar(int c) { if (io.KeyMods & ImGuiMod_Ctrl) { return; + } if (!Memory::IsValidAddress(curAddress_)) { ScrollCursor(1, GotoMode::RESET); @@ -385,9 +344,6 @@ void ImMemView::onMouseDown(WPARAM wParam, LPARAM lParam, int button) { } void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { - if (Achievements::HardcoreModeActive()) - return; - if (button == 2) { int32_t selectedSize = selectRangeEnd_ - selectRangeStart_; bool enable16 = !asciiSelected_ && (selectedSize == 1 || (selectedSize & 1) == 0); @@ -398,16 +354,13 @@ void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { EnableMenuItem(menu, ID_MEMVIEW_COPYVALUE_32, enable32 ? MF_ENABLED : MF_GRAYED); EnableMenuItem(menu, ID_MEMVIEW_COPYFLOAT_32, enable32 ? MF_ENABLED : MF_GRAYED); - switch (TriggerContextMenu(ContextMenuID::MEMVIEW, wnd, ContextPoint::FromEvent(lParam))) { - case ID_MEMVIEW_DUMP: - { + if (ImGui::MenuItem("Dump memory")) { DumpMemoryWindow dump(wnd, debugger_); dump.exec(); break; } - case ID_MEMVIEW_COPYVALUE_8: - { + if (ImGui::MenuItem("Copy value (8-bit)")) { auto memLock = Memory::Lock(); size_t tempSize = 3 * selectedSize + 1; char *temp = new char[tempSize]; @@ -431,13 +384,11 @@ void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { if (pos > temp) *(pos - 1) = '\0'; } - W32Util::CopyTextToClipboard(wnd, temp); + // W32Util::CopyTextToClipboard(wnd, temp); delete[] temp; } - break; - case ID_MEMVIEW_COPYVALUE_16: - { + if (ImGui::MenuItem("Copy value (16-bit)")) { auto memLock = Memory::Lock(); size_t tempSize = 5 * ((selectedSize + 1) / 2) + 1; char *temp = new char[tempSize]; @@ -455,10 +406,8 @@ void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { W32Util::CopyTextToClipboard(wnd, temp); delete[] temp; } - break; - case ID_MEMVIEW_COPYVALUE_32: - { + if (ImGui::MenuItem("Copy value (32-bit)")) { auto memLock = Memory::Lock(); size_t tempSize = 9 * ((selectedSize + 3) / 4) + 1; char *temp = new char[tempSize]; @@ -476,18 +425,15 @@ void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { W32Util::CopyTextToClipboard(wnd, temp); delete[] temp; } - break; - case ID_MEMVIEW_COPYFLOAT_32: - { + if (ImGui::MenuItem("Copy value (float32)") { auto memLock = Memory::Lock(); std::ostringstream stream; stream << (Memory::IsValidAddress(curAddress_) ? Memory::Read_Float(curAddress_) : NAN); auto temp_string = stream.str(); W32Util::CopyTextToClipboard(wnd, temp_string.c_str()); } - break; - + /* case ID_MEMVIEW_EXTENTBEGIN: { std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, curAddress_, 1); @@ -509,28 +455,26 @@ void ImMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { gotoAddr(addr); break; } - - case ID_MEMVIEW_COPYADDRESS: - { + */ + if (ImGui::MenuItem("Copy address")) { char temp[24]; snprintf(temp, sizeof(temp), "0x%08X", curAddress_); W32Util::CopyTextToClipboard(wnd, temp); } - break; - case ID_MEMVIEW_GOTOINDISASM: + if (ImGui::MenuItem("Goto in disasm")) { if (disasmWindow) { disasmWindow->Goto(curAddress_); disasmWindow->Show(true); } - break; } - return; } + /* int x = LOWORD(lParam); int y = HIWORD(lParam); ReleaseCapture(); + */ GotoPoint(x, y, GotoModeFromModifiers(button == 2)); }