#include #include #include #include #include #include #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 * PAGE_HEIGHT + y % PAGE_HEIGHT; 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) { static char pixels[PAGE_SIZE]; for (int col = 0; col < PAGE_WIDTH / 8; col++) { for (int row = 0; row < PAGE_HEIGHT; row++) { pixels[row * PAGE_WIDTH / 8 + col] = data[col * PAGE_HEIGHT + row]; } } if (p->tex) SDL_DestroyTexture(p->tex); SDL_Surface *surface = must(SDL_CreateSurfaceFrom( PAGE_WIDTH, PAGE_HEIGHT, SDL_PIXELFORMAT_INDEX1LSB, pixels, PAGE_WIDTH / 8 )); must(SDL_SetSurfacePalette(surface, texture_palette())); p->tex = must(SDL_CreateTextureFromSurface(renderer, surface)); 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; } }