27#include <imgui_stdlib.h>
33using namespace std::literals;
40 , symbolManager(manager.getReactor().getSymbolManager())
44static void saveItems(
zstring_view label,
const std::vector<ImGuiBreakPoints::GuiItem>& items, ImGuiTextBuffer& buf)
46 auto saveAddr = [](std::optional<uint16_t> addr) {
49 for (
const auto& item : items) {
54 saveAddr(item.endAddr),
59 buf.appendf(
"%s=%s\n", label.
c_str(), list.getString().c_str());
66 saveItems(
"breakpoint", guiBps, buf);
67 saveItems(
"watchpoint", guiWps, buf);
68 saveItems(
"condition", guiConditions, buf);
71template<
typename Item>
76 auto loadAddr = [&](
const TclObject& o) -> std::optional<uint16_t> {
77 if (o.getString().empty())
return {};
78 return o.getInt(interp);
82 TclObject list(value);
83 if (list.getListLength(interp) != 8)
return;
86 .wantEnable = list.getListIndex(interp, 0).getBoolean(interp),
87 .wpType = list.getListIndex(interp, 1).getInt(interp),
88 .addr = loadAddr(list.getListIndex(interp, 2)),
89 .endAddr = loadAddr(list.getListIndex(interp, 3)),
90 .addrStr = list.getListIndex(interp, 4),
91 .endAddrStr = list.getListIndex(interp, 5),
92 .cond = list.getListIndex(interp, 6),
93 .cmd = list.getListIndex(interp, 7),
95 if (item.wpType < 0 || item.wpType > 3)
return;
98 auto& items = getItems(tag);
99 items.push_back(std::move(item));
102 auto& cpuInterface = motherBoard->getCPUInterface();
103 auto& debugger = motherBoard->getDebugger();
104 syncToOpenMsx<Item>(cpuInterface, debugger, interp, items.back());
106 }
catch (CommandException&) {
114 auto& cpuInterface = motherBoard->getCPUInterface();
115 clear(
static_cast<BreakPoint *
>(
nullptr), cpuInterface);
116 clear(
static_cast<WatchPoint *
>(
nullptr), cpuInterface);
125 }
else if (name ==
"breakpoint"sv) {
126 loadItem<BreakPoint>(value);
127 }
else if (name ==
"watchpoint"sv) {
128 loadItem<WatchPoint>(value);
129 }
else if (name ==
"condition"sv) {
130 loadItem<DebugCondition>(value);
141 if (!
show || !motherBoard)
return;
143 ImGui::SetNextWindowSize(
gl::vec2{25, 14} * ImGui::GetFontSize(), ImGuiCond_FirstUseEver);
149 paintTab<BreakPoint>(cpuInterface, debugger);
152 paintTab<WatchPoint>(cpuInterface, debugger);
155 paintTab<DebugCondition>(cpuInterface, debugger);
161static std::string_view getCheckCmd(
BreakPoint*) {
return "pc_in_slot"; }
162static std::string_view getCheckCmd(WatchPoint*) {
return "watch_in_slot"; }
163static std::string_view getCheckCmd(DebugCondition*) {
return "pc_in_slot"; }
169 auto end = cond.size();
170 std::optional<int> o_ps;
171 std::optional<int> o_ss;
172 std::optional<int> o_seg;
174 auto next = [&](std::string_view s) {
175 if (cond.substr(pos).starts_with(s)) {
182 bool stop = cond.substr(pos) ==
"]";
183 if (stop || (next(
"] && (") && cond.ends_with(
')'))) {
187 rest = cond.substr(pos, cond.size() - pos - 1);
189 if (o_ps) {
hasPs =
true;
ps = *o_ps; }
190 if (o_ss) {
hasSs =
true;
ss = *o_ss; }
191 if (o_seg) {
hasSeg =
true;
seg = narrow<uint8_t>(*o_seg); }
196 auto isDigit = [](
char c) {
return (
'0' <= c) && (c <=
'9'); };
197 auto getInt = [&](
unsigned max) -> std::optional<int> {
199 if ((pos ==
end) || !isDigit(cond[pos]))
return {};
200 while ((pos !=
end) && isDigit(cond[pos])) {
201 i = 10 * i + (cond[pos] -
'0');
204 if (i >= max)
return {};
208 if (!next(
tmpStrCat(
'[', checkCmd,
' ')))
return;
212 if (!next(
" "))
return;
218 if (!next(
" "))
return;
228 std::string result =
strCat(
'[', checkCmd,
' ',
ps);
247 std::string result =
strCat(
"Slot:",
ps,
'-');
262template<
typename Item>
struct HasAddress : std::true_type {};
272static void remove(WatchPoint*, MSXCPUInterface& cpuInterface,
unsigned id)
274 cpuInterface.removeWatchPoint(
id);
276static void remove(DebugCondition*, MSXCPUInterface& cpuInterface,
unsigned id)
278 cpuInterface.removeCondition(
id);
281void ImGuiBreakPoints::clear(BreakPoint* tag, MSXCPUInterface& cpuInterface)
283 while (!guiBps.empty()) {
284 if (
const auto& bp = guiBps.back(); bp.id > 0) {
285 remove(tag, cpuInterface, bp.id);
290void ImGuiBreakPoints::clear(WatchPoint* tag, MSXCPUInterface& cpuInterface)
292 while (!guiWps.empty()) {
293 if (
auto& wp = guiWps.back(); wp.id > 0) {
294 remove(tag, cpuInterface, wp.id);
300void ImGuiBreakPoints::clear(DebugCondition* tag, MSXCPUInterface& cpuInterface)
302 while (!guiConditions.empty()) {
303 if (
auto& cond = guiConditions.back(); cond.id > 0) {
304 remove(tag, cpuInterface, cond.id);
306 guiConditions.pop_back();
312 paintTab<BreakPoint>(cpuInterface, debugger, addr);
315template<
typename Item>
316void ImGuiBreakPoints::paintTab(
MSXCPUInterface& cpuInterface,
Debugger& debugger, std::optional<uint16_t> addr)
318 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
319 constexpr bool isCondition = std::is_same_v<Item, DebugCondition>;
322 auto& items = getItems(tag);
324 int flags = ImGuiTableFlags_RowBg |
325 ImGuiTableFlags_BordersV |
326 ImGuiTableFlags_BordersOuter |
327 ImGuiTableFlags_Resizable |
328 ImGuiTableFlags_Sortable |
329 ImGuiTableFlags_Hideable |
330 ImGuiTableFlags_Reorderable |
331 ImGuiTableFlags_ContextMenuInBody |
332 ImGuiTableFlags_SizingStretchProp;
334 flags |= ImGuiTableFlags_ScrollY
335 | ImGuiTableFlags_ScrollX;
337 const auto& style = ImGui::GetStyle();
338 auto width = style.ItemSpacing.x + 2.0f * style.FramePadding.x +
ImGui::CalcTextSize(
"Remove").x;
339 bool disableRemove =
true;
341 int lastDrawnRow = -1;
342 im::Table(
"items", 5, flags, {-width, 0}, [&]{
343 syncFromOpenMsx<Item>(items, cpuInterface);
345 ImGui::TableSetupScrollFreeze(0, 1);
346 ImGui::TableSetupColumn(
"Enable", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoSort);
347 int typeFlags = isWatchPoint ? ImGuiTableColumnFlags_NoHide : ImGuiTableColumnFlags_Disabled;
348 ImGui::TableSetupColumn(
"Type", typeFlags);
349 int addressFlags = hasAddress ? ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_DefaultSort
350 : ImGuiTableColumnFlags_Disabled;
351 ImGui::TableSetupColumn(
"Address", addressFlags);
352 ImGui::TableSetupColumn(
"Condition", isCondition ? ImGuiTableColumnFlags_NoHide : 0);
353 ImGui::TableSetupColumn(
"Action", addr ? 0 : ImGuiTableColumnFlags_DefaultHide);
354 ImGui::TableHeadersRow();
359 if (!addr || (items[row].addr == addr)) {
360 ++count; lastDrawnRow = row;
361 if (row == selectedRow) disableRemove = false;
362 drawRow<Item>(cpuInterface, debugger, row, items[row]);
366 if (count == 1) disableRemove =
false;
369 if (ImGui::Button(
"Add")) {
379 item.wantEnable =
false;
381 item.addrStr = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
383 items.push_back(std::move(item));
387 if (ImGui::Button(
"Remove")) {
388 int removeRow = (
count == 1) ? lastDrawnRow : selectedRow;
389 auto it = items.begin() + removeRow;
391 remove(tag, cpuInterface, it->id);
400 if (ImGui::Button(
"Clear")) {
401 clear(tag, cpuInterface);
408static const std::vector<BreakPoint>& getOpenMSXItems(BreakPoint*,
const MSXCPUInterface&)
410 return MSXCPUInterface::getBreakPoints();
412static const std::vector<std::shared_ptr<WatchPoint>>& getOpenMSXItems(WatchPoint*,
const MSXCPUInterface& cpuInterface)
414 return cpuInterface.getWatchPoints();
416static const std::vector<DebugCondition>& getOpenMSXItems(DebugCondition*,
const MSXCPUInterface&)
418 return MSXCPUInterface::getConditions();
421[[nodiscard]]
static unsigned getId(
const BreakPoint& bp) {
return bp.getId(); }
422[[nodiscard]]
static unsigned getId(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getId(); }
423[[nodiscard]]
static unsigned getId(
const DebugCondition& cond) {
return cond.getId(); }
425[[nodiscard]]
static uint16_t getAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
426[[nodiscard]]
static uint16_t getAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getBeginAddress()); }
427[[nodiscard]]
static uint16_t getAddress(
const DebugCondition& cond) =
delete;
429[[nodiscard]]
static uint16_t getEndAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
430[[nodiscard]]
static uint16_t getEndAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getEndAddress()); }
431[[nodiscard]]
static uint16_t getEndAddress(
const DebugCondition& cond) =
delete;
433[[nodiscard]]
static TclObject getConditionObj(
const BreakPointBase& bp) {
return bp.getConditionObj(); }
434[[nodiscard]]
static TclObject getConditionObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getConditionObj(); }
436[[nodiscard]]
static TclObject getCommandObj(
const BreakPointBase& bp) {
return bp.getCommandObj(); }
437[[nodiscard]]
static TclObject getCommandObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getCommandObj(); }
440[[nodiscard]] std::vector<ImGuiBreakPoints::GuiItem>& ImGuiBreakPoints::getBps(
MSXCPUInterface& cpuInterface)
442 syncFromOpenMsx<BreakPoint>(guiBps, cpuInterface);
446template<
typename Item>
447void ImGuiBreakPoints::syncFromOpenMsx(std::vector<GuiItem>& items,
MSXCPUInterface& cpuInterface)
450 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
454 const auto& openMsxItems = getOpenMSXItems(tag, cpuInterface);
455 std::erase_if(items, [&](
auto& item) {
457 if (
id < 0)
return false;
458 bool remove = !
contains(openMsxItems,
unsigned(
id), [](
const auto& i) {
return getId(i); });
464 for (
const auto& item : openMsxItems) {
465 auto formatAddr = [&](uint16_t addr) {
466 if (
auto syms = symbolManager.lookupValue(addr); !syms.empty()) {
467 return TclObject(syms.front()->name);
469 return TclObject(
tmpStrCat(
"0x", hex_string<4>(addr)));
471 if (
auto it =
ranges::find(items, narrow<int>(getId(item)), &GuiItem::id);
474 if constexpr (isWatchPoint) {
477 if constexpr (hasAddress) {
479 auto addr = getAddress(item);
480 auto endAddr = getEndAddress(item);
482 (*it->addr != addr) ||
483 (it->endAddr && (it->endAddr != endAddr)) ||
484 (!it->endAddr && (addr != endAddr));
487 it->endAddr = (addr != endAddr) ? std::optional<uint16_t>(endAddr) : std::nullopt;
488 it->addrStr = formatAddr(addr);
489 it->endAddrStr = (addr != endAddr) ? formatAddr(endAddr) : TclObject{};
494 it->cond = getConditionObj(item);
495 it->cmd = getCommandObj(item);
498 WatchPoint::Type wpType = WatchPoint::Type::WRITE_MEM;
499 std::optional<uint16_t> addr;
500 std::optional<uint16_t> endAddr;
502 TclObject endAddrStr;
503 if constexpr (isWatchPoint) {
504 wpType = item->getType();
506 if constexpr (hasAddress) {
507 addr = getAddress(item);
508 endAddr = getEndAddress(item);
509 if (*addr == *endAddr) endAddr.reset();
510 addrStr = formatAddr(*addr);
511 if (endAddr) endAddrStr = formatAddr(*endAddr);
513 items.push_back(GuiItem{
514 narrow<int>(getId(item)),
517 addr, endAddr, std::move(addrStr), std::move(endAddrStr),
518 getConditionObj(item), getCommandObj(item)});
524void ImGuiBreakPoints::checkSort(std::vector<GuiItem>& items)
const
526 auto* sortSpecs = ImGui::TableGetSortSpecs();
527 if (!sortSpecs->SpecsDirty)
return;
529 sortSpecs->SpecsDirty =
false;
530 assert(sortSpecs->SpecsCount == 1);
531 assert(sortSpecs->Specs);
532 assert(sortSpecs->Specs->SortOrder == 0);
534 switch (sortSpecs->Specs->ColumnIndex) {
540 return std::tuple(item.addr, item.endAddr,
541 item.addrStr.getString(),
542 item.endAddrStr.getString());
546 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cond.getString(); });
549 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cmd.getString(); });
556std::optional<uint16_t> ImGuiBreakPoints::parseAddress(
const TclObject& o)
558 return symbolManager.parseSymbolOrValue(o.getString());
561template<
typename Item>
562static bool isValidAddr(
const ImGuiBreakPoints::GuiItem& i)
564 constexpr bool hasAddress = HasAddress<Item>{};
565 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
567 if (!hasAddress)
return true;
568 if (!i.addr)
return false;
570 if (i.endAddr && (*i.endAddr < *i.addr))
return false;
571 if ((WatchPoint::Type(i.wpType) ==
one_of(WatchPoint::Type::READ_IO, WatchPoint::Type::WRITE_IO)) &&
572 ((*i.addr >= 0x100) || (i.endAddr && (*i.endAddr >= 0x100)))) {
579template<
typename Item>
580static bool isValidCond(std::string_view cond, Interpreter& interp)
582 if (cond.empty())
return AllowEmptyCond<Item>{};
583 return interp.validExpression(cond);
586static bool isValidCmd(std::string_view cmd, Interpreter& interp)
588 return !cmd.empty() && interp.validCommand(cmd);
591static void create(BreakPoint*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
593 BreakPoint newBp(*item.addr, item.cmd, item.cond,
false);
594 item.id = narrow<int>(newBp.getId());
595 cpuInterface.insertBreakPoint(std::move(newBp));
597static void create(WatchPoint*, MSXCPUInterface&, Debugger& debugger, ImGuiBreakPoints::GuiItem& item)
599 item.id = debugger.setWatchPoint(
601 static_cast<WatchPoint::Type
>(item.wpType),
602 *item.addr, (item.endAddr ? *item.endAddr : *item.addr),
605static void create(DebugCondition*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
607 DebugCondition newCond(item.cmd, item.cond,
false);
608 item.id = narrow<int>(newCond.getId());
609 cpuInterface.setCondition(std::move(newCond));
612template<
typename Item>
613void ImGuiBreakPoints::syncToOpenMsx(
614 MSXCPUInterface& cpuInterface, Debugger& debugger,
615 Interpreter& interp, GuiItem& item)
const
621 remove(tag, cpuInterface, item.id);
622 item.id = --idCounter;
624 if (item.wantEnable &&
625 isValidAddr<Item>(item) &&
626 isValidCond<Item>(item.cond.getString(), interp) &&
627 isValidCmd(item.cmd.getString(), interp)) {
629 create(tag, cpuInterface, debugger, item);
634template<
typename Item>
635void ImGuiBreakPoints::drawRow(MSXCPUInterface& cpuInterface, Debugger& debugger,
int row, GuiItem& item)
637 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
640 auto& interp = manager.getInterpreter();
641 const auto& style = ImGui::GetStyle();
642 float rowHeight = 2.0f * style.FramePadding.y + ImGui::GetTextLineHeight();
644 auto setRedBg = [](
bool valid) {
646 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,
getColor(imColor::RED_BG));
649 bool needSync =
false;
650 std::string cond{item.cond.getString()};
651 std::string cmd {item.cmd .getString()};
652 bool validAddr = isValidAddr<Item>(item);
653 bool validCond = isValidCond<Item>(cond, interp);
654 bool validCmd = isValidCmd(cmd, interp);
656 if (ImGui::TableNextColumn()) {
657 auto pos = ImGui::GetCursorPos();
658 if (ImGui::Selectable(
"##selection", selectedRow == row,
659 ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap,
660 {0.0f, rowHeight})) {
663 ImGui::SetCursorPos(pos);
664 im::Disabled(!validAddr || !validCond || !validCmd, [&]{
665 if (ImGui::Checkbox(
"##enabled", &item.wantEnable)) {
668 if (ImGui::IsItemActive()) selectedRow = row;
671 if (ImGui::TableNextColumn()) {
672 ImGui::SetNextItemWidth(-FLT_MIN);
673 if (ImGui::Combo(
"##type", &item.wpType,
"read IO\000write IO\000read memory\000write memory\000")) {
674 validAddr = isValidAddr<Item>(item);
677 if (ImGui::IsItemActive()) selectedRow = row;
679 if (ImGui::TableNextColumn()) {
680 auto addrToolTip = [&]{
681 if (!item.addr)
return;
683 auto tip =
strCat(
"0x", hex_string<4>(*item.addr));
685 strAppend(tip,
"...0x", hex_string<4>(*item.endAddr));
691 bool addrChanged =
false;
692 std::string addr{item.addrStr.getString()};
693 std::string endAddr{item.endAddrStr.getString()};
694 ImGui::SetNextItemWidth(-FLT_MIN);
695 if constexpr (isWatchPoint) {
696 auto pos = ImGui::GetCursorPos();
697 std::string displayAddr = addr;
698 if (!endAddr.empty()) {
702 ImGui::TextUnformatted(displayAddr);
705 ImGui::SetCursorPos(pos);
706 if (ImGui::InvisibleButton(
"##range-button", {-FLT_MIN, rowHeight})) {
707 ImGui::OpenPopup(
"range-popup");
709 if (ImGui::IsItemActive()) selectedRow = row;
711 addrChanged |= editRange(addr, endAddr);
714 assert(endAddr.empty());
716 addrChanged |= ImGui::InputText(
"##addr", &addr);
719 if (ImGui::IsItemActive()) selectedRow = row;
723 item.endAddrStr = endAddr;
724 item.addr = parseAddress(item.addrStr);
725 item.endAddr = parseAddress(item.endAddrStr);
726 if (item.endAddr && !item.addr) item.endAddr.reset();
730 if (ImGui::TableNextColumn()) {
732 auto checkCmd = getCheckCmd(tag);
733 ParsedSlotCond slot(checkCmd, cond);
734 auto pos = ImGui::GetCursorPos();
736 ImGui::TextUnformatted(slot.toDisplayString());
738 ImGui::SetCursorPos(pos);
739 if (ImGui::InvisibleButton(
"##cond-button", {-FLT_MIN, rowHeight})) {
740 ImGui::OpenPopup(
"cond-popup");
742 if (ImGui::IsItemActive()) selectedRow = row;
744 if (editCondition(slot)) {
745 cond = slot.toTclExpression(checkCmd);
751 if (ImGui::TableNextColumn()) {
754 ImGui::SetNextItemWidth(-FLT_MIN);
755 if (ImGui::InputText(
"##cmd", &cmd)) {
759 if (ImGui::IsItemActive()) selectedRow = row;
763 syncToOpenMsx<Item>(cpuInterface, debugger, interp, item);
767bool ImGuiBreakPoints::editRange(std::string&
begin, std::string&
end)
769 bool changed =
false;
772 const auto& style = ImGui::GetStyle();
773 auto pos = ImGui::GetCursorPos().x +
ImGui::CalcTextSize(
"end: (?)").x + 2.0f * style.ItemSpacing.x;
775 ImGui::AlignTextToFramePadding();
777 ImGui::SameLine(pos);
779 changed |= ImGui::InputText(
"##begin", &begin);
782 ImGui::AlignTextToFramePadding();
784 HelpMarker(
"End address is included in the range.\n"
785 "Leave empty for a single address.");
786 ImGui::SameLine(pos);
788 changed |= ImGui::InputText(
"##end", &end);
794bool ImGuiBreakPoints::editCondition(ParsedSlotCond& slot)
796 bool changed =
false;
799 const auto& style = ImGui::GetStyle();
800 auto pos = ImGui::GetCursorPos().x + ImGui::GetFrameHeight() +
803 changed |= ImGui::Checkbox(
"primary", &slot.hasPs);
804 ImGui::SameLine(pos);
806 changed |= ImGui::Combo(
"##ps", &slot.ps,
"0\0001\0002\0003\000");
808 changed |= ImGui::Checkbox(
"secondary", &slot.hasSs);
809 ImGui::SameLine(pos);
810 im::Disabled(!slot.hasSs, [&]{
811 changed |= ImGui::Combo(
"##ss", &slot.ss,
"0\0001\0002\0003\000");
814 changed |= ImGui::Checkbox(
"segment", &slot.hasSeg);
815 ImGui::SameLine(pos);
818 changed |= ImGui::InputScalar(
"##seg", ImGuiDataType_U8, &slot.seg, &one);
825 ImGui::SetNextItemWidth(-FLT_MIN);
826 changed |= ImGui::InputText(
"##cond", &slot.rest);
832void ImGuiBreakPoints::refreshSymbols()
834 refresh<BreakPoint>(guiBps);
835 refresh<WatchPoint>(guiWps);
839template<
typename Item>
840void ImGuiBreakPoints::refresh(std::vector<GuiItem>& items)
843 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
845 auto* motherBoard = manager.getReactor().getMotherBoard();
846 if (!motherBoard)
return;
848 for (
auto& item : items) {
850 auto adjust = [&](std::optional<uint16_t>& addr,
TclObject& str) {
853 if (
auto newAddr = parseAddress(str)) {
855 if (*newAddr != *addr) {
861 auto s = str.getString();
862 if ((s.size() == 6) && s.starts_with(
"0x")) {
863 if (
auto newSyms = symbolManager.lookupValue(*addr); !newSyms.empty()) {
864 str = newSyms.front()->name;
871 str = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
876 if (
auto newAddr = parseAddress(str)) {
883 adjust(item.addr, item.addrStr);
885 adjust(item.endAddr, item.endAddrStr);
888 auto& cpuInterface = motherBoard->getCPUInterface();
889 auto& debugger = motherBoard->getDebugger();
890 auto& interp = manager.getInterpreter();
891 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)
ALWAYS_INLINE unsigned count(const uint8_t *pIn, const uint8_t *pMatch, const uint8_t *pInLimit)
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 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(int 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 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)