add colors for header/footer
This commit is contained in:
parent
f683654ba0
commit
b9a490d8cc
15 changed files with 309 additions and 147 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,4 +3,5 @@ build/
|
||||||
*.swo
|
*.swo
|
||||||
*.swp
|
*.swp
|
||||||
rntviewer
|
rntviewer
|
||||||
*.gdbhist
|
.gdbhist
|
||||||
|
.gdb_history
|
||||||
|
|
5
Makefile
5
Makefile
|
@ -13,7 +13,10 @@ build/imgui.o: src/imgui_inc.cpp third_party/imgui/imgui.h
|
||||||
$(CXX) -O3 -fPIC -c -Ithird_party/imgui $< -o $@
|
$(CXX) -O3 -fPIC -c -Ithird_party/imgui $< -o $@
|
||||||
|
|
||||||
d:
|
d:
|
||||||
$(MOLD) $(CXX) -DDEBUG -g -O0 $(CFLAGS) -fsanitize=undefined $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o -lasan $(ROOTLIBS) $(LIBS)
|
$(MOLD) $(CXX) -DDEBUG -g -O0 -DENABLE_ASAN $(CFLAGS) -fsanitize=undefined $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o -lasan $(ROOTLIBS) $(LIBS)
|
||||||
|
|
||||||
|
noasan:
|
||||||
|
$(MOLD) $(CXX) -DDEBUG -g -O0 $(CFLAGS) -fsanitize=undefined $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOTLIBS) $(LIBS)
|
||||||
|
|
||||||
r:
|
r:
|
||||||
$(MOLD) $(CXX) -O2 $(CFLAGS) $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOTLIBS) $(LIBS)
|
$(MOLD) $(CXX) -O2 $(CFLAGS) $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOTLIBS) $(LIBS)
|
||||||
|
|
|
@ -8,7 +8,7 @@ Size=1152,1414
|
||||||
|
|
||||||
[Window][main]
|
[Window][main]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=1143,1388
|
Size=1775,680
|
||||||
|
|
||||||
[Window][Hex View]
|
[Window][Hex View]
|
||||||
Pos=91,62
|
Pos=91,62
|
||||||
|
|
|
@ -1,57 +1,23 @@
|
||||||
enum Input_Key {
|
|
||||||
KEY_UP,
|
|
||||||
KEY_DOWN,
|
|
||||||
KEY_LEFT,
|
|
||||||
KEY_RIGHT,
|
|
||||||
KEY_Q,
|
|
||||||
KEY_ALT,
|
|
||||||
KEY_TAB,
|
|
||||||
|
|
||||||
KEY_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Mouse_Button {
|
|
||||||
MOUSE_BTN_LEFT,
|
|
||||||
MOUSE_BTN_RIGHT,
|
|
||||||
|
|
||||||
MOUSE_BTN_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Mouse_Button_State : u16 {
|
|
||||||
MOUSE_BTN_STATE_IS_DOWN = 0x1,
|
|
||||||
MOUSE_BTN_STATE_JUST_PRESSED = 0x2,
|
|
||||||
MOUSE_BTN_STATE_JUST_RELEASED = 0x4,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Key_State : u16 {
|
|
||||||
KEY_STATE_IS_DOWN = 0x1,
|
|
||||||
KEY_STATE_JUST_PRESSED = 0x2,
|
|
||||||
KEY_STATE_JUST_RELEASED = 0x4,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct User_Input {
|
|
||||||
u16 key_state[KEY_COUNT];
|
|
||||||
|
|
||||||
u16 mouse_btn_state[MOUSE_BTN_COUNT];
|
|
||||||
struct { i32 x; i32 y; } mouse_pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Window_Data {
|
|
||||||
// Real width and height of the window
|
|
||||||
i32 width;
|
|
||||||
i32 height;
|
|
||||||
bool size_just_changed;
|
|
||||||
|
|
||||||
f32 desired_aspect_ratio;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct App_State {
|
struct App_State {
|
||||||
Window_Data win_data;
|
Window_Data win_data;
|
||||||
User_Input user_input;
|
User_Input user_input;
|
||||||
|
RNTuple_Info *rntinfo;
|
||||||
|
|
||||||
FILE *inspected_file;
|
FILE *inspected_file;
|
||||||
u8 *inspected_fmem;
|
u8 *inspected_fmem;
|
||||||
u64 inspected_file_size;
|
u64 inspected_file_size;
|
||||||
// @Platform: inotify file descriptor
|
// @Platform: inotify file descriptor
|
||||||
int inot;
|
int inot;
|
||||||
|
|
||||||
|
const char *ntpl_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
internal
|
||||||
|
size_t file_size(FILE *f)
|
||||||
|
{
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size_t res = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
internal
|
|
||||||
size_t file_size(FILE *f)
|
|
||||||
{
|
|
||||||
fseek(f, 0, SEEK_END);
|
|
||||||
size_t res = ftell(f);
|
|
||||||
fseek(f, 0, SEEK_SET);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
internal
|
||||||
void monitor_key(GLFWwindow *window, u16 *key_state, i32 glfw_key, Input_Key haru_key) {
|
void monitor_key(GLFWwindow *window, u16 *key_state, i32 glfw_key, Input_Key haru_key) {
|
||||||
u16& state = key_state[haru_key];
|
u16& state = key_state[haru_key];
|
||||||
|
|
34
src/mem.cpp
34
src/mem.cpp
|
@ -4,7 +4,7 @@
|
||||||
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
#define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
||||||
#define SLLStackPop_N(f,next) ((f)=(f)->next)
|
#define SLLStackPop_N(f,next) ((f)=(f)->next)
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef ENABLE_ASAN
|
||||||
#define asan_poison_memory_region(mem, cmt) __asan_poison_memory_region(mem, cmt)
|
#define asan_poison_memory_region(mem, cmt) __asan_poison_memory_region(mem, cmt)
|
||||||
#define asan_unpoison_memory_region(mem, cmt) __asan_unpoison_memory_region(mem, cmt)
|
#define asan_unpoison_memory_region(mem, cmt) __asan_unpoison_memory_region(mem, cmt)
|
||||||
#else
|
#else
|
||||||
|
@ -12,27 +12,6 @@
|
||||||
#define asan_unpoison_memory_region(mem, cmt)
|
#define asan_unpoison_memory_region(mem, cmt)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// @Platform
|
|
||||||
internal
|
|
||||||
void *os_reserve(u64 size)
|
|
||||||
{
|
|
||||||
return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Platform
|
|
||||||
internal
|
|
||||||
void os_release(void *mem, u64 size)
|
|
||||||
{
|
|
||||||
munmap(mem, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Platform
|
|
||||||
internal
|
|
||||||
b32x os_commit(void *addr, u64 size)
|
|
||||||
{
|
|
||||||
return mprotect(addr, size, PROT_READ|PROT_WRITE) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// init_res: initial reserved size
|
// init_res: initial reserved size
|
||||||
// init_cmt: initial committed size
|
// init_cmt: initial committed size
|
||||||
internal
|
internal
|
||||||
|
@ -143,6 +122,15 @@ T *arena_push(Arena *arena)
|
||||||
return (T *)mem;
|
return (T *)mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
internal
|
||||||
|
T *arena_push_zeroed(Arena *arena)
|
||||||
|
{
|
||||||
|
T *mem = arena_push<T>(arena);
|
||||||
|
memset(mem, 0, sizeof(T));
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
internal
|
internal
|
||||||
T *arena_push_array_no_zero(Arena *arena, u64 count)
|
T *arena_push_array_no_zero(Arena *arena, u64 count)
|
||||||
|
@ -181,7 +169,7 @@ u64 arena_pos(Arena *arena)
|
||||||
internal
|
internal
|
||||||
void arena_pop_to(Arena *arena, u64 big_pos_unclamped)
|
void arena_pop_to(Arena *arena, u64 big_pos_unclamped)
|
||||||
{
|
{
|
||||||
u64 big_pos = min(ARENA_HEADER_SIZE, big_pos_unclamped);
|
u64 big_pos = max(ARENA_HEADER_SIZE, big_pos_unclamped);
|
||||||
|
|
||||||
// unroll the chain
|
// unroll the chain
|
||||||
Arena *current = arena->cur;
|
Arena *current = arena->cur;
|
||||||
|
|
65
src/platform_linux.h
Normal file
65
src/platform_linux.h
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h> // for NAME_MAX
|
||||||
|
|
||||||
|
internal
|
||||||
|
void os_open_and_map_file(const char *fname, App_State &app)
|
||||||
|
{
|
||||||
|
FILE *file = fopen(fname, "rb");
|
||||||
|
int fd = fileno(file);
|
||||||
|
size_t fsize = file_size(file);
|
||||||
|
|
||||||
|
void *fmem = mmap(0, fsize, PROT_READ, MAP_SHARED_VALIDATE, fd, 0);
|
||||||
|
if (!fmem)
|
||||||
|
fprintf(stderr, "Failed to open file %s\n", fname);
|
||||||
|
|
||||||
|
app.inspected_file = file;
|
||||||
|
app.inspected_file_size = fsize;
|
||||||
|
app.inspected_fmem = reinterpret_cast<u8*>(fmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void os_unmap_file(u8 *&mem, u64 size)
|
||||||
|
{
|
||||||
|
if (mem) munmap(mem, size);
|
||||||
|
mem = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void os_start_file_watch(const char *fname, App_State &app)
|
||||||
|
{
|
||||||
|
int inot = inotify_init1(IN_NONBLOCK);
|
||||||
|
if (inot == -1)
|
||||||
|
fprintf(stderr, "Failed to init inotify: %s (%d)\n", strerror(errno), errno);
|
||||||
|
if (inotify_add_watch(inot, fname, IN_MODIFY) == -1)
|
||||||
|
fprintf(stderr, "Failed to add inotify watch: %s (%d)\n", strerror(errno), errno);
|
||||||
|
|
||||||
|
app.inot = inot;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void os_stop_file_watch(App_State &app)
|
||||||
|
{
|
||||||
|
if (app.inot != -1) close(app.inot);
|
||||||
|
app.inot = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void *os_reserve(u64 size)
|
||||||
|
{
|
||||||
|
return mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void os_release(void *mem, u64 size)
|
||||||
|
{
|
||||||
|
munmap(mem, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
b32x os_commit(void *addr, u64 size)
|
||||||
|
{
|
||||||
|
return mprotect(addr, size, PROT_READ|PROT_WRITE) == 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,34 +1,53 @@
|
||||||
internal
|
internal
|
||||||
MemoryEditor make_memory_editor()
|
u32 mem_edit_bg_color_fn(const u8 *data, u64 off, const void *user_data)
|
||||||
|
{
|
||||||
|
const RNTuple_Info *ntinfo = reinterpret_cast<const RNTuple_Info *>(user_data);
|
||||||
|
|
||||||
|
if (ntinfo->header.start <= off && off <= ntinfo->header.end())
|
||||||
|
return IM_COL32(200, 0, 50, 255);
|
||||||
|
if (ntinfo->footer.start <= off && off <= ntinfo->footer.end())
|
||||||
|
return IM_COL32(50, 0, 200, 255);
|
||||||
|
return IM_COL32(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
MemoryEditor make_memory_editor(const RNTuple_Info &ntpl_info)
|
||||||
{
|
{
|
||||||
MemoryEditor mem_edit;
|
MemoryEditor mem_edit;
|
||||||
// mem_edit.ReadOnly = true;
|
// mem_edit.ReadOnly = true;
|
||||||
mem_edit.Cols = 32;
|
mem_edit.Cols = 32;
|
||||||
|
mem_edit.BgColorFn = mem_edit_bg_color_fn;
|
||||||
|
mem_edit.BgColorFnUserData = &ntpl_info;
|
||||||
return mem_edit;
|
return mem_edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
void update_and_render(Arena *arena, App_State &app, f32 delta_time)
|
void update_and_render(Arena *arena, App_State &app, f32 delta_time)
|
||||||
{
|
{
|
||||||
|
(void)delta_time;
|
||||||
|
|
||||||
ImGui::SetNextWindowPos({ 0, 0 });
|
ImGui::SetNextWindowPos({ 0, 0 });
|
||||||
ImGui::SetNextWindowSize({ (f32)app.win_data.width, (f32)app.win_data.height });
|
ImGui::SetNextWindowSize({ (f32)app.win_data.width, (f32)app.win_data.height });
|
||||||
|
|
||||||
Temp scratch = temp_begin(arena);
|
Temp scratch = temp_begin(arena);
|
||||||
defer { temp_end(scratch); };
|
defer { temp_end(scratch); };
|
||||||
|
|
||||||
u64 text_buf_size = min(app.inspected_file_size * 2, 2048);
|
const u64 inspected_max_size = 2048;
|
||||||
|
u64 text_buf_size = min(app.inspected_file_size * 2, inspected_max_size);
|
||||||
char *text_buf = arena_push_array_no_zero<char>(scratch.arena, text_buf_size + 1);
|
char *text_buf = arena_push_array_no_zero<char>(scratch.arena, text_buf_size + 1);
|
||||||
// TODO: convert file content to human readable
|
// Convert file content to human readable
|
||||||
|
// @Speed: maybe do this only when the file changes
|
||||||
for (u64 i = 0; i < text_buf_size / 2; ++i)
|
for (u64 i = 0; i < text_buf_size / 2; ++i)
|
||||||
sprintf(&text_buf[2 * i], "%02X", app.inspected_fmem[i]);
|
sprintf(&text_buf[2 * i], "%02X", app.inspected_fmem[i]);
|
||||||
text_buf[text_buf_size] = 0;
|
text_buf[text_buf_size] = 0;
|
||||||
|
|
||||||
if (ImGui::Begin("main")) {
|
if (ImGui::Begin("main")) {
|
||||||
// ImGui::SetNextWindowContentSize({ 500, 600 });
|
ImGui::Text("Inspecting RNTuple '%s' (%s)", app.ntpl_name,
|
||||||
// ImGui::SetCursorX(30);
|
(const char *)rntuple_description(scratch.arena, app.rntinfo->anchor));
|
||||||
// ImGui::TextWrapped("%s", text_buf);
|
|
||||||
static MemoryEditor mem_edit = make_memory_editor();
|
static MemoryEditor mem_edit = make_memory_editor(*app.rntinfo);
|
||||||
mem_edit.DrawWindow("Hex View", app.inspected_fmem, app.inspected_file_size);
|
mem_edit.DrawWindow("Hex View", app.inspected_fmem, app.inspected_file_size);
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
src/rntuple.cpp
Normal file
38
src/rntuple.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
internal
|
||||||
|
String8 rntuple_description(Arena *arena, const RNTuple &anchor)
|
||||||
|
{
|
||||||
|
String8 desc = push_str8f(arena, "version %u.%u.%u.%u",
|
||||||
|
anchor.GetVersionEpoch(),
|
||||||
|
anchor.GetVersionMajor(),
|
||||||
|
anchor.GetVersionMinor(),
|
||||||
|
anchor.GetVersionPatch());
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
RNTuple_Info *get_rntuple_info(Arena *arena, const char *fname, const char *ntpl_name)
|
||||||
|
{
|
||||||
|
RNTuple_Info *info = arena_push_zeroed<RNTuple_Info>(arena);
|
||||||
|
|
||||||
|
// Open the TFile
|
||||||
|
TFile *tfile = TFile::Open(fname, "READ");
|
||||||
|
if (!tfile) {
|
||||||
|
fprintf(stderr, "Failed to open TFile.\n");
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
defer { delete tfile; };
|
||||||
|
|
||||||
|
// Get the RNTuple information
|
||||||
|
const RNTuple *anchor = tfile->Get<RNTuple>(ntpl_name);
|
||||||
|
if (anchor) {
|
||||||
|
info->anchor = *anchor;
|
||||||
|
info->header.start = anchor->GetSeekHeader();
|
||||||
|
info->header.len = anchor->GetNBytesHeader();
|
||||||
|
info->footer.start = anchor->GetSeekFooter();
|
||||||
|
info->footer.len = anchor->GetNBytesFooter();
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "RNTuple '%s' not found in %s.\n", ntpl_name, fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
13
src/rntuple.h
Normal file
13
src/rntuple.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using RNTuple = ROOT::Experimental::RNTuple;
|
||||||
|
|
||||||
|
struct Byte_Range {
|
||||||
|
u64 start, len;
|
||||||
|
u64 end() const { return start + len; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RNTuple_Info {
|
||||||
|
RNTuple anchor;
|
||||||
|
|
||||||
|
Byte_Range header;
|
||||||
|
Byte_Range footer;
|
||||||
|
};
|
|
@ -6,12 +6,6 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
// @Platform
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/inotify.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <limits.h> // for NAME_MAX
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include <sanitizer/asan_interface.h>
|
#include <sanitizer/asan_interface.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,11 +21,19 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "defer.hpp"
|
#include "defer.hpp"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
#include "str.h"
|
||||||
|
#include "rntuple.h"
|
||||||
|
#include "window.h"
|
||||||
#include "app_state.h"
|
#include "app_state.h"
|
||||||
|
|
||||||
|
// @Platform
|
||||||
|
#include "platform_linux.h"
|
||||||
|
|
||||||
namespace chr = std::chrono;
|
namespace chr = std::chrono;
|
||||||
|
|
||||||
#include "mem.cpp"
|
#include "mem.cpp"
|
||||||
|
#include "str.cpp"
|
||||||
|
#include "rntuple.cpp"
|
||||||
#include "render.cpp"
|
#include "render.cpp"
|
||||||
#include "mainloop.cpp"
|
#include "mainloop.cpp"
|
||||||
|
|
||||||
|
@ -86,16 +88,25 @@ GLFWwindow* init_glfw(i32 desired_win_width, i32 desired_win_height)
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
void app_cleanup(App_State &app)
|
||||||
|
{
|
||||||
|
os_stop_file_watch(app);
|
||||||
|
os_unmap_file(app.inspected_fmem, app.inspected_file_size);
|
||||||
|
if (app.inspected_file) fclose(app.inspected_file);
|
||||||
|
app.inspected_file = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc < 3) {
|
if (argc > 1 && argv[1][0] == '-') {
|
||||||
fprintf(stderr, "Usage: %s <ntuple_name> <ntuple_file.root>\n", argv[0]);
|
fprintf(stderr, "Usage: %s <ntuple_name> <ntuple_file.root>\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect arguments
|
// Collect arguments
|
||||||
const char *ntpl_name = argv[1];
|
const char *ntpl_name = argc > 1 ? argv[1] : nullptr;
|
||||||
const char *fname = argv[2];
|
const char *fname = argc > 2 ? argv[2] : nullptr;
|
||||||
|
|
||||||
// Allocate program memory
|
// Allocate program memory
|
||||||
Arena *arena = arena_alloc();
|
Arena *arena = arena_alloc();
|
||||||
|
@ -118,57 +129,22 @@ int main(int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open and map te file
|
App_State app {};
|
||||||
FILE *file = fopen(fname, "rb");
|
defer { app_cleanup(app); };
|
||||||
defer { fclose(file); };
|
|
||||||
|
|
||||||
int fd = fileno(file);
|
// Open and map the file
|
||||||
size_t fsize = file_size(file);
|
if (fname) {
|
||||||
// @Platform
|
os_open_and_map_file(fname, app);
|
||||||
void *fmem = mmap(0, fsize, PROT_READ, MAP_SHARED_VALIDATE, fd, 0);
|
|
||||||
if (!fmem) {
|
|
||||||
fprintf(stderr, "Failed to open file %s\n", fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
defer { munmap(fmem, fsize); };
|
|
||||||
|
|
||||||
// @Platform: watch file for changes (to adapt the displayed file size - otherwise
|
// Watch file for changes (to adapt the displayed file size - otherwise
|
||||||
// we may try to access invalid memory when the file gets shrunk)
|
// we may try to access invalid memory when the file gets shrunk)
|
||||||
int inot = inotify_init1(IN_NONBLOCK);
|
os_start_file_watch(fname, app);
|
||||||
if (inot == -1) {
|
|
||||||
fprintf(stderr, "Failed to init inotify: %s (%d)\n", strerror(errno), errno);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
if (inotify_add_watch(inot, fname, IN_MODIFY) == -1) {
|
|
||||||
fprintf(stderr, "Failed to add inotify watch: %s (%d)\n", strerror(errno), errno);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
defer { close(inot); };
|
|
||||||
|
|
||||||
// Open the TFile
|
app.ntpl_name = ntpl_name;
|
||||||
#if 0
|
app.rntinfo = get_rntuple_info(arena, fname, ntpl_name);
|
||||||
TFile *tfile = TFile::Open(fname, "READ");
|
|
||||||
if (!tfile) {
|
|
||||||
fprintf(stderr, "Failed to open TFile.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
defer { delete tfile; };
|
|
||||||
|
|
||||||
// Get the RNTuple information
|
|
||||||
const RNTuple *anchor = tfile->Get<RNTuple>(ntpl_name);
|
|
||||||
if (!anchor) {
|
|
||||||
fprintf(stderr, "RNTuple '%s' not found in %s.\n", ntpl_name, fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Start main loop
|
// Start main loop
|
||||||
App_State app {};
|
|
||||||
app.inspected_file = file;
|
|
||||||
app.inspected_fmem = (u8*)fmem;
|
|
||||||
app.inspected_file_size = fsize;
|
|
||||||
app.inot = inot;
|
|
||||||
|
|
||||||
run_main_loop(window, arena, app);
|
run_main_loop(window, arena, app);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
22
src/str.cpp
Normal file
22
src/str.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
internal
|
||||||
|
String8 push_str8fv(Arena *arena, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
va_list args2;
|
||||||
|
va_copy(args2, args);
|
||||||
|
u32 needed_bytes = vsnprintf(0, 0, fmt, args) + 1;
|
||||||
|
String8 result = {};
|
||||||
|
result.str = arena_push_array_no_zero<u8>(arena, needed_bytes);
|
||||||
|
result.size = vsnprintf((char*)result.str, needed_bytes, fmt, args2);
|
||||||
|
result.str[result.size] = 0;
|
||||||
|
va_end(args2);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 push_str8f(Arena *arena, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 result = push_str8fv(arena, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
12
src/str.h
Normal file
12
src/str.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
struct String8 {
|
||||||
|
u8* str;
|
||||||
|
u64 size;
|
||||||
|
|
||||||
|
operator const char *() const {
|
||||||
|
return (const char *)str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define str8(s) String8((u8*)(s), sizeof(s) - 1)
|
||||||
|
|
||||||
|
String8 push_str8f(Arena *arena, char *fmt, ...);
|
47
src/window.h
Normal file
47
src/window.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
enum Input_Key {
|
||||||
|
KEY_UP,
|
||||||
|
KEY_DOWN,
|
||||||
|
KEY_LEFT,
|
||||||
|
KEY_RIGHT,
|
||||||
|
KEY_Q,
|
||||||
|
KEY_ALT,
|
||||||
|
KEY_TAB,
|
||||||
|
|
||||||
|
KEY_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Mouse_Button {
|
||||||
|
MOUSE_BTN_LEFT,
|
||||||
|
MOUSE_BTN_RIGHT,
|
||||||
|
|
||||||
|
MOUSE_BTN_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Mouse_Button_State : u16 {
|
||||||
|
MOUSE_BTN_STATE_IS_DOWN = 0x1,
|
||||||
|
MOUSE_BTN_STATE_JUST_PRESSED = 0x2,
|
||||||
|
MOUSE_BTN_STATE_JUST_RELEASED = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Key_State : u16 {
|
||||||
|
KEY_STATE_IS_DOWN = 0x1,
|
||||||
|
KEY_STATE_JUST_PRESSED = 0x2,
|
||||||
|
KEY_STATE_JUST_RELEASED = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct User_Input {
|
||||||
|
u16 key_state[KEY_COUNT];
|
||||||
|
|
||||||
|
u16 mouse_btn_state[MOUSE_BTN_COUNT];
|
||||||
|
struct { i32 x; i32 y; } mouse_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Window_Data {
|
||||||
|
// Real width and height of the window
|
||||||
|
i32 width;
|
||||||
|
i32 height;
|
||||||
|
bool size_just_changed;
|
||||||
|
|
||||||
|
f32 desired_aspect_ratio;
|
||||||
|
};
|
||||||
|
|
21
third_party/imgui_club/imgui_memory_editor.h
vendored
21
third_party/imgui_club/imgui_memory_editor.h
vendored
|
@ -94,6 +94,8 @@ struct MemoryEditor
|
||||||
ImU8 (*ReadFn)(const ImU8* data, size_t off); // = 0 // optional handler to read bytes.
|
ImU8 (*ReadFn)(const ImU8* data, size_t off); // = 0 // optional handler to read bytes.
|
||||||
void (*WriteFn)(ImU8* data, size_t off, ImU8 d); // = 0 // optional handler to write bytes.
|
void (*WriteFn)(ImU8* data, size_t off, ImU8 d); // = 0 // optional handler to write bytes.
|
||||||
bool (*HighlightFn)(const ImU8* data, size_t off);//= 0 // optional handler to return Highlight property (to support non-contiguous highlighting).
|
bool (*HighlightFn)(const ImU8* data, size_t off);//= 0 // optional handler to return Highlight property (to support non-contiguous highlighting).
|
||||||
|
ImU32 (*BgColorFn)(const ImU8* data, size_t off, const void *UserData); // = 0 // optional handler to return custom background color of individual bytes.
|
||||||
|
const void *BgColorFnUserData;
|
||||||
|
|
||||||
// [Internal State]
|
// [Internal State]
|
||||||
bool ContentsWidthChanged;
|
bool ContentsWidthChanged;
|
||||||
|
@ -126,6 +128,8 @@ struct MemoryEditor
|
||||||
ReadFn = NULL;
|
ReadFn = NULL;
|
||||||
WriteFn = NULL;
|
WriteFn = NULL;
|
||||||
HighlightFn = NULL;
|
HighlightFn = NULL;
|
||||||
|
BgColorFn = NULL;
|
||||||
|
BgColorFnUserData = NULL;
|
||||||
|
|
||||||
// State/Internals
|
// State/Internals
|
||||||
ContentsWidthChanged = false;
|
ContentsWidthChanged = false;
|
||||||
|
@ -302,6 +306,19 @@ struct MemoryEditor
|
||||||
}
|
}
|
||||||
draw_list->AddRectFilled(pos, ImVec2(pos.x + highlight_width, pos.y + s.LineHeight), HighlightColor);
|
draw_list->AddRectFilled(pos, ImVec2(pos.x + highlight_width, pos.y + s.LineHeight), HighlightColor);
|
||||||
}
|
}
|
||||||
|
else if (BgColorFn)
|
||||||
|
{
|
||||||
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||||
|
float highlight_width = s.GlyphWidth * 2;
|
||||||
|
bool is_next_byte_highlighted = (addr + 1 < mem_size) && ((BgColorFn(mem_data, addr + 1, BgColorFnUserData) & IM_COL32_A_MASK) != 0);
|
||||||
|
if (is_next_byte_highlighted || (n + 1 == Cols))
|
||||||
|
{
|
||||||
|
highlight_width = s.HexCellWidth;
|
||||||
|
if (OptMidColsCount > 0 && n > 0 && (n + 1) < Cols && ((n + 1) % OptMidColsCount) == 0)
|
||||||
|
highlight_width += s.SpacingBetweenMidCols;
|
||||||
|
}
|
||||||
|
draw_list->AddRectFilled(pos, ImVec2(pos.x + highlight_width, pos.y + s.LineHeight), BgColorFn(mem_data, addr, BgColorFnUserData));
|
||||||
|
}
|
||||||
|
|
||||||
if (DataEditingAddr == addr)
|
if (DataEditingAddr == addr)
|
||||||
{
|
{
|
||||||
|
@ -413,6 +430,10 @@ struct MemoryEditor
|
||||||
draw_list->AddRectFilled(pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), ImGui::GetColorU32(ImGuiCol_FrameBg));
|
draw_list->AddRectFilled(pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), ImGui::GetColorU32(ImGuiCol_FrameBg));
|
||||||
draw_list->AddRectFilled(pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), ImGui::GetColorU32(ImGuiCol_TextSelectedBg));
|
draw_list->AddRectFilled(pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), ImGui::GetColorU32(ImGuiCol_TextSelectedBg));
|
||||||
}
|
}
|
||||||
|
else if (BgColorFn)
|
||||||
|
{
|
||||||
|
draw_list->AddRectFilled(pos, ImVec2(pos.x + s.GlyphWidth, pos.y + s.LineHeight), BgColorFn(mem_data, addr, BgColorFnUserData));
|
||||||
|
}
|
||||||
unsigned char c = ReadFn ? ReadFn(mem_data, addr) : mem_data[addr];
|
unsigned char c = ReadFn ? ReadFn(mem_data, addr) : mem_data[addr];
|
||||||
char display_c = (c < 32 || c >= 128) ? '.' : c;
|
char display_c = (c < 32 || c >= 128) ? '.' : c;
|
||||||
draw_list->AddText(pos, (display_c == c) ? color_text : color_disabled, &display_c, &display_c + 1);
|
draw_list->AddText(pos, (display_c == c) ? color_text : color_disabled, &display_c, &display_c + 1);
|
||||||
|
|
Loading…
Reference in a new issue