diff options
| author | raven <citrons@mondecitronne.com> | 2026-04-11 18:13:34 -0500 |
|---|---|---|
| committer | raven <citrons@mondecitronne.com> | 2026-04-11 18:13:34 -0500 |
| commit | f6c30f0acf44969646b2c895bd2672c0ebc85d66 (patch) | |
| tree | f399de34810f76408a6bd47e3620c1429cea5338 | |
| parent | 629d7d2ca4cbdda7aafcd6476b77248d1fa63bcc (diff) | |
tooltip with address, byte value and strings
| -rw-r--r-- | src/hash.h | 2 | ||||
| -rw-r--r-- | src/main.c | 62 | ||||
| -rw-r--r-- | src/menu.c | 11 | ||||
| -rw-r--r-- | src/tooltip.c | 74 | ||||
| -rw-r--r-- | src/tooltip.h | 19 |
5 files changed, 157 insertions, 11 deletions
@@ -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]; @@ -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(¤t_tooltip, tooltip_buf); + } else { + set_tooltip_text(¤t_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(¤t_tooltip); + } else { + float mx, my; + SDL_GetMouseState(&mx, &my); + show_tooltip(¤t_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(); @@ -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 |
