1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
#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 * 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
));
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;
}
}
|