aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-30 20:31:08 +0200
committerBad Diode <bd@badd10de.dev>2023-08-30 20:31:08 +0200
commit874ae39b6074da2778b72bcbaf6c7c7ef19aa233 (patch)
tree5ed5989ac78df0fea75c88c0b63f9a1a5ead6f53 /src
parentbe57c62f4633623005b5ac463ce7f65e8761d9bd (diff)
downloaduxngba-874ae39b6074da2778b72bcbaf6c7c7ef19aa233.tar.gz
uxngba-874ae39b6074da2778b72bcbaf6c7c7ef19aa233.zip
Remove previous uxn core
Diffstat (limited to 'src')
-rw-r--r--src/devices.c515
-rw-r--r--src/main.c337
-rw-r--r--src/uxn-core.c4
-rw-r--r--src/uxn.c117
-rw-r--r--src/uxn.h37
5 files changed, 291 insertions, 719 deletions
diff --git a/src/devices.c b/src/devices.c
index e031a85..c65d79b 100644
--- a/src/devices.c
+++ b/src/devices.c
@@ -1,290 +1,305 @@
1static time_t seconds = 0; 1static time_t seconds = 0;
2 2
3int 3#define RAM_PAGES 0x10
4uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) { 4
5 (void)u; 5void
6 txt_printf("HALTED\n"); 6deo_console(u8 *dev, u8 port) {
7 txt_printf("I: %lu\n", instr); 7 switch(port) {
8 txt_printf("E: %lu\n", err); 8 case 0x8:
9 txt_printf("A: %lu\n", addr); 9 txt_putc(dev[port]);
10 while (true); 10 return;
11 case 0x9:
12 txt_printf("ERROR: %c");
13 txt_putc(dev[port]);
14 return;
15 }
11} 16}
12 17
13IWRAM_CODE 18u16
14u8 19dei_screen(u8 *dev, u8 port) {
15screen_dei(u8 *d, u8 port) { 20 switch(port) {
16 // switch(port) { 21 case 0x0:
17 // case 0x2: return (SCREEN_WIDTH >> 8); 22 case 0x8:
18 // case 0x3: return (SCREEN_WIDTH); 23 case 0xa:
19 // case 0x4: return (SCREEN_HEIGHT >> 8); 24 case 0xc: return PEEK2(dev + port);
20 // case 0x5: return (SCREEN_HEIGHT); 25 case 0x2: return SCREEN_WIDTH;
21 // default: return d[port]; 26 case 0x4: return SCREEN_HEIGHT;
22 // } 27 default: return dev[port];
28 }
23} 29}
24 30
25IWRAM_CODE 31u16
26void 32dei_mouse(u8 *dev, u8 port) {
27screen_deo(u8 *ram, u8 *d, u8 port) { 33 switch(port) {
28 // switch(port) { 34 case 0x0:
29 // case 0xe: { 35 case 0x2:
30 // u8 ctrl = d[0xe]; 36 case 0x4:
31 // u8 color = ctrl & 0x3; 37 case 0xa:
32 // u16 x0 = PEEK2(d + 0x8); 38 case 0xc: return PEEK2(dev + port);
33 // u16 y0 = PEEK2(d + 0xa); 39 default: return dev[port];
34 // u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK; 40 }
35 // if(ctrl & 0x80) {
36 // u16 x1 = SCREEN_WIDTH - 1;
37 // u16 y1 = SCREEN_HEIGHT - 1;
38 // if(ctrl & 0x10) x1 = x0, x0 = 0;
39 // if(ctrl & 0x20) y1 = y0, y0 = 0;
40 // PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
41 // } else {
42 // PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
43 // if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */
44 // if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */
45 // }
46 // break;
47 // }
48 // case 0xf: {
49 // u16 x, y, dx, dy, addr;
50 // u8 n, twobpp = !!(d[0xf] & 0x80);
51 // x = PEEK2(d + 0x8);
52 // y = PEEK2(d + 0xa);
53 // addr = PEEK2(d + 0xc);
54 // n = d[0x6] >> 4;
55 // dx = (d[0x6] & 0x01) << 3;
56 // dy = (d[0x6] & 0x02) << 2;
57 // if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
58 // return;
59 // }
60 // u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK;
61 // u8 color = d[0xf] & 0xf;
62 // u8 flipx = d[0xf] & 0x10;
63 // u8 flipy = d[0xf] & 0x20;
64 // for(size_t i = 0; i <= n; i++) {
65 // u8 *sprite = &ram[addr];
66 // if (twobpp) {
67 // PROF(ppu_2bpp(layer,
68 // x + dy * i,
69 // y + dx * i,
70 // sprite,
71 // color,
72 // flipx, flipy), ppu_chr_cycles);
73 // } else {
74 // PROF(ppu_1bpp(layer,
75 // x + dy * i,
76 // y + dx * i,
77 // sprite,
78 // color,
79 // flipx, flipy), ppu_icn_cycles);
80 // }
81 // addr += (d[0x6] & 0x04) << (1 + twobpp);
82 // }
83 // POKE2(d + 0xc, addr); /* auto addr+length */
84 // POKE2(d + 0x8, x + dx); /* auto x+8 */
85 // POKE2(d + 0xa, y + dy); /* auto y+8 */
86 // break;
87 // }
88 // }
89} 41}
90 42
91u8 43void
92audio_dei(int instance, u8 *d, u8 port) { 44deo_screen(u8 *dev, u8 port) {
93 // AudioChannel *c = &channels[instance]; 45 switch(port) {
94 // switch(port) { 46 case 0xe: {
95 // // case 0x4: return apu_get_vu(instance); 47 u8 ctrl = dev[0xe];
96 // case 0x2: { 48 u8 color = ctrl & 0x3;
97 // POKE2(d + 0x2, c->pos); 49 u16 x0 = PEEK2(dev + 0x8);
98 // c->pos <<= 12; // fixed point. 50 u16 y0 = PEEK2(dev + 0xa);
99 // break; 51 u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
100 // } 52 if(ctrl & 0x80) {
101 // } 53 u16 x1 = SCREEN_WIDTH - 1;
102 return d[port]; 54 u16 y1 = SCREEN_HEIGHT - 1;
55 if(ctrl & 0x10) x1 = x0, x0 = 0;
56 if(ctrl & 0x20) y1 = y0, y0 = 0;
57 PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
58 } else {
59 PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
60 if(dev[0x6] & 0x1) POKE2(dev + 0x8, x0 + 1); /* auto x+1 */
61 if(dev[0x6] & 0x2) POKE2(dev + 0xa, y0 + 1); /* auto y+1 */
62 }
63 break;
64 }
65 case 0xf: {
66 u16 x, y, dx, dy, addr;
67 u8 n, twobpp = !!(dev[0xf] & 0x80);
68 x = PEEK2(dev + 0x8);
69 y = PEEK2(dev + 0xa);
70 addr = PEEK2(dev + 0xc);
71 n = dev[0x6] >> 4;
72 dx = (dev[0x6] & 0x01) << 3;
73 dy = (dev[0x6] & 0x02) << 2;
74 if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
75 return;
76 }
77 u8 *layer = (dev[0xf] & 0x40) ? FG_BACK : BG_BACK;
78 u8 color = dev[0xf] & 0xf;
79 u8 flipx = dev[0xf] & 0x10;
80 u8 flipy = dev[0xf] & 0x20;
81 for(size_t i = 0; i <= n; i++) {
82 u8 *sprite = &uxn_ram[addr];
83 if (twobpp) {
84 PROF(ppu_2bpp(layer,
85 x + dy * i,
86 y + dx * i,
87 sprite,
88 color,
89 flipx, flipy), ppu_chr_cycles);
90 } else {
91 PROF(ppu_1bpp(layer,
92 x + dy * i,
93 y + dx * i,
94 sprite,
95 color,
96 flipx, flipy), ppu_icn_cycles);
97 }
98 addr += (dev[0x6] & 0x04) << (1 + twobpp);
99 }
100 POKE2(dev + 0xc, addr); /* auto addr+length */
101 POKE2(dev + 0x8, x + dx); /* auto x+8 */
102 POKE2(dev + 0xa, y + dy); /* auto y+8 */
103 break;
104 }
105 }
103} 106}
104 107
105void 108void
106audio_deo(int instance, u8 *d, u8 port, Uxn *u) { 109deo_system(u8 *dev, u8 port) {
107 // AudioChannel *c = &channels[instance]; 110 switch(port) {
108 // if (port == 0xf) { 111 case 0x3: {
109 // u16 length = 0; 112 // TODO: Rom bank switching (Needs testing).
110 // u16 adsr = 0; 113 u16 addr = PEEK2(dev + 0x2);
111 // u16 addr = 0; 114 if(uxn_ram[addr] == 0x01) {
112 // u8 pitch = d[0xf] & 0x7f; 115 u16 i, length = PEEK2(uxn_ram + addr + 1);
113 // adsr = PEEK2(d + 0x8); 116 u16 a_page = PEEK2(uxn_ram + addr + 1 + 2);
114 // length = PEEK2(d + 0xa); 117 u16 a_addr = PEEK2(uxn_ram + addr + 1 + 4);
115 // addr = PEEK2(d + 0xc); 118 u16 b_addr = PEEK2(uxn_ram + addr + 1 + 8);
116 // u8 *data = &u->ram[addr]; 119 u8 *rom = uxn_rom + (a_page % RAM_PAGES) * 0x10000;
117 // u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3; 120 for(i = 0; i < length; i++) {
118 // bool loop = !(d[0xf] & 0x80); 121 uxn_ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
119 // update_channel(c, data, length, pitch, adsr, vol, loop); 122 }
120 // } 123 }
124 } break;
125 case 0x4: {
126 // TODO: Set wst_ptr, but is it the offset instead?
127 } break;
128 case 0x5: {
129 // TODO: Set rst_ptr, but is it the offset instead?
130 } break;
131 case 0x8:
132 case 0x9:
133 case 0xa:
134 case 0xb:
135 case 0xc:
136 case 0xd: {
137 // Setup RGB palette.
138 putcolors(&dev[0x8]);
139 } break;
140 case 0xe: {
141 // TODO: System inspect.
142 } break;
143 }
121} 144}
122 145
123u8 146u16
124datetime_dei(u8 *d, u8 port) { 147dei_system(u8 *dev, u8 port) {
148 switch (port) {
149 case 0x0:
150 case 0x2:
151 case 0x6:
152 case 0x8:
153 case 0xa:
154 case 0xc: return PEEK2(dev + port);
155 case 0x4: {
156 // TODO: Return wst_ptr, but is it the offset instead?
157 } break;
158 case 0x5: {
159 // TODO: Return rst_ptr, but is it the offset instead?
160 } break;
161 }
162 return dev[port];
163}
164
165u16
166dei_datetime(u8 *dev, u8 port) {
125 struct tm *t = gmtime(&seconds); 167 struct tm *t = gmtime(&seconds);
126 switch(port) { 168 switch(port) {
127 case 0x0: return (t->tm_year + 1900) >> 8; 169 case 0x0: return (t->tm_year + 1900);
128 case 0x1: return (t->tm_year + 1900); 170 case 0x1: return (t->tm_year + 1900) >> 8;
129 case 0x2: return t->tm_mon; 171 case 0x2: return t->tm_mon;
130 case 0x3: return t->tm_mday; 172 case 0x3: return t->tm_mday;
131 case 0x4: return t->tm_hour; 173 case 0x4: return t->tm_hour;
132 case 0x5: return t->tm_min; 174 case 0x5: return t->tm_min;
133 case 0x6: return t->tm_sec; 175 case 0x6: return t->tm_sec;
134 case 0x7: return t->tm_wday; 176 case 0x7: return t->tm_wday;
135 case 0x8: return t->tm_yday >> 8; 177 case 0x8: return t->tm_yday;
136 case 0x9: return t->tm_yday; 178 case 0x9: return t->tm_yday >> 8;
137 case 0xa: return t->tm_isdst; 179 case 0xa: return t->tm_isdst;
138 default: return d[port]; 180 default: return dev[port];
139 } 181 }
140} 182}
141 183
142u8 184u16
143file_dei(u8 id, u8 *d, u8 port) { 185dei_audio(u8 *dev, u8 port) {
144 // UxnFile *c = &uxn_file[id]; 186 size_t idx = (dev - (device_data + 0x30)) / 16;
145 // u16 res; 187 AudioChannel *c = &channels[idx];
146 // switch(port) { 188 switch(port) {
147 // case 0xc: 189 case 0x0:
148 // case 0xd: { 190 case 0x8:
149 // res = file_read(c, &d[port], 1); 191 case 0xa:
150 // POKE2(d + 0x2, res); 192 case 0x2: // TODO: return the position
151 // break; 193 case 0xc: return PEEK2(dev + port);
152 // } 194 // case 0x2: {
153 // } 195 // POKE2(d + 0x2, c->pos);
154 return d[port]; 196 // c->pos <<= 12; // fixed point.
155} 197 // break;
156 198 // }
157void 199 // case 0x4: return apu_get_vu(idx);
158file_deo(u8 id, u8 *ram, u8 *d, u8 port) { 200 // TODO: return the current envelope loudness (0x00-0xff).
159 // u16 a, b, res; 201 default: return dev[port];
160 // UxnFile *f = &uxn_file[id]; 202 }
161 // switch(port) { 203 return dev[port];
162 // case 0x5: {
163 // a = PEEK2(d + 0x4);
164 // b = PEEK2(d + 0xa);
165 // if(b > 0x10000 - a) {
166 // b = 0x10000 - a;
167 // }
168 // res = file_stat(f, &ram[a], b);
169 // POKE2(d + 0x2, res);
170 // } break;
171 // case 0x6: {
172 // // TODO: no file deletion for now
173 // // res = file_delete();
174 // // POKE2(d + 0x2, res);
175 // } break;
176 // case 0x9: {
177 // a = PEEK2(d + 0x8);
178 // res = file_init(f, &ram[a]);
179 // POKE2(d + 0x2, res);
180 // } break;
181 // case 0xd: {
182 // a = PEEK2(d + 0xc);
183 // b = PEEK2(d + 0xa);
184 // if(b > 0x10000 - a) {
185 // b = 0x10000 - a;
186 // }
187 // res = file_read(f, &ram[a], b);
188 // POKE2(d + 0x2, res);
189 // } break;
190 // case 0xf: {
191 // a = PEEK2(d + 0xe);
192 // b = PEEK2(d + 0xa);
193 // if(b > 0x10000 - a) {
194 // b = 0x10000 - a;
195 // }
196 // res = file_write(f, &ram[a], b, d[0x7]);
197 // POKE2(d + 0x2, res);
198 // } break;
199 // }
200} 204}
201 205
202void 206void
203console_deo(u8 *d, u8 port) { 207deo_audio(u8 *dev, u8 port) {
204 // switch(port) { 208 size_t idx = (dev - (device_data + 0x30)) / 16;
205 // case 0x8: 209 txt_printf("IDX: %d\n", idx);
206 // txt_putc(d[port]); 210 AudioChannel *c = &channels[idx];
207 // return; 211 if (port == 0xf) {
208 // case 0x9: 212 u16 length = 0;
209 // txt_printf("ERROR: %c"); 213 u16 adsr = 0;
210 // txt_putc(d[port]); 214 u16 addr = 0;
211 // return; 215 u8 pitch = dev[0xf] & 0x7f;
212 // } 216 adsr = PEEK2(dev + 0x8);
217 length = PEEK2(dev + 0xa);
218 addr = PEEK2(dev + 0xc);
219 u8 *data = &uxn_ram[addr];
220 u32 vol = MAX(dev[0xe] >> 4, dev[0xe] & 0xf) * 4 / 3;
221 bool loop = !(dev[0xf] & 0x80);
222 update_channel(c, data, length, pitch, adsr, vol, loop);
223 }
213} 224}
214 225
215#define RAM_PAGES 0x10 226u16
216 227dei_file(u8 *dev, u8 port) {
217static void 228 size_t idx = (dev - (device_data + 0xa0)) / 16;
218system_cmd(u8 *ram, u16 addr) { 229 UxnFile *c = &uxn_file[idx];
219 if(ram[addr] == 0x01) { 230 switch(port) {
220 // NOTE: Handle rom paging on a case by case basis if a rom has to be 231 case 0x0:
221 // split in multiple chunks. The GBA compiler doesn't like allocating 232 case 0x2:
222 // big arrays, but it's fine if we split it into chunks of 64KB, for 233 case 0x4:
223 // example. 234 case 0x8:
224 // 235 case 0xa:
225 // u16 i, length = PEEK2(ram + addr + 1); 236 case 0xe: return PEEK2(dev + port);
226 // u16 a_page = PEEK2(ram + addr + 1 + 2); 237 case 0xc:
227 // u16 a_addr = PEEK2(ram + addr + 1 + 4); 238 case 0xd: {
228 // u16 b_addr = PEEK2(ram + addr + 1 + 8); 239 u16 res = file_read(c, &dev[port], 1);
229 // u8 *rom = uxn_rom; 240 POKE2(dev + 0x2, res);
230 // for(i = 0; i < length; i++) { 241 return res;
231 // switch (a_page % RAM_PAGES) { 242 }
232 // case 0: { rom = uxn_rom; } break;
233 // case 1: { rom = uxn_rom_2; } break;
234 // case 2: { rom = uxn_rom_3; } break;
235 // case 3: { rom = uxn_rom_4; } break;
236 // case 4: { rom = uxn_rom_5; } break;
237 // case 5: { rom = uxn_rom_6; } break;
238 // case 6: { rom = uxn_rom_7; } break;
239 // }
240 // ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
241 // }
242 } 243 }
244 return dev[port];
243} 245}
244 246
245void 247void
246system_deo(Uxn *u, u8 *d, u8 port) { 248deo_file(u8 *dev, u8 port) {
247 // switch(port) { 249 size_t idx = (dev - (device_data + 0xa0)) / 16;
248 // case 0x3: { 250 u16 a, b, res;
249 // system_cmd(u->ram, PEEK2(d + 2)); 251 UxnFile *f = &uxn_file[idx];
250 // } break; 252 switch(port) {
251 // } 253 case 0x5: {
252} 254 a = PEEK2(dev + 0x4);
253 255 b = PEEK2(dev + 0xa);
254u8 256 if(b > 0x10000 - a) {
255uxn_dei(Uxn *u, u8 addr) { 257 b = 0x10000 - a;
256 u8 p = addr & 0x0f, d = addr & 0xf0; 258 }
257 switch(d) { 259 res = file_stat(f, &uxn_ram[a], b);
258 case 0x20: return screen_dei(&u->dev[d], p); 260 POKE2(dev + 0x2, res);
259 case 0x30: return audio_dei(0, &u->dev[d], p); 261 } break;
260 case 0x40: return audio_dei(1, &u->dev[d], p); 262 case 0x6: {
261 case 0x50: return audio_dei(2, &u->dev[d], p); 263 // TODO: no file deletion for now
262 case 0x60: return audio_dei(3, &u->dev[d], p); 264 // res = file_delete();
263 case 0xa0: return file_dei(0, &u->dev[d], p); 265 // POKE2(dev + 0x2, res);
264 case 0xb0: return file_dei(1, &u->dev[d], p); 266 } break;
265 case 0xc0: return datetime_dei(&u->dev[d], p); 267 case 0x9: {
268 a = PEEK2(dev + 0x8);
269 res = file_init(f, &uxn_ram[a]);
270 POKE2(dev + 0x2, res);
271 } break;
272 case 0xd: {
273 a = PEEK2(dev + 0xc);
274 b = PEEK2(dev + 0xa);
275 if(b > 0x10000 - a) {
276 b = 0x10000 - a;
277 }
278 res = file_read(f, &uxn_ram[a], b);
279 POKE2(dev + 0x2, res);
280 } break;
281 case 0xf: {
282 a = PEEK2(dev + 0xe);
283 b = PEEK2(dev + 0xa);
284 if(b > 0x10000 - a) {
285 b = 0x10000 - a;
286 }
287 res = file_write(f, &uxn_ram[a], b, dev[0x7]);
288 POKE2(dev + 0x2, res);
289 } break;
266 } 290 }
267 return u->dev[addr];
268} 291}
269 292
270void 293void
271uxn_deo(Uxn *u, u8 addr) { 294deo_stub(u8 *dev, u8 port) {
272 u8 p = addr & 0x0f, d = addr & 0xf0; 295 (void)dev;
273 switch(d) { 296 (void)port;
274 case 0x00:
275 system_deo(u, &u->dev[d], p);
276 if(p > 0x7 && p < 0xe) {
277 putcolors(&u->dev[0x8]);
278 }
279 break;
280 case 0x10: console_deo(&u->dev[d], p); break;
281 case 0x20: screen_deo(u->ram, &u->dev[d], p); break;
282 case 0x30: audio_deo(0, &u->dev[d], p, u); break;
283 case 0x40: audio_deo(1, &u->dev[d], p, u); break;
284 case 0x50: audio_deo(2, &u->dev[d], p, u); break;
285 case 0x60: audio_deo(3, &u->dev[d], p, u); break;
286 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break;
287 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break;
288 }
289} 297}
290 298
299u16
300dei_stub(u8 *dev, u8 port) {
301 if (port == 0) {
302 return PEEK2(dev);
303 }
304 return dev[port];
305}
diff --git a/src/main.c b/src/main.c
index 96ced87..32400f9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -17,13 +17,12 @@
17 17
18#include "uxn-core.c" 18#include "uxn-core.c"
19 19
20#include "uxn.c" 20#include "rom.c"
21#include "ppu.c" 21#include "ppu.c"
22#include "apu.c" 22#include "apu.c"
23#include "file.c" 23#include "file.c"
24#include "text.h" 24#include "text.h"
25 25
26#include "rom.c"
27#include "config.c" 26#include "config.c"
28#include "profiling.c" 27#include "profiling.c"
29#include "input.c" 28#include "input.c"
@@ -31,297 +30,6 @@
31#include "debug.c" 30#include "debug.c"
32 31
33void 32void
34deo_console(u8 *dev, u8 port) {
35 switch(port) {
36 case 0x8:
37 txt_putc(dev[port]);
38 return;
39 case 0x9:
40 txt_printf("ERROR: %c");
41 txt_putc(dev[port]);
42 return;
43 }
44}
45
46u16
47dei_screen(u8 *dev, u8 port) {
48 switch(port) {
49 case 0x0:
50 case 0x8:
51 case 0xa:
52 case 0xc: return PEEK2(dev + port);
53 case 0x2: return SCREEN_WIDTH;
54 case 0x4: return SCREEN_HEIGHT;
55 default: return dev[port];
56 }
57}
58
59u16
60dei_mouse(u8 *dev, u8 port) {
61 switch(port) {
62 case 0x0:
63 case 0x2:
64 case 0x4:
65 case 0xa:
66 case 0xc: return PEEK2(dev + port);
67 default: return dev[port];
68 }
69}
70
71void
72deo_screen(u8 *dev, u8 port) {
73 switch(port) {
74 case 0xe: {
75 u8 ctrl = dev[0xe];
76 u8 color = ctrl & 0x3;
77 u16 x0 = PEEK2(dev + 0x8);
78 u16 y0 = PEEK2(dev + 0xa);
79 u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
80 if(ctrl & 0x80) {
81 u16 x1 = SCREEN_WIDTH - 1;
82 u16 y1 = SCREEN_HEIGHT - 1;
83 if(ctrl & 0x10) x1 = x0, x0 = 0;
84 if(ctrl & 0x20) y1 = y0, y0 = 0;
85 PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
86 } else {
87 PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
88 if(dev[0x6] & 0x1) POKE2(dev + 0x8, x0 + 1); /* auto x+1 */
89 if(dev[0x6] & 0x2) POKE2(dev + 0xa, y0 + 1); /* auto y+1 */
90 }
91 break;
92 }
93 case 0xf: {
94 u16 x, y, dx, dy, addr;
95 u8 n, twobpp = !!(dev[0xf] & 0x80);
96 x = PEEK2(dev + 0x8);
97 y = PEEK2(dev + 0xa);
98 addr = PEEK2(dev + 0xc);
99 n = dev[0x6] >> 4;
100 dx = (dev[0x6] & 0x01) << 3;
101 dy = (dev[0x6] & 0x02) << 2;
102 if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
103 return;
104 }
105 u8 *layer = (dev[0xf] & 0x40) ? FG_BACK : BG_BACK;
106 u8 color = dev[0xf] & 0xf;
107 u8 flipx = dev[0xf] & 0x10;
108 u8 flipy = dev[0xf] & 0x20;
109 for(size_t i = 0; i <= n; i++) {
110 u8 *sprite = &uxn_ram[addr];
111 if (twobpp) {
112 PROF(ppu_2bpp(layer,
113 x + dy * i,
114 y + dx * i,
115 sprite,
116 color,
117 flipx, flipy), ppu_chr_cycles);
118 } else {
119 PROF(ppu_1bpp(layer,
120 x + dy * i,
121 y + dx * i,
122 sprite,
123 color,
124 flipx, flipy), ppu_icn_cycles);
125 }
126 addr += (dev[0x6] & 0x04) << (1 + twobpp);
127 }
128 POKE2(dev + 0xc, addr); /* auto addr+length */
129 POKE2(dev + 0x8, x + dx); /* auto x+8 */
130 POKE2(dev + 0xa, y + dy); /* auto y+8 */
131 break;
132 }
133 }
134}
135
136void
137deo_system(u8 *dev, u8 port) {
138 switch(port) {
139 case 0x3: {
140 // TODO: Rom bank switching.
141 } break;
142 case 0x4: {
143 // TODO: Set wst_ptr, but is it the offset instead?
144 } break;
145 case 0x5: {
146 // TODO: Set rst_ptr, but is it the offset instead?
147 } break;
148 case 0x8:
149 case 0x9:
150 case 0xa:
151 case 0xb:
152 case 0xc:
153 case 0xd: {
154 // Setup RGB palette.
155 putcolors(&dev[0x8]);
156 } break;
157 case 0xe: {
158 // TODO: System inspect.
159 } break;
160 }
161}
162
163u16
164dei_system(u8 *dev, u8 port) {
165 switch (port) {
166 case 0x0:
167 case 0x2:
168 case 0x6:
169 case 0x8:
170 case 0xa:
171 case 0xc: return PEEK2(dev + port);
172 case 0x4: {
173 // TODO: Return wst_ptr, but is it the offset instead?
174 } break;
175 case 0x5: {
176 // TODO: Return rst_ptr, but is it the offset instead?
177 } break;
178 default: { return dev[port]; } break;
179 }
180}
181
182u16
183dei_datetime(u8 *dev, u8 port) {
184 struct tm *t = gmtime(&seconds);
185 switch(port) {
186 case 0x0: return (t->tm_year + 1900);
187 case 0x1: return (t->tm_year + 1900) >> 8;
188 case 0x2: return t->tm_mon;
189 case 0x3: return t->tm_mday;
190 case 0x4: return t->tm_hour;
191 case 0x5: return t->tm_min;
192 case 0x6: return t->tm_sec;
193 case 0x7: return t->tm_wday;
194 case 0x8: return t->tm_yday;
195 case 0x9: return t->tm_yday >> 8;
196 case 0xa: return t->tm_isdst;
197 default: return dev[port];
198 }
199}
200
201u16
202dei_audio(u8 *dev, u8 port) {
203 size_t idx = (dev - (device_data + 0x30)) / 16;
204 AudioChannel *c = &channels[idx];
205 switch(port) {
206 case 0x0:
207 case 0x8:
208 case 0xa:
209 case 0x2: // TODO: return the position
210 case 0xc: return PEEK2(dev + port);
211 // case 0x2: {
212 // POKE2(d + 0x2, c->pos);
213 // c->pos <<= 12; // fixed point.
214 // break;
215 // }
216 // case 0x4: return apu_get_vu(idx);
217 // TODO: return the current envelope loudness (0x00-0xff).
218 default: return dev[port];
219 }
220 return dev[port];
221}
222
223void
224deo_audio(u8 *dev, u8 port) {
225 size_t idx = (dev - (device_data + 0x30)) / 16;
226 txt_printf("IDX: %d\n", idx);
227 AudioChannel *c = &channels[idx];
228 if (port == 0xf) {
229 u16 length = 0;
230 u16 adsr = 0;
231 u16 addr = 0;
232 u8 pitch = dev[0xf] & 0x7f;
233 adsr = PEEK2(dev + 0x8);
234 length = PEEK2(dev + 0xa);
235 addr = PEEK2(dev + 0xc);
236 u8 *data = &uxn_ram[addr];
237 u32 vol = MAX(dev[0xe] >> 4, dev[0xe] & 0xf) * 4 / 3;
238 bool loop = !(dev[0xf] & 0x80);
239 update_channel(c, data, length, pitch, adsr, vol, loop);
240 }
241}
242
243u16
244dei_file(u8 *dev, u8 port) {
245 size_t idx = (dev - (device_data + 0xa0)) / 16;
246 UxnFile *c = &uxn_file[idx];
247 switch(port) {
248 case 0x0:
249 case 0x2:
250 case 0x4:
251 case 0x8:
252 case 0xa:
253 case 0xe: return PEEK2(dev + port);
254 case 0xc:
255 case 0xd: {
256 u16 res = file_read(c, &dev[port], 1);
257 POKE2(dev + 0x2, res);
258 return res;
259 }
260 }
261 return dev[port];
262}
263
264void
265deo_file(u8 *dev, u8 port) {
266 size_t idx = (dev - (device_data + 0xa0)) / 16;
267 u16 a, b, res;
268 UxnFile *f = &uxn_file[idx];
269 switch(port) {
270 case 0x5: {
271 a = PEEK2(dev + 0x4);
272 b = PEEK2(dev + 0xa);
273 if(b > 0x10000 - a) {
274 b = 0x10000 - a;
275 }
276 res = file_stat(f, &uxn_ram[a], b);
277 POKE2(dev + 0x2, res);
278 } break;
279 case 0x6: {
280 // TODO: no file deletion for now
281 // res = file_delete();
282 // POKE2(dev + 0x2, res);
283 } break;
284 case 0x9: {
285 a = PEEK2(dev + 0x8);
286 res = file_init(f, &uxn_ram[a]);
287 POKE2(dev + 0x2, res);
288 } break;
289 case 0xd: {
290 a = PEEK2(dev + 0xc);
291 b = PEEK2(dev + 0xa);
292 if(b > 0x10000 - a) {
293 b = 0x10000 - a;
294 }
295 res = file_read(f, &uxn_ram[a], b);
296 POKE2(dev + 0x2, res);
297 } break;
298 case 0xf: {
299 a = PEEK2(dev + 0xe);
300 b = PEEK2(dev + 0xa);
301 if(b > 0x10000 - a) {
302 b = 0x10000 - a;
303 }
304 res = file_write(f, &uxn_ram[a], b, dev[0x7]);
305 POKE2(dev + 0x2, res);
306 } break;
307 }
308}
309
310void
311deo_stub(u8 *dev, u8 port) {
312 (void)dev;
313 (void)port;
314}
315
316u16
317dei_stub(u8 *dev, u8 port) {
318 if (port == 0) {
319 return PEEK2(dev);
320 }
321 return dev[port];
322}
323
324void
325init_uxn() { 33init_uxn() {
326 // Initialize uxn. 34 // Initialize uxn.
327 u32 fill = 0; 35 u32 fill = 0;
@@ -339,30 +47,29 @@ init_uxn() {
339 47
340 // Setup deo/dei maps. 48 // Setup deo/dei maps.
341 for (size_t i = 0; i < 16; i++) { 49 for (size_t i = 0; i < 16; i++) {
342 deo_map[i] = deo_stub; 50 deo_map[i] = (uintptr_t) deo_stub;
343 dei_map[i] = dei_stub; 51 dei_map[i] = (uintptr_t) dei_stub;
344 } 52 }
345 deo_map[0x0] = deo_system; 53 deo_map[0x0] = (uintptr_t) deo_system;
346 dei_map[0x0] = dei_system; 54 dei_map[0x0] = (uintptr_t) dei_system;
347 deo_map[0x1] = deo_console; 55 deo_map[0x1] = (uintptr_t) deo_console;
348 deo_map[0x2] = deo_screen; 56 deo_map[0x2] = (uintptr_t) deo_screen;
349 dei_map[0x2] = dei_screen; 57 dei_map[0x2] = (uintptr_t) dei_screen;
350 deo_map[0x3] = deo_audio; 58 deo_map[0x3] = (uintptr_t) deo_audio;
351 dei_map[0x3] = dei_audio; 59 dei_map[0x3] = (uintptr_t) dei_audio;
352 deo_map[0x4] = deo_audio; 60 deo_map[0x4] = (uintptr_t) deo_audio;
353 dei_map[0x4] = dei_audio; 61 dei_map[0x4] = (uintptr_t) dei_audio;
354 deo_map[0x5] = deo_audio; 62 deo_map[0x5] = (uintptr_t) deo_audio;
355 dei_map[0x5] = dei_audio; 63 dei_map[0x5] = (uintptr_t) dei_audio;
356 deo_map[0x6] = deo_audio; 64 deo_map[0x6] = (uintptr_t) deo_audio;
357 dei_map[0x6] = dei_audio; 65 dei_map[0x6] = (uintptr_t) dei_audio;
358 deo_map[0xa] = deo_file; 66 deo_map[0xa] = (uintptr_t) deo_file;
359 dei_map[0xa] = dei_file; 67 dei_map[0xa] = (uintptr_t) dei_file;
360 deo_map[0xb] = deo_file; 68 deo_map[0xb] = (uintptr_t) deo_file;
361 dei_map[0xb] = dei_file; 69 dei_map[0xb] = (uintptr_t) dei_file;
362 dei_map[0xc] = dei_datetime; 70 dei_map[0xc] = (uintptr_t) dei_datetime;
363 dei_map[0x9] = dei_mouse; 71 dei_map[0x9] = (uintptr_t) dei_mouse;
364} 72}
365
366int 73int
367main(void) { 74main(void) {
368 // Adjust system wait times. 75 // Adjust system wait times.
diff --git a/src/uxn-core.c b/src/uxn-core.c
index 6ff4c50..8a2c971 100644
--- a/src/uxn-core.c
+++ b/src/uxn-core.c
@@ -30,3 +30,7 @@ extern u8 device_data[256];
30 30
31EWRAM_BSS 31EWRAM_BSS
32u8 uxn_ram[KB(64)]; 32u8 uxn_ram[KB(64)];
33
34#define PAGE_PROGRAM 0x0100
35#define POKE2(d, v) do { (d)[0] = (v) >> 8; (d)[1] = (v); } while(0)
36#define PEEK2(d) ((d)[0] << 8 | (d)[1])
diff --git a/src/uxn.c b/src/uxn.c
deleted file mode 100644
index d525ff1..0000000
--- a/src/uxn.c
+++ /dev/null
@@ -1,117 +0,0 @@
1#include "uxn.h"
2
3/*
4Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards
5
6Permission to use, copy, modify, and distribute this software for any
7purpose with or without fee is hereby granted, provided that the above
8copyright notice and this permission notice appear in all copies.
9
10THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11WITH REGARD TO THIS SOFTWARE.
12*/
13
14#define T s->dat[s->ptr - 1]
15#define N s->dat[s->ptr - 2]
16#define L s->dat[s->ptr - 3]
17#define H2 PEEK2(s->dat + s->ptr - 3)
18#define T2 PEEK2(s->dat + s->ptr - 2)
19#define N2 PEEK2(s->dat + s->ptr - 4)
20#define L2 PEEK2(s->dat + s->ptr - 6)
21
22/* Registers
23
24[ . ][ . ][ . ][ L ][ N ][ T ] <
25[ . ][ . ][ . ][ H2 ][ T ] <
26[ L2 ][ N2 ][ T2 ] <
27
28*/
29
30
31u16 deo_mask[] = {0xff08, 0x0300, 0xc028, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x0000, 0x0000, 0xa260, 0xa260, 0x0000, 0x0000, 0x0000, 0x0000};
32u16 dei_mask[] = {0x0000, 0x0000, 0x003c, 0x0014, 0x0014, 0x0014, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0x0000, 0x0000, 0x0000};
33
34#define POKE2(d, v) { (d)[0] = (v) >> 8; (d)[1] = (v); }
35#define PEEK2(d) ((d)[0] << 8 | (d)[1])
36#define HALT(c) { return uxn_halt(u, ins, (c), pc - 1); }
37#define SET(mul, add) { if(mul > s->ptr) HALT(1) tmp = s->ptr + k * mul + add; if(tmp > 254) HALT(2) s->ptr = tmp; }
38#define PUT(o, v) { s->dat[(u8)(s->ptr - 1 - (o))] = (v); }
39#define PUT2(o, v) { tmp = (v); s->dat[(u8)(s->ptr - o - 2)] = tmp >> 8; s->dat[(u8)(s->ptr - o - 1)] = tmp; }
40#define PUSH(stack, v) { if(s->ptr > 254) HALT(2) stack->dat[stack->ptr++] = (v); }
41#define PUSH2(stack, v) { if(s->ptr > 253) HALT(2) tmp = (v); stack->dat[stack->ptr] = tmp >> 8; stack->dat[stack->ptr + 1] = tmp; stack->ptr += 2; }
42#define DEO(a, b) { u->dev[(a)] = (b); if((deo_mask[(a) >> 4] >> ((a) & 0xf)) & 0x1) uxn_deo(u, (a)); }
43#define DEI(a, b) { PUT((a), ((dei_mask[(b) >> 4] >> ((b) & 0xf)) & 0x1) ? uxn_dei(u, (b)) : u->dev[(b)]) }
44
45IWRAM_CODE
46int
47uxn_eval(Uxn *u, u16 pc) {
48 u8 ins, opc, k;
49 u16 t, n, l, tmp;
50 Stack *s;
51 if(!pc || u->dev[0x0f]) return 0;
52 for(;;) {
53 ins = u->ram[pc++];
54 k = !!(ins & 0x80);
55 s = ins & 0x40 ? u->rst : u->wst;
56 opc = !(ins & 0x1f) ? 0 - (ins >> 5) : ins & 0x3f;
57 switch(opc) {
58 /* IMM */
59 case 0x00: /* BRK */ return 1;
60 case 0xff: /* JCI */ pc += !!s->dat[--s->ptr] * PEEK2(u->ram + pc) + 2; break;
61 case 0xfe: /* JMI */ pc += PEEK2(u->ram + pc) + 2; break;
62 case 0xfd: /* JSI */ PUSH2(u->rst, pc + 2) pc += PEEK2(u->ram + pc) + 2; break;
63 case 0xfc: /* LIT */ PUSH(s, u->ram[pc++]) break;
64 case 0xfb: /* LIT2 */ PUSH2(s, PEEK2(u->ram + pc)) pc += 2; break;
65 case 0xfa: /* LITr */ PUSH(s, u->ram[pc++]) break;
66 case 0xf9: /* LIT2r */ PUSH2(s, PEEK2(u->ram + pc)) pc += 2; break;
67 /* ALU */
68 case 0x01: /* INC */ t=T; SET(1, 0) PUT(0, t + 1) break; case 0x21: t=T2; SET(2, 0) PUT2(0, t + 1) break;
69 case 0x02: /* POP */ SET(1,-1) break; case 0x22: SET(2,-2) break;
70 case 0x03: /* NIP */ t=T; SET(2,-1) PUT(0, t) break; case 0x23: t=T2; SET(4,-2) PUT2(0, t) break;
71 case 0x04: /* SWP */ t=T;n=N; SET(2, 0) PUT(0, n) PUT(1, t) break; case 0x24: t=T2;n=N2; SET(4, 0) PUT2(0, n) PUT2(2, t) break;
72 case 0x05: /* ROT */ t=T;n=N;l=L; SET(3, 0) PUT(0, l) PUT(1, t) PUT(2, n) break; case 0x25: t=T2;n=N2;l=L2; SET(6, 0) PUT2(0, l) PUT2(2, t) PUT2(4, n) break;
73 case 0x06: /* DUP */ t=T; SET(1, 1) PUT(0, t) PUT(1, t) break; case 0x26: t=T2; SET(2, 2) PUT2(0, t) PUT2(2, t) break;
74 case 0x07: /* OVR */ t=T;n=N; SET(2, 1) PUT(0, n) PUT(1, t) PUT(2, n) break; case 0x27: t=T2;n=N2; SET(4, 2) PUT2(0, n) PUT2(2, t) PUT2(4, n) break;
75 case 0x08: /* EQU */ t=T;n=N; SET(2,-1) PUT(0, n == t) break; case 0x28: t=T2;n=N2; SET(4,-3) PUT(0, n == t) break;
76 case 0x09: /* NEQ */ t=T;n=N; SET(2,-1) PUT(0, n != t) break; case 0x29: t=T2;n=N2; SET(4,-3) PUT(0, n != t) break;
77 case 0x0a: /* GTH */ t=T;n=N; SET(2,-1) PUT(0, n > t) break; case 0x2a: t=T2;n=N2; SET(4,-3) PUT(0, n > t) break;
78 case 0x0b: /* LTH */ t=T;n=N; SET(2,-1) PUT(0, n < t) break; case 0x2b: t=T2;n=N2; SET(4,-3) PUT(0, n < t) break;
79 case 0x0c: /* JMP */ t=T; SET(1,-1) pc += (s8)t; break; case 0x2c: t=T2; SET(2,-2) pc = t; break;
80 case 0x0d: /* JCN */ t=T;n=N; SET(2,-2) pc += !!n * (s8)t; break; case 0x2d: t=T2;n=L; SET(3,-3) if(n) pc = t; break;
81 case 0x0e: /* JSR */ t=T; SET(1,-1) PUSH2(u->rst, pc) pc += (s8)t; break; case 0x2e: t=T2; SET(2,-2) PUSH2(u->rst, pc) pc = t; break;
82 case 0x0f: /* STH */ t=T; SET(1,-1) PUSH((ins & 0x40 ? u->wst : u->rst), t) break; case 0x2f: t=T2; SET(2,-2) PUSH2((ins & 0x40 ? u->wst : u->rst), t) break;
83 case 0x10: /* LDZ */ t=T; SET(1, 0) PUT(0, u->ram[t]) break; case 0x30: t=T; SET(1, 1) PUT2(0, PEEK2(u->ram + t)) break;
84 case 0x11: /* STZ */ t=T;n=N; SET(2,-2) u->ram[t] = n; break; case 0x31: t=T;n=H2; SET(3,-3) POKE2(u->ram + t, n) break;
85 case 0x12: /* LDR */ t=T; SET(1, 0) PUT(0, u->ram[pc + (s8)t]) break; case 0x32: t=T; SET(1, 1) PUT2(0, PEEK2(u->ram + pc + (s8)t)) break;
86 case 0x13: /* STR */ t=T;n=N; SET(2,-2) u->ram[pc + (s8)t] = n; break; case 0x33: t=T;n=H2; SET(3,-3) POKE2(u->ram + pc + (s8)t, n) break;
87 case 0x14: /* LDA */ t=T2; SET(2,-1) PUT(0, u->ram[t]) break; case 0x34: t=T2; SET(2, 0) PUT2(0, PEEK2(u->ram + t)) break;
88 case 0x15: /* STA */ t=T2;n=L; SET(3,-3) u->ram[t] = n; break; case 0x35: t=T2;n=N2; SET(4,-4) POKE2(u->ram + t, n) break;
89 case 0x16: /* DEI */ t=T; SET(1, 0) DEI(0, t) break; case 0x36: t=T; SET(1, 1) DEI(1, t) DEI(0, t + 1) break;
90 case 0x17: /* DEO */ t=T;n=N; SET(2,-2) DEO(t, n) break; case 0x37: t=T;n=N;l=L; SET(3,-3) DEO(t, l) DEO(t + 1, n) break;
91 case 0x18: /* ADD */ t=T;n=N; SET(2,-1) PUT(0, n + t) break; case 0x38: t=T2;n=N2; SET(4,-2) PUT2(0, n + t) break;
92 case 0x19: /* SUB */ t=T;n=N; SET(2,-1) PUT(0, n - t) break; case 0x39: t=T2;n=N2; SET(4,-2) PUT2(0, n - t) break;
93 case 0x1a: /* MUL */ t=T;n=N; SET(2,-1) PUT(0, n * t) break; case 0x3a: t=T2;n=N2; SET(4,-2) PUT2(0, n * t) break;
94 case 0x1b: /* DIV */ t=T;n=N; SET(2,-1) PUT(0, n / t) break; case 0x3b: t=T2;n=N2; SET(4,-2) PUT2(0, n / t) break;
95 case 0x1c: /* AND */ t=T;n=N; SET(2,-1) PUT(0, n & t) break; case 0x3c: t=T2;n=N2; SET(4,-2) PUT2(0, n & t) break;
96 case 0x1d: /* ORA */ t=T;n=N; SET(2,-1) PUT(0, n | t) break; case 0x3d: t=T2;n=N2; SET(4,-2) PUT2(0, n | t) break;
97 case 0x1e: /* EOR */ t=T;n=N; SET(2,-1) PUT(0, n ^ t) break; case 0x3e: t=T2;n=N2; SET(4,-2) PUT2(0, n ^ t) break;
98 case 0x1f: /* SFT */ t=T;n=N; SET(2,-1) PUT(0, n >> (t & 0xf) << (t >> 4)) break; case 0x3f: t=T;n=H2; SET(3,-1) PUT2(0, n >> (t & 0xf) << (t >> 4)) break;
99 }
100 }
101}
102
103int
104uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo)
105{
106 u32 i;
107 char *cptr = (char *)u;
108 for(i = 0; i < sizeof(*u); i++)
109 cptr[i] = 0x00;
110 u->wst = (Stack *)(ram + 0x10000);
111 u->rst = (Stack *)(ram + 0x10100);
112 u->dev = (u8 *)(ram + 0x10200);
113 u->ram = ram;
114 u->dei = dei;
115 u->deo = deo;
116 return 1;
117}
diff --git a/src/uxn.h b/src/uxn.h
deleted file mode 100644
index 04aba84..0000000
--- a/src/uxn.h
+++ /dev/null
@@ -1,37 +0,0 @@
1#ifndef UXNGBA_UXN_H
2#define UXNGBA_UXN_H
3/*
4Copyright (c) 2021 Devine Lu Linvega
5
6Permission to use, copy, modify, and distribute this software for any
7purpose with or without fee is hereby granted, provided that the above
8copyright notice and this permission notice appear in all copies.
9
10THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11WITH REGARD TO THIS SOFTWARE.
12*/
13
14#define PAGE_PROGRAM 0x0100
15
16/* clang-format on */
17
18typedef struct {
19 u8 dat[255], ptr;
20} Stack;
21
22typedef struct Uxn {
23 u8 *ram, *dev;
24 Stack *wst, *rst;
25 u8 (*dei)(struct Uxn *u, u8 addr);
26 void (*deo)(struct Uxn *u, u8 addr, u8 value);
27} Uxn;
28
29typedef u8 Dei(Uxn *u, u8 addr);
30typedef void Deo(Uxn *u, u8 addr, u8 value);
31
32u8 uxn_dei(Uxn *u, u8 addr);
33void uxn_deo(Uxn *u, u8 addr);
34int uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr);
35int uxn_boot(Uxn *u, u8 *ram, Dei *dei, Deo *deo);
36int uxn_eval(Uxn *u, u16 pc);
37#endif // UXNGBA_UXN_H