From 3af50b956b8887b64c3c29b30a0008be866b24c4 Mon Sep 17 00:00:00 2001 From: the lemons Date: Sun, 5 Feb 2023 19:06:16 -0600 Subject: initial commit --- memview.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 memview.c (limited to 'memview.c') diff --git a/memview.c b/memview.c new file mode 100644 index 0000000..c2af3ac --- /dev/null +++ b/memview.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "memview.h" +#include "procfs.h" + +struct viewer { + int fd; + SDL_Renderer *renderer; + SDL_Texture *page_texture; + uint8_t page_buffer[PAGE_SIZE]; +}; + +enum color { + BLACK = 0x00000000, + WHITE = 0xFFFFFFFF, + GREY = 0xFF303030, +}; + +#define BIT_OF(X, I) (((X) >> (I)) & 1ULL) + +static uintptr_t zorder(int x, int y) { + uintptr_t z = 0; + unsigned int ux, uy; + memcpy(&ux, &x, sizeof(unsigned int)); + memcpy(&uy, &y, sizeof(unsigned int)); + // interleaving bits results in a point on the z-order curve + for (int i = 0; i < sizeof(x) * CHAR_BIT; i++) + z |= (BIT_OF(ux, i) << i*2) | (BIT_OF(uy, i) << (i*2 + 1)); + return z; +} + +static void unzorder(uintptr_t z, int *x, int *y) { + unsigned int ux, uy = 0; + for (int i = 0; i < sizeof(z) * CHAR_BIT / 2; i++) { + ux |= BIT_OF(z, i*2) << i; + uy |= BIT_OF(z, i*2 + 1) << i; + } + memcpy(x, &ux, sizeof(int)); + memcpy(y, &uy, sizeof(int)); +} + +uintptr_t to_addr(int x, int y) { + uintptr_t page = zorder(x / PAGE_WIDTH, y / PAGE_HEIGHT); + int offset = x % PAGE_WIDTH + y % PAGE_HEIGHT * PAGE_WIDTH; + return page * PAGE_SIZE + offset; +} + +void to_pos(uintptr_t addr, int *x, int *y) { + int px, py; + unzorder(addr / PAGE_SIZE, &px, &py); + int offset = addr % PAGE_SIZE; + *x = px * PAGE_WIDTH + offset % PAGE_WIDTH; + *y = py * PAGE_HEIGHT + offset / PAGE_WIDTH; +} + +struct viewer *create_viewer(int fd, SDL_Renderer *renderer) { + struct viewer *v = calloc(1, sizeof(struct viewer)); + if (!v) return NULL; + v->fd = fd; v->renderer = renderer; + v->page_texture = SDL_CreateTexture(v->renderer, + SDL_PIXELFORMAT_RGBA32, + SDL_TEXTUREACCESS_STREAMING, + PAGE_WIDTH, PAGE_HEIGHT); + if (!v->page_texture) {free(v); return NULL;} + return v; +} + +void destroy_viewer(struct viewer *v) { + SDL_DestroyTexture(v->page_texture); + free(v); +} + +static void render_page(SDL_Texture *tex, uint8_t *data) { + uint32_t *pixels; int pitch; + assert(SDL_LockTexture(tex, NULL, (void **) &pixels, &pitch) != -1); + if (data) { + for (int i = 0; i < PAGE_SIZE; i++) { + for (int j = 0; j < CHAR_BIT; j++) { + uint8_t bit = (data[i] >> j) & 1; + pixels[i * CHAR_BIT + j] = bit ? WHITE : BLACK; + } + } + } else { + for (int i = 0; i < PAGE_WIDTH * PAGE_HEIGHT; i++) + pixels[i] = GREY; + } + SDL_UnlockTexture(tex); +} + +void render_pages(struct viewer *v, + int x, int y, int width, int height, double scale, bool refresh) { + int page_x = x / PAGE_WIDTH; + int page_y = y / PAGE_HEIGHT; + + int offs_x = x % PAGE_WIDTH * scale; + int offs_y = y % PAGE_HEIGHT * scale; + + int page_width = PAGE_WIDTH * scale; + int page_height = PAGE_HEIGHT * scale; + + int view_width = width / page_width; + int view_height = height / page_height; + + for (int draw_y = -1; draw_y <= view_height + 1; draw_y++) { + for (int draw_x = -1; draw_x <= view_width + 1; draw_x++) { + SDL_Rect src = {0, 0, PAGE_WIDTH, PAGE_HEIGHT}; + SDL_Rect dest = { + draw_x * page_width - offs_x, draw_y * page_height - offs_y, + page_width, page_height + }; + uintptr_t page = zorder(page_x + draw_x, page_y + draw_y); + bool success = read_page(v->fd, page, v->page_buffer) != -1; + // TODO: unless refresh is true, do not redraw if page unaltered + render_page(v->page_texture, success ? v->page_buffer : NULL); + SDL_RenderCopy(v->renderer, v->page_texture, &src, &dest); + } + } +} -- cgit v1.2.3