summaryrefslogtreecommitdiff
path: root/src/memory.c
diff options
context:
space:
mode:
authorraven <citrons@mondecitronne.com>2026-04-08 22:51:39 -0500
committerraven <citrons@mondecitronne.com>2026-04-08 22:51:39 -0500
commit18a86e1038b20cb6f8922beead08dcc24ba2a4d3 (patch)
tree85cb74210d67d42763a4709d18af93aa60a8f400 /src/memory.c
parent4a3429a96b5b5ea7468540349aeb4535d5738053 (diff)
rewrite and port to SDL3
Diffstat (limited to 'src/memory.c')
-rw-r--r--src/memory.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/memory.c b/src/memory.c
new file mode 100644
index 0000000..373ca27
--- /dev/null
+++ b/src/memory.c
@@ -0,0 +1,140 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <SDL3/SDL.h>
+#include <sys/mman.h>
+#include "main.h"
+#include "procfs.h"
+#include "hash.h"
+#include "curve.h"
+#include "panic.h"
+#include "memory.h"
+
+uintptr_t to_addr(int x, int y) {
+ unsigned int ux, uy;
+ memcpy(&ux, &x, sizeof(unsigned int));
+ memcpy(&uy, &y, sizeof(unsigned int));
+ uintptr_t page = zorder(ux / PAGE_WIDTH, uy / PAGE_HEIGHT);
+ int offset =
+ x % PAGE_WIDTH / CHAR_BIT + y % PAGE_HEIGHT * PAGE_WIDTH / CHAR_BIT;
+ 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;
+ int ux = px * PAGE_WIDTH + offset % PAGE_WIDTH;
+ int uy = py * PAGE_HEIGHT + offset / PAGE_WIDTH;
+ memcpy(x, &ux, sizeof(int));
+ memcpy(y, &uy, sizeof(int));
+}
+
+int init_page_list(page_list *l, int fd) {
+ l->fd = fd;
+}
+
+static void free_page(page *p) {
+ if (p->tex) {
+ SDL_DestroyTexture(p->tex);
+ }
+ free(p);
+}
+
+void free_page_list(page_list *l) {
+ page *p = l->first;
+ while (p) {
+ page *next = p->next;
+ free_page(p);
+ p = next;
+ }
+ l->fd = -1;
+ l->first = NULL;
+}
+
+void free_unused_pages(page_list *l) {
+ page **prev_link = &l->first;
+ page *p = l->first;
+ while (p) {
+ page *next = p->next;
+ if (!p->in_use) {
+ *prev_link = next;
+ free_page(p);
+ } else {
+ prev_link = &p->next;
+ p->in_use = false;
+ }
+ p = next;
+ }
+}
+
+page *get_page(page_list *l, uintptr_t addr) {
+ addr = addr - addr % PAGE_SIZE;
+ for (page *p = l->first; p; p = p->next) {
+ if (p->address == addr) {
+ return p;
+ }
+ }
+ page *p = calloc(1, sizeof(page));
+ if (!p) panic("out of memory");
+ p->address = addr;
+ p->l = l;
+ p->next = l->first;
+ l->first = p;
+ return p;
+}
+
+static SDL_Palette *texture_palette() {
+ SDL_Color colors[] = {{0x00, 0x00, 0x00, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}};
+ static SDL_Palette *palette = NULL;
+ if (!palette) {
+ palette = must(SDL_CreatePalette(2));
+ must(SDL_SetPaletteColors(palette, colors, 0, 2));
+ }
+ return palette;
+}
+
+SDL_Texture *get_texture(page *p) {
+ static char data[PAGE_SIZE];
+ if (read_mem(p->l->fd, p->address, data, PAGE_SIZE) != 0) {
+ return NULL;
+ }
+ uint32_t hash = fnv(data, PAGE_SIZE);
+ if (p->hash != hash) {
+ if (p->tex) SDL_DestroyTexture(p->tex);
+ SDL_Surface *surface = must(SDL_CreateSurfaceFrom(
+ PAGE_WIDTH, PAGE_HEIGHT, SDL_PIXELFORMAT_INDEX1LSB, data,
+ PAGE_WIDTH / 8
+ ));
+ p->tex = must(SDL_CreateTextureFromSurface(renderer, surface));
+ must(SDL_SetTexturePalette(p->tex, texture_palette()));
+ SDL_DestroySurface(surface);
+ }
+ p->hash = hash;
+ p->in_use = true;
+ return p->tex;
+}
+
+static void write_bit(int fd, int x, int y, bool bit) {
+ uintptr_t addr = to_addr(x, y);
+ int bit_offs = x % CHAR_BIT;
+ uint8_t byte;
+ if (read_mem(fd, addr, &byte, 1) == -1) return;
+ byte = (byte & ~(1 << bit_offs)) | (bit << bit_offs);
+ write_mem(fd, addr, &byte, 1);
+}
+
+void draw_line(page_list *l,
+ double x1, double y1, double x2, double y2, bool bit) {
+ double dx = (x2 - x1);
+ double dy = (y2 - y1);
+ int step = abs(dx) >= abs(dy) ? abs(dx) : abs(dy);
+ dx = dx / step; dy = dy / step;
+ double x = x1; double y = y1;
+ for (int i = 0; i <= step; i++) {
+ write_bit(l->fd, x, y, bit);
+ x = x + dx;
+ y = y + dy;
+ }
+}