27#include <imgui_stdlib.h>
33using namespace std::literals;
40 , symbolManager(manager.getReactor().getSymbolManager())
45static void saveItems(
zstring_view label,
const std::vector<ImGuiBreakPoints::GuiItem>& items, ImGuiTextBuffer& buf)
47 auto saveAddr = [](std::optional<uint16_t> addr) {
50 for (
const auto& item : items) {
55 saveAddr(item.endAddr),
60 buf.appendf(
"%s=%s\n", label.
c_str(), list.getString().c_str());
69 saveItems(
"breakpoint", guiBps, buf);
70 saveItems(
"watchpoint", guiWps, buf);
71 saveItems(
"condition", guiConditions, buf);
76template<
typename Item>
81 auto loadAddr = [&](
const TclObject& o) -> std::optional<uint16_t> {
82 if (o.getString().empty())
return {};
83 return o.getInt(interp);
87 TclObject list(value);
88 if (list.getListLength(interp) != 8)
return;
91 .wantEnable = list.getListIndex(interp, 0).getBoolean(interp),
92 .wpType = list.getListIndex(interp, 1).getInt(interp),
93 .addr = loadAddr(list.getListIndex(interp, 2)),
94 .endAddr = loadAddr(list.getListIndex(interp, 3)),
95 .addrStr = list.getListIndex(interp, 4),
96 .endAddrStr = list.getListIndex(interp, 5),
97 .cond = list.getListIndex(interp, 6),
98 .cmd = list.getListIndex(interp, 7),
100 if (item.wpType < 0 || item.wpType > 3)
return;
103 auto& items = getItems(tag);
104 items.push_back(std::move(item));
107 auto& cpuInterface = motherBoard->getCPUInterface();
108 auto& debugger = motherBoard->getDebugger();
109 syncToOpenMsx<Item>(cpuInterface, debugger, interp, items.back());
111 }
catch (CommandException&) {
121 auto& cpuInterface = motherBoard->getCPUInterface();
122 clear(
static_cast<BreakPoint *
>(
nullptr), cpuInterface);
123 clear(
static_cast<WatchPoint *
>(
nullptr), cpuInterface);
134 }
else if (name ==
"breakpoint"sv) {
135 loadItem<BreakPoint>(value);
136 }
else if (name ==
"watchpoint"sv) {
137 loadItem<WatchPoint>(value);
138 }
else if (name ==
"condition"sv) {
139 loadItem<DebugCondition>(value);
151 if (!motherBoard)
return;
155 syncFromOpenMsx<BreakPoint> (guiBps, cpuInterface);
156 syncFromOpenMsx<WatchPoint> (guiWps, cpuInterface);
157 syncFromOpenMsx<DebugCondition>(guiConditions, cpuInterface);
161 ImGui::SetNextWindowSize(
gl::vec2{25, 14} * ImGui::GetFontSize(), ImGuiCond_FirstUseEver);
166 paintTab<BreakPoint>(cpuInterface, debugger);
169 paintTab<WatchPoint>(cpuInterface, debugger);
172 paintTab<DebugCondition>(cpuInterface, debugger);
178static std::string_view getCheckCmd(
BreakPoint*) {
return "pc_in_slot"; }
179static std::string_view getCheckCmd(WatchPoint*) {
return "watch_in_slot"; }
180static std::string_view getCheckCmd(DebugCondition*) {
return "pc_in_slot"; }
186 auto end = cond.size();
187 std::optional<int> o_ps;
188 std::optional<int> o_ss;
189 std::optional<int> o_seg;
191 auto next = [&](std::string_view s) {
192 if (cond.substr(pos).starts_with(s)) {
199 bool stop = cond.substr(pos) ==
"]";
200 if (stop || (next(
"] && (") && cond.ends_with(
')'))) {
204 rest = cond.substr(pos, cond.size() - pos - 1);
206 if (o_ps) {
hasPs =
true;
ps = *o_ps; }
207 if (o_ss) {
hasSs =
true;
ss = *o_ss; }
208 if (o_seg) {
hasSeg =
true;
seg = narrow<uint8_t>(*o_seg); }
213 auto isDigit = [](
char c) {
return (
'0' <= c) && (c <=
'9'); };
214 auto getInt = [&](
unsigned max) -> std::optional<int> {
216 if ((pos ==
end) || !isDigit(cond[pos]))
return {};
217 while ((pos !=
end) && isDigit(cond[pos])) {
218 i = 10 * i + (cond[pos] -
'0');
221 if (i >= max)
return {};
225 if (!next(
tmpStrCat(
'[', checkCmd,
' ')))
return;
229 if (!next(
" "))
return;
235 if (!next(
" "))
return;
245 std::string result =
strCat(
'[', checkCmd,
' ',
ps);
264 std::string result =
strCat(
"Slot:",
ps,
'-');
279template<
typename Item>
struct HasAddress : std::true_type {};
289static void remove(WatchPoint*, MSXCPUInterface& cpuInterface,
unsigned id)
291 cpuInterface.removeWatchPoint(
id);
293static void remove(DebugCondition*, MSXCPUInterface& cpuInterface,
unsigned id)
295 cpuInterface.removeCondition(
id);
298void ImGuiBreakPoints::clear(BreakPoint* tag, MSXCPUInterface& cpuInterface)
300 while (!guiBps.empty()) {
301 if (
const auto& bp = guiBps.back(); bp.id > 0) {
302 remove(tag, cpuInterface, bp.id);
307void ImGuiBreakPoints::clear(WatchPoint* tag, MSXCPUInterface& cpuInterface)
309 while (!guiWps.empty()) {
310 if (
auto& wp = guiWps.back(); wp.id > 0) {
311 remove(tag, cpuInterface, wp.id);
317void ImGuiBreakPoints::clear(DebugCondition* tag, MSXCPUInterface& cpuInterface)
319 while (!guiConditions.empty()) {
320 if (
auto& cond = guiConditions.back(); cond.id > 0) {
321 remove(tag, cpuInterface, cond.id);
323 guiConditions.pop_back();
329 paintTab<BreakPoint>(cpuInterface, debugger, addr);
332template<
typename Item>
333void ImGuiBreakPoints::paintTab(
MSXCPUInterface& cpuInterface,
Debugger& debugger, std::optional<uint16_t> addr)
335 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
336 constexpr bool isCondition = std::is_same_v<Item, DebugCondition>;
339 auto& items = getItems(tag);
341 int flags = ImGuiTableFlags_RowBg |
342 ImGuiTableFlags_BordersV |
343 ImGuiTableFlags_BordersOuter |
344 ImGuiTableFlags_Resizable |
345 ImGuiTableFlags_Sortable |
346 ImGuiTableFlags_Hideable |
347 ImGuiTableFlags_Reorderable |
348 ImGuiTableFlags_ContextMenuInBody |
349 ImGuiTableFlags_SizingStretchProp;
351 flags |= ImGuiTableFlags_ScrollY
352 | ImGuiTableFlags_ScrollX;
354 const auto& style = ImGui::GetStyle();
355 auto width = style.ItemSpacing.x + 2.0f * style.FramePadding.x +
ImGui::CalcTextSize(
"Remove").x;
356 bool disableRemove =
true;
358 int lastDrawnRow = -1;
359 im::Table(
"items", 5, flags, {-width, 0}, [&]{
360 ImGui::TableSetupScrollFreeze(0, 1);
361 ImGui::TableSetupColumn(
"Enable", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoSort);
362 int typeFlags = isWatchPoint ? ImGuiTableColumnFlags_NoHide : ImGuiTableColumnFlags_Disabled;
363 ImGui::TableSetupColumn(
"Type", typeFlags);
364 int addressFlags = hasAddress ? ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_DefaultSort
365 : ImGuiTableColumnFlags_Disabled;
366 ImGui::TableSetupColumn(
"Address", addressFlags);
367 ImGui::TableSetupColumn(
"Condition", isCondition ? ImGuiTableColumnFlags_NoHide : 0);
368 ImGui::TableSetupColumn(
"Action", addr ? 0 : ImGuiTableColumnFlags_DefaultHide);
369 ImGui::TableHeadersRow();
374 if (!addr || (items[row].addr == addr)) {
375 ++count; lastDrawnRow = row;
376 if (row == selectedRow) disableRemove = false;
377 drawRow<Item>(cpuInterface, debugger, row, items[row]);
381 if (count == 1) disableRemove =
false;
384 if (ImGui::Button(
"Add")) {
394 item.wantEnable =
false;
396 item.addrStr = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
398 items.push_back(std::move(item));
402 if (ImGui::Button(
"Remove")) {
403 int removeRow = (
count == 1) ? lastDrawnRow : selectedRow;
404 auto it = items.begin() + removeRow;
406 remove(tag, cpuInterface, it->id);
415 if (ImGui::Button(
"Clear")) {
416 clear(tag, cpuInterface);
423static const std::vector<BreakPoint>& getOpenMSXItems(BreakPoint*,
const MSXCPUInterface&)
425 return MSXCPUInterface::getBreakPoints();
427static const std::vector<std::shared_ptr<WatchPoint>>& getOpenMSXItems(WatchPoint*,
const MSXCPUInterface& cpuInterface)
429 return cpuInterface.getWatchPoints();
431static const std::vector<DebugCondition>& getOpenMSXItems(DebugCondition*,
const MSXCPUInterface&)
433 return MSXCPUInterface::getConditions();
436[[nodiscard]]
static unsigned getId(
const BreakPoint& bp) {
return bp.getId(); }
437[[nodiscard]]
static unsigned getId(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getId(); }
438[[nodiscard]]
static unsigned getId(
const DebugCondition& cond) {
return cond.getId(); }
440[[nodiscard]]
static uint16_t getAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
441[[nodiscard]]
static uint16_t getAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getBeginAddress()); }
442[[nodiscard]]
static uint16_t getAddress(
const DebugCondition& cond) =
delete;
444[[nodiscard]]
static uint16_t getEndAddress(
const BreakPoint& bp) {
return bp.getAddress(); }
445[[nodiscard]]
static uint16_t getEndAddress(
const std::shared_ptr<WatchPoint>& wp) {
return narrow<uint16_t>(wp->getEndAddress()); }
446[[nodiscard]]
static uint16_t getEndAddress(
const DebugCondition& cond) =
delete;
448[[nodiscard]]
static TclObject getConditionObj(
const BreakPointBase& bp) {
return bp.getConditionObj(); }
449[[nodiscard]]
static TclObject getConditionObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getConditionObj(); }
451[[nodiscard]]
static TclObject getCommandObj(
const BreakPointBase& bp) {
return bp.getCommandObj(); }
452[[nodiscard]]
static TclObject getCommandObj(
const std::shared_ptr<WatchPoint>& wp) {
return wp->getCommandObj(); }
455template<
typename Item>
456void ImGuiBreakPoints::syncFromOpenMsx(std::vector<GuiItem>& items, MSXCPUInterface& cpuInterface)
458 constexpr bool hasAddress = HasAddress<Item>{};
459 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
463 const auto& openMsxItems = getOpenMSXItems(tag, cpuInterface);
464 std::erase_if(items, [&](
auto& item) {
466 if (
id < 0)
return false;
467 bool remove = !
contains(openMsxItems,
unsigned(
id), [](
const auto& i) {
return getId(i); });
473 for (
const auto& item : openMsxItems) {
474 auto formatAddr = [&](uint16_t addr) {
475 if (
auto syms = symbolManager.lookupValue(addr); !syms.empty()) {
476 return TclObject(syms.front()->name);
478 return TclObject(
tmpStrCat(
"0x", hex_string<4>(addr)));
480 if (
auto it =
ranges::find(items, narrow<int>(getId(item)), &GuiItem::id);
483 if constexpr (isWatchPoint) {
486 if constexpr (hasAddress) {
488 auto addr = getAddress(item);
489 auto endAddr = getEndAddress(item);
491 (*it->addr != addr) ||
492 (it->endAddr && (it->endAddr != endAddr)) ||
493 (!it->endAddr && (addr != endAddr));
496 it->endAddr = (addr != endAddr) ? std::optional<uint16_t>(endAddr) : std::nullopt;
497 it->addrStr = formatAddr(addr);
498 it->endAddrStr = (addr != endAddr) ? formatAddr(endAddr) : TclObject{};
503 it->cond = getConditionObj(item);
504 it->cmd = getCommandObj(item);
507 WatchPoint::Type wpType = WatchPoint::Type::WRITE_MEM;
508 std::optional<uint16_t> addr;
509 std::optional<uint16_t> endAddr;
511 TclObject endAddrStr;
512 if constexpr (isWatchPoint) {
513 wpType = item->getType();
515 if constexpr (hasAddress) {
516 addr = getAddress(item);
517 endAddr = getEndAddress(item);
518 if (*addr == *endAddr) endAddr.reset();
519 addrStr = formatAddr(*addr);
520 if (endAddr) endAddrStr = formatAddr(*endAddr);
522 items.push_back(GuiItem{
523 narrow<int>(getId(item)),
526 addr, endAddr, std::move(addrStr), std::move(endAddrStr),
527 getConditionObj(item), getCommandObj(item)});
533void ImGuiBreakPoints::checkSort(std::vector<GuiItem>& items)
const
535 auto* sortSpecs = ImGui::TableGetSortSpecs();
536 if (!sortSpecs->SpecsDirty)
return;
538 sortSpecs->SpecsDirty =
false;
539 assert(sortSpecs->SpecsCount == 1);
540 assert(sortSpecs->Specs);
541 assert(sortSpecs->Specs->SortOrder == 0);
543 switch (sortSpecs->Specs->ColumnIndex) {
549 return std::tuple(item.addr, item.endAddr,
550 item.addrStr.getString(),
551 item.endAddrStr.getString());
555 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cond.getString(); });
558 sortUpDown_String(items, sortSpecs, [](
const auto& item) {
return item.cmd.getString(); });
565std::optional<uint16_t> ImGuiBreakPoints::parseAddress(
const TclObject& o)
567 return symbolManager.parseSymbolOrValue(o.getString());
570template<
typename Item>
571static bool isValidAddr(
const ImGuiBreakPoints::GuiItem& i)
573 constexpr bool hasAddress = HasAddress<Item>{};
574 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
576 if (!hasAddress)
return true;
577 if (!i.addr)
return false;
579 if (i.endAddr && (*i.endAddr < *i.addr))
return false;
580 if ((WatchPoint::Type(i.wpType) ==
one_of(WatchPoint::Type::READ_IO, WatchPoint::Type::WRITE_IO)) &&
581 ((*i.addr >= 0x100) || (i.endAddr && (*i.endAddr >= 0x100)))) {
588template<
typename Item>
589static bool isValidCond(std::string_view cond, Interpreter& interp)
591 if (cond.empty())
return AllowEmptyCond<Item>{};
592 return interp.validExpression(cond);
595static bool isValidCmd(std::string_view cmd, Interpreter& interp)
597 return !cmd.empty() && interp.validCommand(cmd);
600static void create(BreakPoint*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
602 BreakPoint newBp(*item.addr, item.cmd, item.cond,
false);
603 item.id = narrow<int>(newBp.getId());
604 cpuInterface.insertBreakPoint(std::move(newBp));
606static void create(WatchPoint*, MSXCPUInterface&, Debugger& debugger, ImGuiBreakPoints::GuiItem& item)
608 item.id = debugger.setWatchPoint(
610 static_cast<WatchPoint::Type
>(item.wpType),
611 *item.addr, (item.endAddr ? *item.endAddr : *item.addr),
614static void create(DebugCondition*, MSXCPUInterface& cpuInterface, Debugger&, ImGuiBreakPoints::GuiItem& item)
616 DebugCondition newCond(item.cmd, item.cond,
false);
617 item.id = narrow<int>(newCond.getId());
618 cpuInterface.setCondition(std::move(newCond));
621template<
typename Item>
622void ImGuiBreakPoints::syncToOpenMsx(
623 MSXCPUInterface& cpuInterface, Debugger& debugger,
624 Interpreter& interp, GuiItem& item)
const
630 remove(tag, cpuInterface, item.id);
631 item.id = --idCounter;
633 if (item.wantEnable &&
634 isValidAddr<Item>(item) &&
635 isValidCond<Item>(item.cond.getString(), interp) &&
636 isValidCmd(item.cmd.getString(), interp)) {
638 create(tag, cpuInterface, debugger, item);
643template<
typename Item>
644void ImGuiBreakPoints::drawRow(MSXCPUInterface& cpuInterface, Debugger& debugger,
int row, GuiItem& item)
646 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
649 auto& interp = manager.getInterpreter();
650 const auto& style = ImGui::GetStyle();
651 float rowHeight = 2.0f * style.FramePadding.y + ImGui::GetTextLineHeight();
653 auto setRedBg = [](
bool valid) {
655 ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,
getColor(imColor::RED_BG));
658 bool needSync =
false;
659 std::string cond{item.cond.getString()};
660 std::string cmd {item.cmd .getString()};
661 bool validAddr = isValidAddr<Item>(item);
662 bool validCond = isValidCond<Item>(cond, interp);
663 bool validCmd = isValidCmd(cmd, interp);
665 if (ImGui::TableNextColumn()) {
666 auto pos = ImGui::GetCursorPos();
667 if (ImGui::Selectable(
"##selection", selectedRow == row,
668 ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap,
669 {0.0f, rowHeight})) {
672 ImGui::SetCursorPos(pos);
673 im::Disabled(!validAddr || !validCond || !validCmd, [&]{
674 if (ImGui::Checkbox(
"##enabled", &item.wantEnable)) {
677 if (ImGui::IsItemActive()) selectedRow = row;
680 if (ImGui::TableNextColumn()) {
681 ImGui::SetNextItemWidth(-FLT_MIN);
682 if (ImGui::Combo(
"##type", &item.wpType,
"read IO\000write IO\000read memory\000write memory\000")) {
683 validAddr = isValidAddr<Item>(item);
686 if (ImGui::IsItemActive()) selectedRow = row;
688 if (ImGui::TableNextColumn()) {
689 auto addrToolTip = [&]{
690 if (!item.addr)
return;
692 auto tip =
strCat(
"0x", hex_string<4>(*item.addr));
694 strAppend(tip,
"...0x", hex_string<4>(*item.endAddr));
700 bool addrChanged =
false;
701 std::string addr{item.addrStr.getString()};
702 std::string endAddr{item.endAddrStr.getString()};
703 ImGui::SetNextItemWidth(-FLT_MIN);
704 if constexpr (isWatchPoint) {
705 auto pos = ImGui::GetCursorPos();
706 std::string displayAddr = addr;
707 if (!endAddr.empty()) {
711 ImGui::TextUnformatted(displayAddr);
714 ImGui::SetCursorPos(pos);
715 if (ImGui::InvisibleButton(
"##range-button", {-FLT_MIN, rowHeight})) {
716 ImGui::OpenPopup(
"range-popup");
718 if (ImGui::IsItemActive()) selectedRow = row;
720 addrChanged |= editRange(addr, endAddr);
723 assert(endAddr.empty());
725 addrChanged |= ImGui::InputText(
"##addr", &addr);
728 if (ImGui::IsItemActive()) selectedRow = row;
732 item.endAddrStr = endAddr;
733 item.addr = parseAddress(item.addrStr);
734 item.endAddr = parseAddress(item.endAddrStr);
735 if (item.endAddr && !item.addr) item.endAddr.reset();
739 if (ImGui::TableNextColumn()) {
741 auto checkCmd = getCheckCmd(tag);
742 ParsedSlotCond slot(checkCmd, cond);
743 auto pos = ImGui::GetCursorPos();
745 ImGui::TextUnformatted(slot.toDisplayString());
747 ImGui::SetCursorPos(pos);
748 if (ImGui::InvisibleButton(
"##cond-button", {-FLT_MIN, rowHeight})) {
749 ImGui::OpenPopup(
"cond-popup");
751 if (ImGui::IsItemActive()) selectedRow = row;
753 if (editCondition(slot)) {
754 cond = slot.toTclExpression(checkCmd);
760 if (ImGui::TableNextColumn()) {
763 ImGui::SetNextItemWidth(-FLT_MIN);
764 if (ImGui::InputText(
"##cmd", &cmd)) {
768 if (ImGui::IsItemActive()) selectedRow = row;
772 syncToOpenMsx<Item>(cpuInterface, debugger, interp, item);
776bool ImGuiBreakPoints::editRange(std::string&
begin, std::string&
end)
778 bool changed =
false;
781 const auto& style = ImGui::GetStyle();
782 auto pos = ImGui::GetCursorPos().x +
ImGui::CalcTextSize(
"end: (?)").x + 2.0f * style.ItemSpacing.x;
784 ImGui::AlignTextToFramePadding();
786 ImGui::SameLine(pos);
788 changed |= ImGui::InputText(
"##begin", &begin);
791 ImGui::AlignTextToFramePadding();
793 HelpMarker(
"End address is included in the range.\n"
794 "Leave empty for a single address.");
795 ImGui::SameLine(pos);
797 changed |= ImGui::InputText(
"##end", &end);
803bool ImGuiBreakPoints::editCondition(ParsedSlotCond& slot)
805 bool changed =
false;
808 const auto& style = ImGui::GetStyle();
809 auto pos = ImGui::GetCursorPos().x + ImGui::GetFrameHeight() +
812 changed |= ImGui::Checkbox(
"primary", &slot.hasPs);
813 ImGui::SameLine(pos);
815 changed |= ImGui::Combo(
"##ps", &slot.ps,
"0\0001\0002\0003\000");
817 changed |= ImGui::Checkbox(
"secondary", &slot.hasSs);
818 ImGui::SameLine(pos);
819 im::Disabled(!slot.hasSs, [&]{
820 changed |= ImGui::Combo(
"##ss", &slot.ss,
"0\0001\0002\0003\000");
823 changed |= ImGui::Checkbox(
"segment", &slot.hasSeg);
824 ImGui::SameLine(pos);
827 changed |= ImGui::InputScalar(
"##seg", ImGuiDataType_U8, &slot.seg, &one);
834 ImGui::SetNextItemWidth(-FLT_MIN);
835 changed |= ImGui::InputText(
"##cond", &slot.rest);
841void ImGuiBreakPoints::refreshSymbols()
843 refresh<BreakPoint>(guiBps);
844 refresh<WatchPoint>(guiWps);
848template<
typename Item>
849void ImGuiBreakPoints::refresh(std::vector<GuiItem>& items)
852 constexpr bool isWatchPoint = std::is_same_v<Item, WatchPoint>;
854 auto* motherBoard = manager.getReactor().getMotherBoard();
855 if (!motherBoard)
return;
857 for (
auto& item : items) {
859 auto adjust = [&](std::optional<uint16_t>& addr,
TclObject& str) {
862 if (
auto newAddr = parseAddress(str)) {
864 if (*newAddr != *addr) {
870 auto s = str.getString();
871 if ((s.size() == 6) && s.starts_with(
"0x")) {
872 if (
auto newSyms = symbolManager.lookupValue(*addr); !newSyms.empty()) {
873 str = newSyms.front()->name;
880 str = TclObject(
tmpStrCat(
"0x", hex_string<4>(*addr)));
885 if (
auto newAddr = parseAddress(str)) {
892 adjust(item.addr, item.addrStr);
894 adjust(item.endAddr, item.endAddrStr);
897 auto& cpuInterface = motherBoard->getCPUInterface();
898 auto& debugger = motherBoard->getDebugger();
899 auto& interp = manager.getInterpreter();
900 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(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 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)