28#include <imgui_stdlib.h>
34using namespace std::literals;
41 , symbolManager(manager.getReactor().getSymbolManager())
46static void saveItems(
zstring_view label,
const std::vector<ImGuiBreakPoints::GuiItem>& items, ImGuiTextBuffer& buf)
48 auto saveAddr = [](std::optional<uint16_t> addr) {
51 for (
const auto& item : items) {
56 saveAddr(item.endAddr),
61 buf.appendf(
"%s=%s\n", label.
c_str(), list.getString().c_str());
70 saveItems(
"breakpoint", guiBps, buf);
71 saveItems(
"watchpoint", guiWps, buf);
72 saveItems(
"condition", guiConditions, buf);
77template<
typename Item>
82 auto loadAddr = [&](
const TclObject& o) -> std::optional<uint16_t> {
83 if (o.getString().empty())
return {};
84 return o.getInt(interp);
88 TclObject list(value);
89 if (list.getListLength(interp) != 8)
return;
92 .wantEnable = list.getListIndex(interp, 0).getBoolean(interp),
93 .wpType = list.getListIndex(interp, 1).getInt(interp),
94 .addr = loadAddr(list.getListIndex(interp, 2)),
95 .endAddr = loadAddr(list.getListIndex(interp, 3)),
96 .addrStr = list.getListIndex(interp, 4),
97 .endAddrStr = list.getListIndex(interp, 5),
98 .cond = list.getListIndex(interp, 6),
99 .cmd = list.getListIndex(interp, 7),
101 if (item.wpType < 0 || item.wpType > 3)
return;
104 auto& items = getItems(tag);
105 items.push_back(std::move(item));
108 auto& cpuInterface = motherBoard->getCPUInterface();
109 auto& debugger = motherBoard->getDebugger();
110 syncToOpenMsx<Item>(cpuInterface, debugger, interp, items.back());
112 }
catch (CommandException&) {
122 auto& cpuInterface = motherBoard->getCPUInterface();
123 clear(
static_cast<BreakPoint *
>(
nullptr), cpuInterface);
124 clear(
static_cast<WatchPoint *
>(
nullptr), cpuInterface);
135 }
else if (name ==
"breakpoint"sv) {
136 loadItem<BreakPoint>(value);
137 }
else if (name ==
"watchpoint"sv) {
138 loadItem<WatchPoint>(value);
139 }
else if (name ==
"condition"sv) {
140 loadItem<DebugCondition>(value);
152 if (!motherBoard)
return;
156 syncFromOpenMsx<BreakPoint> (guiBps, cpuInterface);
157 syncFromOpenMsx<WatchPoint> (guiWps, cpuInterface);
158 syncFromOpenMsx<DebugCondition>(guiConditions, cpuInterface);
162 ImGui::SetNextWindowSize(
gl::vec2{25, 14} * ImGui::GetFontSize(), ImGuiCond_FirstUseEver);
167 paintTab<BreakPoint>(cpuInterface, debugger);
170 paintTab<WatchPoint>(cpuInterface, debugger);
173 paintTab<DebugCondition>(cpuInterface, debugger);
179static std::string_view getCheckCmd(
BreakPoint*) {
return "pc_in_slot"; }
180static std::string_view getCheckCmd(WatchPoint*) {
return "watch_in_slot"; }
181static std::string_view getCheckCmd(DebugCondition*) {
return "pc_in_slot"; }
187 auto end = cond.size();
188 std::optional<int> o_ps;
189 std::optional<int> o_ss;
190 std::optional<int> o_seg;
192 auto next = [&](std::string_view s) {
193 if (cond.substr(pos).starts_with(s)) {
200 bool stop = cond.substr(pos) ==
"]";
201 if (stop || (next(
"] && (") && cond.ends_with(
')'))) {
205 rest = cond.substr(pos, cond.size() - pos - 1);
207 if (o_ps) {
hasPs =
true;
ps = *o_ps; }
208 if (o_ss) {
hasSs =
true;
ss = *o_ss; }
209 if (o_seg) {
hasSeg =
true;
seg = narrow<uint8_t>(*o_seg); }
214 auto isDigit = [](
char c) {
return (
'0' <= c) && (c <=
'9'); };
215 auto getInt = [&](
unsigned max) -> std::optional<int> {
217 if ((pos ==
end) || !isDigit(cond[pos]))
return {};
218 while ((pos !=
end) && isDigit(cond[pos])) {
219 i = 10 * i + (cond[pos] -
'0');
222 if (i >= max)
return {};
226 if (!next(
tmpStrCat(
'[', checkCmd,
' ')))
return;
230 if (!next(
" "))
return;
236 if (!next(
" "))
return;
246 std::string result =
strCat(
'[', checkCmd,
' ',
ps);
265 std::string result =
strCat(
"Slot:",
ps,
'-');
280template<
typename Item>
struct HasAddress : std::true_type {};
290static void remove(WatchPoint*, MSXCPUInterface& cpuInterface,
unsigned id)
292 cpuInterface.removeWatchPoint(
id);
294static void remove(DebugCondition*, MSXCPUInterface& cpuInterface,
unsigned id)
296 cpuInterface.removeCondition(
id);
299void ImGuiBreakPoints::clear(BreakPoint* tag, MSXCPUInterface& cpuInterface)
301 while (!guiBps.empty()) {
302 if (
const auto& bp = guiBps.back(); bp.id > 0) {
303 remove(tag, cpuInterface, bp.id);
308void ImGuiBreakPoints::clear(WatchPoint* tag, MSXCPUInterface& cpuInterface)
310 while (!guiWps.empty()) {
311 if (
auto& wp = guiWps.back(); wp.id > 0) {
312 remove(tag, cpuInterface, wp.id);
318void ImGuiBreakPoints::clear(DebugCondition* tag, MSXCPUInterface& cpuInterface)
320 while (!guiConditions.empty()) {
321 if (
auto& cond = guiConditions.back(); cond.id > 0) {
322 remove(tag, cpuInterface, cond.id);
324 guiConditions.pop_back();
330 paintTab<BreakPoint>(cpuInterface, debugger, addr);
333template<
typename Item>
334void ImGuiBreakPoints::paintTab(
MSXCPUInterface& cpuInterface,
Debugger& debugger, std::optional<uint16_t> addr)
336 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
337 constexpr bool isCondition = std::is_same_v<Item, DebugCondition>;
340 auto& items = getItems(tag);
342 int flags = ImGuiTableFlags_RowBg |
343 ImGuiTableFlags_BordersV |
344 ImGuiTableFlags_BordersOuter |
345 ImGuiTableFlags_Resizable |
346 ImGuiTableFlags_Sortable |
347 ImGuiTableFlags_Hideable |
348 ImGuiTableFlags_Reorderable |
349 ImGuiTableFlags_ContextMenuInBody |
350 ImGuiTableFlags_SizingStretchProp;
352 flags |= ImGuiTableFlags_ScrollY
353 | ImGuiTableFlags_ScrollX;
355 const auto& style = ImGui::GetStyle();
356 auto width = style.ItemSpacing.x + 2.0f * style.FramePadding.x +
ImGui::CalcTextSize(
"Remove").x;
357 bool disableRemove =
true;
359 int lastDrawnRow = -1;
360 im::Table(
"items", 5, flags, {-width, 0}, [&]{
361 ImGui::TableSetupScrollFreeze(0, 1);
362 ImGui::TableSetupColumn(
"Enable", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoSort);
363 int typeFlags = isWatchPoint ? ImGuiTableColumnFlags_NoHide : ImGuiTableColumnFlags_Disabled;
364 ImGui::TableSetupColumn(
"Type", typeFlags);
365 int addressFlags = hasAddress ? ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_DefaultSort
366 : ImGuiTableColumnFlags_Disabled;
367 ImGui::TableSetupColumn(
"Address", addressFlags);
368 ImGui::TableSetupColumn(
"Condition", isCondition ? ImGuiTableColumnFlags_NoHide : 0);
369 ImGui::TableSetupColumn(
"Action", addr ? 0 : ImGuiTableColumnFlags_DefaultHide);
370 ImGui::TableHeadersRow();
375 if (!addr || (items[row].addr == addr)) {
376 ++count; lastDrawnRow = row;
377 if (row == selectedRow) disableRemove = false;
378 drawRow<Item>(cpuInterface, debugger, row, items[row]);
382 if (count == 1) disableRemove =
false;
385 if (ImGui::Button(
"Add")) {
395 item.wantEnable =
false;
397 item.addrStr = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
399 items.push_back(std::move(item));
403 if (ImGui::Button(
"Remove")) {
404 int removeRow = (
count == 1) ? lastDrawnRow : selectedRow;
405 auto it = items.begin() + removeRow;
407 remove(tag, cpuInterface, it->id);
416 if (ImGui::Button(
"Clear")) {
417 clear(tag, cpuInterface);
424static const std::vector<BreakPoint>& getOpenMSXItems(BreakPoint*,
const MSXCPUInterface&)
426 return MSXCPUInterface::getBreakPoints();
428static const std::vector<std::shared_ptr<WatchPoint>>& getOpenMSXItems(WatchPoint*,
const MSXCPUInterface& cpuInterface)
430 return cpuInterface.getWatchPoints();
432static const std::vector<DebugCondition>& getOpenMSXItems(DebugCondition*,
const MSXCPUInterface&)
434 return MSXCPUInterface::getConditions();
437[[nodiscard]]
static unsigned getId(
const BreakPoint& bp) {
return bp.getId(); }
438[[nodiscard]]
static unsigned getId(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getId(); }
439[[nodiscard]]
static unsigned getId(
const DebugCondition& cond) {
return cond.getId(); }
441[[nodiscard]]
static uint16_t getAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
442[[nodiscard]]
static uint16_t getAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getBeginAddress()); }
443[[nodiscard]]
static uint16_t getAddress(
const DebugCondition& cond) =
delete;
445[[nodiscard]]
static uint16_t getEndAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
446[[nodiscard]]
static uint16_t getEndAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getEndAddress()); }
447[[nodiscard]]
static uint16_t getEndAddress(
const DebugCondition& cond) =
delete;
449[[nodiscard]]
static TclObject getConditionObj(
const BreakPointBase& bp) {
return bp.getConditionObj(); }
450[[nodiscard]]
static TclObject getConditionObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getConditionObj(); }
452[[nodiscard]]
static TclObject getCommandObj(
const BreakPointBase& bp) {
return bp.getCommandObj(); }
453[[nodiscard]]
static TclObject getCommandObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getCommandObj(); }
456template<
typename Item>
457void ImGuiBreakPoints::syncFromOpenMsx(std::vector<GuiItem>& items, MSXCPUInterface& cpuInterface)
459 constexpr bool hasAddress = HasAddress<Item>{};
460 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
464 const auto& openMsxItems = getOpenMSXItems(tag, cpuInterface);
465 std::erase_if(items, [&](
auto& item) {
467 if (
id < 0)
return false;
468 bool remove = !
contains(openMsxItems,
unsigned(
id), [](
const auto& i) {
return getId(i); });
474 for (
const auto& item : openMsxItems) {
475 auto formatAddr = [&](uint16_t addr) {
476 if (
auto syms = symbolManager.lookupValue(addr); !syms.empty()) {
477 return TclObject(syms.front()->name);
479 return TclObject(
tmpStrCat(
"0x", hex_string<4>(addr)));
481 if (
auto it =
ranges::find(items, narrow<int>(getId(item)), &GuiItem::id);
484 if constexpr (isWatchPoint) {
487 if constexpr (hasAddress) {
489 auto addr = getAddress(item);
490 auto endAddr = getEndAddress(item);
492 (*it->addr != addr) ||
493 (it->endAddr && (it->endAddr != endAddr)) ||
494 (!it->endAddr && (addr != endAddr));
497 it->endAddr = (addr != endAddr) ? std::optional<uint16_t>(endAddr) : std::nullopt;
498 it->addrStr = formatAddr(addr);
499 it->endAddrStr = (addr != endAddr) ? formatAddr(endAddr) : TclObject{};
504 it->cond = getConditionObj(item);
505 it->cmd = getCommandObj(item);
508 WatchPoint::Type wpType = WatchPoint::Type::WRITE_MEM;
509 std::optional<uint16_t> addr;
510 std::optional<uint16_t> endAddr;
512 TclObject endAddrStr;
513 if constexpr (isWatchPoint) {
514 wpType = item->getType();
516 if constexpr (hasAddress) {
517 addr = getAddress(item);
518 endAddr = getEndAddress(item);
519 if (*addr == *endAddr) endAddr.reset();
520 addrStr = formatAddr(*addr);
521 if (endAddr) endAddrStr = formatAddr(*endAddr);
523 items.push_back(GuiItem{
524 narrow<int>(getId(item)),
527 addr, endAddr, std::move(addrStr), std::move(endAddrStr),
528 getConditionObj(item), getCommandObj(item)});
534void ImGuiBreakPoints::checkSort(std::vector<GuiItem>& items)
const
536 auto* sortSpecs = ImGui::TableGetSortSpecs();
537 if (!sortSpecs->SpecsDirty)
return;
539 sortSpecs->SpecsDirty =
false;
540 assert(sortSpecs->SpecsCount == 1);
541 assert(sortSpecs->Specs);
542 assert(sortSpecs->Specs->SortOrder == 0);
544 switch (sortSpecs->Specs->ColumnIndex) {
550 return std::tuple(item.addr, item.endAddr,
551 item.addrStr.getString(),
552 item.endAddrStr.getString());
556 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cond.getString(); });
559 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cmd.getString(); });
566std::optional<uint16_t> ImGuiBreakPoints::parseAddress(
const TclObject& o)
568 return symbolManager.parseSymbolOrValue(o.getString());
571template<
typename Item>
572static bool isValidAddr(
const ImGuiBreakPoints::GuiItem& i)
574 constexpr bool hasAddress = HasAddress<Item>{};
575 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
577 if (!hasAddress)
return true;
578 if (!i.addr)
return false;
580 if (i.endAddr && (*i.endAddr < *i.addr))
return false;
581 if ((WatchPoint::Type(i.wpType) ==
one_of(WatchPoint::Type::READ_IO, WatchPoint::Type::WRITE_IO)) &&
582 ((*i.addr >= 0x100) || (i.endAddr && (*i.endAddr >= 0x100)))) {
589template<
typename Item>
590static bool isValidCond(std::string_view cond, Interpreter& interp)
592 if (cond.empty())
return AllowEmptyCond<Item>{};
593 return interp.validExpression(cond);
596static bool isValidCmd(std::string_view cmd, Interpreter& interp)
598 return !cmd.empty() && interp.validCommand(cmd);
601static void create(BreakPoint*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
603 BreakPoint newBp(*item.addr, item.cmd, item.cond,
false);
604 item.id = narrow<int>(newBp.getId());
605 cpuInterface.insertBreakPoint(std::move(newBp));
607static void create(WatchPoint*, MSXCPUInterface&, Debugger& debugger, ImGuiBreakPoints::GuiItem& item)
609 item.id = debugger.setWatchPoint(
611 static_cast<WatchPoint::Type
>(item.wpType),
612 *item.addr, (item.endAddr ? *item.endAddr : *item.addr),
615static void create(DebugCondition*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
617 DebugCondition newCond(item.cmd, item.cond,
false);
618 item.id = narrow<int>(newCond.getId());
619 cpuInterface.setCondition(std::move(newCond));
622template<
typename Item>
623void ImGuiBreakPoints::syncToOpenMsx(
624 MSXCPUInterface& cpuInterface, Debugger& debugger,
625 Interpreter& interp, GuiItem& item)
const
631 remove(tag, cpuInterface, item.id);
632 item.id = --idCounter;
634 if (item.wantEnable &&
635 isValidAddr<Item>(item) &&
636 isValidCond<Item>(item.cond.getString(), interp) &&
637 isValidCmd(item.cmd.getString(), interp)) {
639 create(tag, cpuInterface, debugger, item);
644template<
typename Item>
645void ImGuiBreakPoints::drawRow(MSXCPUInterface& cpuInterface, Debugger& debugger,
int row, GuiItem& item)
647 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
650 auto& interp = manager.getInterpreter();
651 const auto& style = ImGui::GetStyle();
652 float rowHeight = 2.0f * style.FramePadding.y + ImGui::GetTextLineHeight();
654 auto setRedBg = [](
bool valid) {
656 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,
getColor(imColor::RED_BG));
659 bool needSync =
false;
660 std::string cond{item.cond.getString()};
661 std::string cmd {item.cmd .getString()};
662 bool validAddr = isValidAddr<Item>(item);
663 bool validCond = isValidCond<Item>(cond, interp);
664 bool validCmd = isValidCmd(cmd, interp);
666 if (ImGui::TableNextColumn()) {
667 auto pos = ImGui::GetCursorPos();
668 if (ImGui::Selectable(
"##selection", selectedRow == row,
669 ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap,
670 {0.0f, rowHeight})) {
673 ImGui::SetCursorPos(pos);
674 im::Disabled(!validAddr || !validCond || !validCmd, [&]{
675 if (ImGui::Checkbox(
"##enabled", &item.wantEnable)) {
678 if (ImGui::IsItemActive()) selectedRow = row;
681 if (ImGui::TableNextColumn()) {
682 ImGui::SetNextItemWidth(-FLT_MIN);
683 if (ImGui::Combo(
"##type", &item.wpType,
"read IO\000write IO\000read memory\000write memory\000")) {
684 validAddr = isValidAddr<Item>(item);
687 if (ImGui::IsItemActive()) selectedRow = row;
689 if (ImGui::TableNextColumn()) {
690 auto addrToolTip = [&]{
691 if (!item.addr)
return;
693 auto tip =
strCat(
"0x", hex_string<4>(*item.addr));
695 strAppend(tip,
"...0x", hex_string<4>(*item.endAddr));
701 bool addrChanged =
false;
702 std::string addr{item.addrStr.getString()};
703 std::string endAddr{item.endAddrStr.getString()};
704 ImGui::SetNextItemWidth(-FLT_MIN);
705 if constexpr (isWatchPoint) {
706 auto pos = ImGui::GetCursorPos();
707 std::string displayAddr = addr;
708 if (!endAddr.empty()) {
712 ImGui::TextUnformatted(displayAddr);
715 ImGui::SetCursorPos(pos);
716 if (ImGui::InvisibleButton(
"##range-button", {-FLT_MIN, rowHeight})) {
717 ImGui::OpenPopup(
"range-popup");
719 if (ImGui::IsItemActive()) selectedRow = row;
721 addrChanged |= editRange(addr, endAddr);
724 assert(endAddr.empty());
726 addrChanged |= ImGui::InputText(
"##addr", &addr);
730 if (ImGui::MenuItem(
"Show in Dissassembly",
nullptr,
nullptr, item.addr.has_value())) {
731 manager.debugger->setGotoTarget(*item.addr);
736 if (ImGui::IsItemActive()) selectedRow = row;
740 item.endAddrStr = endAddr;
741 item.addr = parseAddress(item.addrStr);
742 item.endAddr = parseAddress(item.endAddrStr);
743 if (item.endAddr && !item.addr) item.endAddr.reset();
747 if (ImGui::TableNextColumn()) {
749 auto checkCmd = getCheckCmd(tag);
750 ParsedSlotCond slot(checkCmd, cond);
751 auto pos = ImGui::GetCursorPos();
753 ImGui::TextUnformatted(slot.toDisplayString());
755 ImGui::SetCursorPos(pos);
756 if (ImGui::InvisibleButton(
"##cond-button", {-FLT_MIN, rowHeight})) {
757 ImGui::OpenPopup(
"cond-popup");
759 if (ImGui::IsItemActive()) selectedRow = row;
761 if (editCondition(slot)) {
762 cond = slot.toTclExpression(checkCmd);
768 if (ImGui::TableNextColumn()) {
771 ImGui::SetNextItemWidth(-FLT_MIN);
772 if (ImGui::InputText(
"##cmd", &cmd)) {
776 if (ImGui::IsItemActive()) selectedRow = row;
780 syncToOpenMsx<Item>(cpuInterface, debugger, interp, item);
784bool ImGuiBreakPoints::editRange(std::string&
begin, std::string&
end)
786 bool changed =
false;
789 const auto& style = ImGui::GetStyle();
790 auto pos = ImGui::GetCursorPos().x +
ImGui::CalcTextSize(
"end: (?)").x + 2.0f * style.ItemSpacing.x;
792 ImGui::AlignTextToFramePadding();
794 ImGui::SameLine(pos);
796 changed |= ImGui::InputText(
"##begin", &begin);
799 ImGui::AlignTextToFramePadding();
801 HelpMarker(
"End address is included in the range.\n"
802 "Leave empty for a single address.");
803 ImGui::SameLine(pos);
805 changed |= ImGui::InputText(
"##end", &end);
811bool ImGuiBreakPoints::editCondition(ParsedSlotCond& slot)
813 bool changed =
false;
816 const auto& style = ImGui::GetStyle();
817 auto pos = ImGui::GetCursorPos().x + ImGui::GetFrameHeight() +
820 changed |= ImGui::Checkbox(
"primary", &slot.hasPs);
821 ImGui::SameLine(pos);
823 changed |= ImGui::Combo(
"##ps", &slot.ps,
"0\0001\0002\0003\000");
825 changed |= ImGui::Checkbox(
"secondary", &slot.hasSs);
826 ImGui::SameLine(pos);
827 im::Disabled(!slot.hasSs, [&]{
828 changed |= ImGui::Combo(
"##ss", &slot.ss,
"0\0001\0002\0003\000");
831 changed |= ImGui::Checkbox(
"segment", &slot.hasSeg);
832 ImGui::SameLine(pos);
835 changed |= ImGui::InputScalar(
"##seg", ImGuiDataType_U8, &slot.seg, &one);
842 ImGui::SetNextItemWidth(-FLT_MIN);
843 changed |= ImGui::InputText(
"##cond", &slot.rest);
849void ImGuiBreakPoints::refreshSymbols()
851 refresh<BreakPoint>(guiBps);
852 refresh<WatchPoint>(guiWps);
856template<
typename Item>
857void ImGuiBreakPoints::refresh(std::vector<GuiItem>& items)
860 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
862 auto* motherBoard = manager.getReactor().getMotherBoard();
863 if (!motherBoard)
return;
865 for (
auto& item : items) {
867 auto adjust = [&](std::optional<uint16_t>& addr,
TclObject& str) {
870 if (
auto newAddr = parseAddress(str)) {
872 if (*newAddr != *addr) {
878 auto s = str.getString();
879 if ((s.size() == 6) && s.starts_with(
"0x")) {
880 if (
auto newSyms = symbolManager.lookupValue(*addr); !newSyms.empty()) {
881 str = newSyms.front()->name;
888 str = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
893 if (
auto newAddr = parseAddress(str)) {
900 adjust(item.addr, item.addrStr);
902 adjust(item.endAddr, item.endAddrStr);
905 auto& cpuInterface = motherBoard->getCPUInterface();
906 auto& debugger = motherBoard->getDebugger();
907 auto& interp = manager.getInterpreter();
908 syncToOpenMsx<Item>(cpuInterface, debugger, interp, item);
Base class for CPU breakpoints.
General debugger condition Like breakpoints, but not tied to a specific address.
ImGuiBreakPoints(ImGuiManager &manager)
void paintBpTab(MSXCPUInterface &cpuInterface, Debugger &debugger, uint16_t addr)
void save(ImGuiTextBuffer &buf) override
void loadLine(std::string_view name, zstring_view value) override
void paint(MSXMotherBoard *motherBoard) override
void loadStart() override
Interpreter & getInterpreter()
void removeBreakPoint(const BreakPoint &bp)
MSXCPUInterface & getCPUInterface()
MSXMotherBoard * getMotherBoard() const
Base class for CPU breakpoints.
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
constexpr const char * c_str() const
auto CalcTextSize(std::string_view str)
void TextUnformatted(const std::string &str)
void Table(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width, std::invocable<> auto next)
void Window(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
void PopupContextItem(const char *str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
void TabBar(const char *str_id, ImGuiTabBarFlags flags, std::invocable<> auto next)
void Disabled(bool b, std::invocable<> auto next)
void Group(std::invocable<> auto next)
void Font(ImFont *font, std::invocable<> auto next)
void TabItem(const char *label, bool *p_open, ImGuiTabItemFlags flags, std::invocable<> auto next)
void Indent(float indent_w, std::invocable<> auto next)
void Popup(const char *str_id, ImGuiWindowFlags flags, std::invocable<> auto next)
void ID_for_range(std::integral auto count, std::invocable< int > auto next)
std::unique_ptr< IDEDevice > create(const DeviceConfig &config)
This file implemented 3 utility functions:
bool loadOnePersistent(std::string_view name, zstring_view value, C &c, const std::tuple< Elements... > &tup)
void sortUpDown_String(Range &range, const ImGuiTableSortSpecs *sortSpecs, Projection proj)
void simpleToolTip(std::string_view desc)
void savePersistent(ImGuiTextBuffer &buf, C &c, const std::tuple< Elements... > &tup)
void sortUpDown_T(Range &range, const ImGuiTableSortSpecs *sortSpecs, Projection proj)
void HelpMarker(std::string_view desc)
ImU32 getColor(imColor col)
TclObject makeTclList(Args &&... args)
auto count(InputRange &&range, const T &value)
auto find(InputRange &&range, const T &value)
constexpr auto to_underlying(E e) noexcept
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
TemporaryString tmpStrCat(Ts &&... ts)
void strAppend(std::string &result, Ts &&...ts)
std::string toDisplayString() const
std::string toTclExpression(std::string_view checkCmd) const
ParsedSlotCond(std::string_view checkCmd, std::string_view cond)
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)