summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraven <citrons@mondecitronne.com>2026-04-11 18:13:34 -0500
committerraven <citrons@mondecitronne.com>2026-04-11 18:13:34 -0500
commitf6c30f0acf44969646b2c895bd2672c0ebc85d66 (patch)
treef399de34810f76408a6bd47e3620c1429cea5338
parent629d7d2ca4cbdda7aafcd6476b77248d1fa63bcc (diff)
tooltip with address, byte value and strings
-rw-r--r--src/hash.h2
-rw-r--r--src/main.c62
-rw-r--r--src/menu.c11
-rw-r--r--src/tooltip.c74
-rw-r--r--src/tooltip.h19
5 files changed, 157 insertions, 11 deletions
diff --git a/src/hash.h b/src/hash.h
index 238b15b..f9da7bb 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -3,7 +3,7 @@
#include <stdint.h>
-static uint64_t fnv(uint8_t *data, size_t size) {
+static uint64_t fnv(const uint8_t *data, size_t size) {
uint64_t hash = 0xcbf29ce484222325;
for (size_t i = 0; i < size; i++) {
hash ^= data[i];
diff --git a/src/main.c b/src/main.c
index 4a80d21..e65459b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,6 +14,7 @@
#include "memory.h"
#include "font.h"
#include "menu.h"
+#include "tooltip.h"
SDL_Window *window;
SDL_Renderer *renderer;
@@ -34,6 +35,7 @@ static procfs_map *mappings = NULL;
static int n_mappings = 0;
static menu *current_menu = NULL;
+static tooltip current_tooltip = {0};
static double get_scale() {
if (scale >= 1) {
@@ -307,6 +309,45 @@ static void update() {
} else {
mouse_held = false;
}
+
+ double x = mx, y = my;
+ absolute_pos(&x, &y);
+ uintptr_t addr = to_addr(x, y);
+ uintptr_t page_addr = addr - addr % PAGE_SIZE;
+ static uint8_t page_data[PAGE_SIZE];
+ if (read_mem(pages.fd, page_addr, page_data, PAGE_SIZE) == 0) {
+ uint8_t hover_byte = page_data[addr % PAGE_SIZE];
+ static char tooltip_buf[1024];
+ int n = snprintf(tooltip_buf, sizeof(tooltip_buf),
+ "%p\n0x%02x", addr, hover_byte
+ );
+ char *p = tooltip_buf + n;
+ if (hover_byte < 128 && hover_byte != 0) {
+ p = stpcpy(p, "\n\"");
+ int min, max;
+ for (min = addr % PAGE_SIZE; min > 0; min--) {
+ uint8_t next = page_data[min - 1];
+ if (next >= 128 || next == 0) break;
+ }
+ for (max = addr % PAGE_SIZE; max < PAGE_SIZE; max++) {
+ uint8_t cur = page_data[max];
+ if (cur >= 128 || cur == 0) break;
+ }
+ while (max - min > 64) {
+ if (max - addr % PAGE_SIZE > addr % PAGE_SIZE - min) {
+ max--;
+ } else {
+ min++;
+ }
+ }
+ memcpy(p, page_data + min, max - min);
+ p += max - min;
+ p = stpcpy(p, "\"");
+ }
+ set_tooltip_text(&current_tooltip, tooltip_buf);
+ } else {
+ set_tooltip_text(&current_tooltip, NULL);
+ }
}
static SDL_Texture *missing_texture();
@@ -377,6 +418,21 @@ static SDL_Texture *missing_texture() {
return tex;
}
+static void show() {
+ SDL_GetWindowSize(window, &window_width, &window_height);
+ SDL_RenderClear(renderer);
+ show_pages();
+ SDL_RenderPresent(renderer);
+ if (current_menu) {
+ menu_render(current_menu);
+ hide_tooltip(&current_tooltip);
+ } else {
+ float mx, my;
+ SDL_GetMouseState(&mx, &my);
+ show_tooltip(&current_tooltip, mx, my);
+ }
+}
+
static void main_loop() {
int last_time = 0, current_time = 0;
while (true) {
@@ -387,11 +443,7 @@ static void main_loop() {
}
}
update();
- SDL_GetWindowSize(window, &window_width, &window_height);
- SDL_RenderClear(renderer);
- show_pages();
- SDL_RenderPresent(renderer);
- if (current_menu) menu_render(current_menu);
+ show();
last_time = current_time;
current_time = SDL_GetTicks();
diff --git a/src/menu.c b/src/menu.c
index 73b1dbd..caffa81 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -6,10 +6,10 @@
#include "main.h"
#include "menu.h"
-#define MENU_PADDING 4
+#define PADDING 4
static int option_at(menu *m, int x, int y) {
- float cur_y = MENU_PADDING;
+ float cur_y = PADDING;
for (int i = 0; i < m->count; i++) {
float tw, th;
must(SDL_GetTextureSize(m->textures[i], &tw, &th));
@@ -34,18 +34,19 @@ menu *create_menu(menu_entry *entries, int count, int x, int y) {
m->textures = calloc(count, sizeof(SDL_Texture *));
if (!m->textures) panic("out of memory");
- int w = MENU_PADDING, h = MENU_PADDING;
+ int w = PADDING, h = PADDING;
for (int i = 0; i < count; i++) {
SDL_Color color = {0xff, 0xff, 0xff, 0xff};
SDL_Surface *text =
must(TTF_RenderText_Blended(font, m->entries[i].name, 0, color));
m->textures[i] = must(SDL_CreateTextureFromSurface(m->renderer, text));
+ SDL_DestroySurface(text);
float tw, th;
must(SDL_GetTextureSize(m->textures[i], &tw, &th));
w = SDL_max(w, tw);
h += th;
}
- w += MENU_PADDING; h += MENU_PADDING;
+ w += PADDING; h += PADDING;
m->height = h;
int px, py;
@@ -122,7 +123,7 @@ void menu_render(menu *m) {
SDL_SetRenderDrawColor(m->renderer, 0x00, 0x00, 0x00, 0xff);
SDL_RenderClear(m->renderer);
- float x = MENU_PADDING, y = MENU_PADDING - SDL_floor(m->scroll);
+ float x = PADDING, y = PADDING - SDL_floor(m->scroll);
for (int i = 0; i < m->count; i++) {
SDL_FRect dst;
dst.x = x;
diff --git a/src/tooltip.c b/src/tooltip.c
new file mode 100644
index 0000000..e900e40
--- /dev/null
+++ b/src/tooltip.c
@@ -0,0 +1,74 @@
+#include <SDL3/SDL.h>
+#include <SDL3_ttf/SDL_ttf.h>
+#include "panic.h"
+#include "font.h"
+#include "hash.h"
+#include "main.h"
+#include "tooltip.h"
+
+#define PADDING 4
+
+void set_tooltip_text(tooltip *t, const char *text) {
+ if (!t->window) {
+ t->window = must(SDL_CreatePopupWindow(window,
+ 0, 0, 0, 0, SDL_WINDOW_TOOLTIP | SDL_WINDOW_BORDERLESS
+ ));
+ t->renderer = must(SDL_CreateRenderer(t->window, NULL));
+ }
+ uint64_t hash = fnv(text, text ? strlen(text) : 0);
+ if (hash == t->hash) {
+ return;
+ }
+ t->hash = hash;
+ if (t->texture) {
+ SDL_DestroyTexture(t->texture);
+ t->texture = NULL;
+ }
+ if (!text) return;
+ SDL_Color color = {0xff, 0xff, 0xff, 0xff};
+ SDL_Surface *s = must(TTF_RenderText_Blended_Wrapped(
+ font, text, 0, color, 0
+ ));
+ t->texture = must(SDL_CreateTextureFromSurface(t->renderer, s));
+ SDL_DestroySurface(s);
+ float tw, th;
+ SDL_GetTextureSize(t->texture, &tw, &th);
+ SDL_SetWindowSize(t->window, tw + PADDING*2, th + PADDING*2);
+ SDL_SyncWindow(t->window);
+}
+
+void show_tooltip(tooltip *t, int x, int y) {
+ if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS)) {
+ hide_tooltip(t);
+ return;
+ }
+ if (!t->texture) {
+ hide_tooltip(t);
+ return;
+ }
+ float tw, th;
+ SDL_GetTextureSize(t->texture, &tw, &th);
+ SDL_SetWindowPosition(t->window, x + PADDING, y - th - PADDING*3);
+ if (t->hidden) {
+ SDL_ShowWindow(t->window);
+ SDL_SyncWindow(t->window);
+ t->hidden = false;
+ }
+
+ SDL_SetRenderDrawColor(t->renderer, 0, 0, 0x20, 0xff);
+ SDL_RenderClear(t->renderer);
+ SDL_SetRenderDrawColor(t->renderer, 0, 0, 0, 0xff);
+ SDL_FRect dst = {PADDING, PADDING, tw, th};
+ SDL_RenderTexture(t->renderer, t->texture, NULL, &dst);
+ SDL_FRect border_rect = {0, 0, tw + PADDING*2, th + PADDING*2};
+ SDL_SetRenderDrawColor(t->renderer, 0x50, 0x50, 0x50, 0xff);
+ SDL_RenderRect(t->renderer, &border_rect);
+ must(SDL_RenderPresent(t->renderer));
+}
+
+void hide_tooltip(tooltip *t) {
+ if (t->window && !t->hidden) {
+ SDL_HideWindow(t->window);
+ t->hidden = true;
+ }
+}
diff --git a/src/tooltip.h b/src/tooltip.h
new file mode 100644
index 0000000..f9385fc
--- /dev/null
+++ b/src/tooltip.h
@@ -0,0 +1,19 @@
+#ifndef TOOLTIP_H
+#define TOOLTIP_H
+
+#include <SDL3/SDL.h>
+#include <stdbool.h>
+
+typedef struct tooltip {
+ SDL_Window *window;
+ SDL_Renderer *renderer;
+ SDL_Texture *texture;
+ uint64_t hash;
+ bool hidden;
+} tooltip;
+
+void set_tooltip_text(tooltip *t, const char *text);
+void show_tooltip(tooltip *t, int x, int y);
+void hide_tooltip(tooltip *t);
+
+#endif