diff --git a/src/render.cpp b/src/render.cpp index f83825c..d72017a 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -33,6 +33,9 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) App_State *app = reinterpret_cast(user_data); off += app->base_display_addr; + if (app->viewer.hovered_range.start <= off && off < app->viewer.hovered_range.end()) + return imcol(app->viewer.col_highlight); + i64 hilite_cluster = app->viewer.highlight_cluster ? app->viewer.highlighted_cluster : -1; Section section = find_section(*app, off, hilite_cluster); @@ -46,6 +49,9 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) internal void mem_edit_interact_fn(const u8 *, u64 off, void *user_data) { + App_State *app = reinterpret_cast(user_data); + off += app->base_display_addr; + app->viewer.hovered_off = off; } internal @@ -219,6 +225,10 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) } // Repeated sections: allow jumping to the N-th + ImGui::ColorEdit3("_TKey Header", app.viewer.col_key, flags); + ImGui::SameLine(); + if (ImGui::Button("TKey Header")) {} // TODO: jump to next key + ImGui::ColorEdit3("_Page Start", app.viewer.col_page_start, flags); ImGui::SameLine(); if (ImGui::Button("Page Start")) @@ -282,6 +292,26 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) ImGui::Checkbox("Highlight cluster", &app.viewer.highlight_cluster); } + // --------------------------------- + ImGui::Separator(); + + { + Section hovered_section = find_section(app, app.viewer.hovered_off); + Sec_Hover_Info hover_info = get_section_hover_info(scratch.arena, hovered_section, app.viewer.hovered_off, app.inspected_file.mem); + u8 indent = 0; + for (String8_Node *node = hover_info.desc; node; node = node->next) { + String8 fmt = str8("%s"); + if (indent) { + // create indent + fmt = push_str8f(scratch.arena, "%%%ds", indent + node->str.size); + } + + ImGui::Text(fmt.c(), node->str.c()); + indent += 2; + } + app.viewer.hovered_range = hover_info.rng; + } + ImGui::EndTable(); } diff --git a/src/render.h b/src/render.h index e48fe53..3aa8599 100644 --- a/src/render.h +++ b/src/render.h @@ -17,6 +17,10 @@ struct Viewer { u64 latest_key_gone_to; u64 latest_checksum_gone_to; u64 latest_page_list_gone_to; + + // Absolute byte offset into inspected_file.mem that has been hovered last. + u64 hovered_off; + Byte_Range hovered_range; }; struct Edit_Bg_Color_Data { diff --git a/src/render_term.cpp b/src/render_term.cpp index 486f086..48a6a50 100644 --- a/src/render_term.cpp +++ b/src/render_term.cpp @@ -39,11 +39,7 @@ String8 render_legend_to_string(Arena *arena, const Term_Viewer &viewer, const A Temp scratch = scratch_begin(&arena, 1); defer { scratch_end(scratch); }; - struct String8_Node { - String8_Node *next; - String8 str; - } *head = nullptr, *tail = nullptr; - + String8_Node *head = nullptr, *tail = nullptr; String8 color_none = ansi_color_table[ACol_None]; u64 tot_len = 0; for (u64 section = 1; section < Sec_COUNT; ++section) { diff --git a/src/rntuple.cpp b/src/rntuple.cpp index ec67006..42ac0d2 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -439,3 +439,57 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1) return {}; } + +struct Sec_Hover_Info { + Byte_Range rng; + String8_Node *desc; +}; + +// `off` is the absolute offset into `data`. +internal +Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, const u8 *data) +{ + Sec_Hover_Info info {}; + + printf("off: 0x%lX, sec start: 0x%lX\n", off, section.range.start); + // assert(off >= section.range.start); + if (off < section.range.start) { + printf("WRONG\n"); // TODO: fix TKey Header case + } + + u64 start = section.range.start; + u64 roff = off - start; // offset relative to `section` + + if (section.id == Sec_RNTuple_Anchor) { + info.desc = push_str8_node(arena, nullptr, "RNTuple Anchor"); + // TODO: dry + if (roff < sizeof(u32)) { + info.rng = { start, sizeof(u32) }; + u32 val; + memcpy(&val, data + info.rng.start, info.rng.len); + val = bswap_32(val); + val -= 0x40000000; + push_str8_node(arena, info.desc, "Object len: %u", val); + } else if (roff < sizeof(u32) + sizeof(u16)) { + info.rng = { start + sizeof(u32), sizeof(u16) }; + u32 val; + memcpy(&val, data + info.rng.start, info.rng.len); + val = bswap_16(val); + push_str8_node(arena, info.desc, "Class version: %u", val); + } else if (roff < sizeof(u32) + sizeof(u16) + sizeof(u16)) { + info.rng = { start + sizeof(u32) + sizeof(u16), sizeof(u16) }; + u16 val; + memcpy(&val, data + info.rng.start, info.rng.len); + val = bswap_16(val); + push_str8_node(arena, info.desc, "Version Epoch: %u", val); + } else if (roff < sizeof(u32) + sizeof(u16) + sizeof(u16) + sizeof(u16)) { + info.rng = { start + sizeof(u32) + sizeof(u16) + sizeof(u16), sizeof(u16) }; + u16 val; + memcpy(&val, data + info.rng.start, info.rng.len); + val = bswap_16(val); + push_str8_node(arena, info.desc, "Version Major: %u", val); + } + } + + return info; +} diff --git a/src/str.cpp b/src/str.cpp index 954b02f..bcf5696 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -36,3 +36,19 @@ String8 to_pretty_size(Arena *arena, u64 bytes) return push_str8f(arena, "%zu B", bytes); } + +internal +String8_Node *push_str8_node(Arena *arena, String8_Node *prev, const char *fmt, ...) +{ + String8_Node *snode = arena_push(arena); + + va_list args; + va_start(args, fmt); + snode->str = push_str8fv(arena, fmt, args); + va_end(args); + + if (prev) + prev->next = snode; + + return snode; +} diff --git a/src/str.h b/src/str.h index 32b2fb3..0e5ceed 100644 --- a/src/str.h +++ b/src/str.h @@ -10,3 +10,10 @@ struct String8 { String8 str8_from_c(const char *str); String8 push_str8f(Arena *arena, char *fmt, ...); + + +struct String8_Node { + String8_Node *next; + String8 str; +}; +