aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-27 22:52:43 +0200
committerBad Diode <bd@badd10de.dev>2023-08-27 22:52:43 +0200
commit8357708a6f73401886bc2bdf405cb19adf419cbc (patch)
treead9b1c3d2fed68bd3cadcff1f5fd868040598706
parent941ad8e28efb685e910b38b06f98bc79fb29677f (diff)
downloaduxngba-8357708a6f73401886bc2bdf405cb19adf419cbc.tar.gz
uxngba-8357708a6f73401886bc2bdf405cb19adf419cbc.zip
Adjust add/sub instructions slightly
-rw-r--r--src/config.c11
-rw-r--r--src/devices.c497
-rw-r--r--src/main.c701
-rw-r--r--src/profiling.c157
-rw-r--r--src/uxn-core.s747
5 files changed, 1053 insertions, 1060 deletions
diff --git a/src/config.c b/src/config.c
new file mode 100644
index 0000000..d100233
--- /dev/null
+++ b/src/config.c
@@ -0,0 +1,11 @@
1#if !defined(TEXT_MODE) || TEXT_MODE == 0
2#define TEXT_LAYER FG_BACK
3#else
4#define TEXT_LAYER BG_BACK
5#endif
6
7#ifndef CONTROL_METHODS
8#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
9#endif
10
11#define PROF_ENABLE 0
diff --git a/src/devices.c b/src/devices.c
new file mode 100644
index 0000000..48d062d
--- /dev/null
+++ b/src/devices.c
@@ -0,0 +1,497 @@
1static time_t seconds = 0;
2
3typedef enum {
4 CONTROL_CONTROLLER,
5 CONTROL_MOUSE,
6 CONTROL_KEYBOARD,
7} ControlMethod;
8
9const ControlMethod ctrl_methods[] = {
10 CONTROL_METHODS
11};
12static ControlMethod ctrl_idx = 0;
13
14#define MOUSE_DELTA 1
15typedef struct Mouse {
16 int x;
17 int y;
18} Mouse;
19
20// static Uxn u;
21
22static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
23
24int
25uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) {
26 (void)u;
27 txt_printf("HALTED\n");
28 txt_printf("I: %lu\n", instr);
29 txt_printf("E: %lu\n", err);
30 txt_printf("A: %lu\n", addr);
31 while (true);
32}
33
34IWRAM_CODE
35u8
36screen_dei(u8 *d, u8 port) {
37 // switch(port) {
38 // case 0x2: return (SCREEN_WIDTH >> 8);
39 // case 0x3: return (SCREEN_WIDTH);
40 // case 0x4: return (SCREEN_HEIGHT >> 8);
41 // case 0x5: return (SCREEN_HEIGHT);
42 // default: return d[port];
43 // }
44}
45
46IWRAM_CODE
47void
48screen_deo(u8 *ram, u8 *d, u8 port) {
49 // switch(port) {
50 // case 0xe: {
51 // u8 ctrl = d[0xe];
52 // u8 color = ctrl & 0x3;
53 // u16 x0 = PEEK2(d + 0x8);
54 // u16 y0 = PEEK2(d + 0xa);
55 // u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
56 // if(ctrl & 0x80) {
57 // u16 x1 = SCREEN_WIDTH - 1;
58 // u16 y1 = SCREEN_HEIGHT - 1;
59 // if(ctrl & 0x10) x1 = x0, x0 = 0;
60 // if(ctrl & 0x20) y1 = y0, y0 = 0;
61 // PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
62 // } else {
63 // PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
64 // if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */
65 // if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */
66 // }
67 // break;
68 // }
69 // case 0xf: {
70 // u16 x, y, dx, dy, addr;
71 // u8 n, twobpp = !!(d[0xf] & 0x80);
72 // x = PEEK2(d + 0x8);
73 // y = PEEK2(d + 0xa);
74 // addr = PEEK2(d + 0xc);
75 // n = d[0x6] >> 4;
76 // dx = (d[0x6] & 0x01) << 3;
77 // dy = (d[0x6] & 0x02) << 2;
78 // if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
79 // return;
80 // }
81 // u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK;
82 // u8 color = d[0xf] & 0xf;
83 // u8 flipx = d[0xf] & 0x10;
84 // u8 flipy = d[0xf] & 0x20;
85 // for(size_t i = 0; i <= n; i++) {
86 // u8 *sprite = &ram[addr];
87 // if (twobpp) {
88 // PROF(ppu_2bpp(layer,
89 // x + dy * i,
90 // y + dx * i,
91 // sprite,
92 // color,
93 // flipx, flipy), ppu_chr_cycles);
94 // } else {
95 // PROF(ppu_1bpp(layer,
96 // x + dy * i,
97 // y + dx * i,
98 // sprite,
99 // color,
100 // flipx, flipy), ppu_icn_cycles);
101 // }
102 // addr += (d[0x6] & 0x04) << (1 + twobpp);
103 // }
104 // POKE2(d + 0xc, addr); /* auto addr+length */
105 // POKE2(d + 0x8, x + dx); /* auto x+8 */
106 // POKE2(d + 0xa, y + dy); /* auto y+8 */
107 // break;
108 // }
109 // }
110}
111
112u8
113audio_dei(int instance, u8 *d, u8 port) {
114 // AudioChannel *c = &channels[instance];
115 // switch(port) {
116 // // case 0x4: return apu_get_vu(instance);
117 // case 0x2: {
118 // POKE2(d + 0x2, c->pos);
119 // c->pos <<= 12; // fixed point.
120 // break;
121 // }
122 // }
123 return d[port];
124}
125
126void
127audio_deo(int instance, u8 *d, u8 port, Uxn *u) {
128 // AudioChannel *c = &channels[instance];
129 // if (port == 0xf) {
130 // u16 length = 0;
131 // u16 adsr = 0;
132 // u16 addr = 0;
133 // u8 pitch = d[0xf] & 0x7f;
134 // adsr = PEEK2(d + 0x8);
135 // length = PEEK2(d + 0xa);
136 // addr = PEEK2(d + 0xc);
137 // u8 *data = &u->ram[addr];
138 // u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3;
139 // bool loop = !(d[0xf] & 0x80);
140 // update_channel(c, data, length, pitch, adsr, vol, loop);
141 // }
142}
143
144u8
145datetime_dei(u8 *d, u8 port) {
146 struct tm *t = gmtime(&seconds);
147 switch(port) {
148 case 0x0: return (t->tm_year + 1900) >> 8;
149 case 0x1: return (t->tm_year + 1900);
150 case 0x2: return t->tm_mon;
151 case 0x3: return t->tm_mday;
152 case 0x4: return t->tm_hour;
153 case 0x5: return t->tm_min;
154 case 0x6: return t->tm_sec;
155 case 0x7: return t->tm_wday;
156 case 0x8: return t->tm_yday >> 8;
157 case 0x9: return t->tm_yday;
158 case 0xa: return t->tm_isdst;
159 default: return d[port];
160 }
161}
162
163u8
164file_dei(u8 id, u8 *d, u8 port) {
165 // UxnFile *c = &uxn_file[id];
166 // u16 res;
167 // switch(port) {
168 // case 0xc:
169 // case 0xd: {
170 // res = file_read(c, &d[port], 1);
171 // POKE2(d + 0x2, res);
172 // break;
173 // }
174 // }
175 return d[port];
176}
177
178void
179file_deo(u8 id, u8 *ram, u8 *d, u8 port) {
180 // u16 a, b, res;
181 // UxnFile *f = &uxn_file[id];
182 // switch(port) {
183 // case 0x5: {
184 // a = PEEK2(d + 0x4);
185 // b = PEEK2(d + 0xa);
186 // if(b > 0x10000 - a) {
187 // b = 0x10000 - a;
188 // }
189 // res = file_stat(f, &ram[a], b);
190 // POKE2(d + 0x2, res);
191 // } break;
192 // case 0x6: {
193 // // TODO: no file deletion for now
194 // // res = file_delete();
195 // // POKE2(d + 0x2, res);
196 // } break;
197 // case 0x9: {
198 // a = PEEK2(d + 0x8);
199 // res = file_init(f, &ram[a]);
200 // POKE2(d + 0x2, res);
201 // } break;
202 // case 0xd: {
203 // a = PEEK2(d + 0xc);
204 // b = PEEK2(d + 0xa);
205 // if(b > 0x10000 - a) {
206 // b = 0x10000 - a;
207 // }
208 // res = file_read(f, &ram[a], b);
209 // POKE2(d + 0x2, res);
210 // } break;
211 // case 0xf: {
212 // a = PEEK2(d + 0xe);
213 // b = PEEK2(d + 0xa);
214 // if(b > 0x10000 - a) {
215 // b = 0x10000 - a;
216 // }
217 // res = file_write(f, &ram[a], b, d[0x7]);
218 // POKE2(d + 0x2, res);
219 // } break;
220 // }
221}
222
223void
224console_deo(u8 *d, u8 port) {
225 // switch(port) {
226 // case 0x8:
227 // txt_putc(d[port]);
228 // return;
229 // case 0x9:
230 // txt_printf("ERROR: %c");
231 // txt_putc(d[port]);
232 // return;
233 // }
234}
235
236#define RAM_PAGES 0x10
237
238static void
239system_cmd(u8 *ram, u16 addr) {
240 if(ram[addr] == 0x01) {
241 // NOTE: Handle rom paging on a case by case basis if a rom has to be
242 // split in multiple chunks. The GBA compiler doesn't like allocating
243 // big arrays, but it's fine if we split it into chunks of 64KB, for
244 // example.
245 //
246 // u16 i, length = PEEK2(ram + addr + 1);
247 // u16 a_page = PEEK2(ram + addr + 1 + 2);
248 // u16 a_addr = PEEK2(ram + addr + 1 + 4);
249 // u16 b_addr = PEEK2(ram + addr + 1 + 8);
250 // u8 *rom = uxn_rom;
251 // for(i = 0; i < length; i++) {
252 // switch (a_page % RAM_PAGES) {
253 // case 0: { rom = uxn_rom; } break;
254 // case 1: { rom = uxn_rom_2; } break;
255 // case 2: { rom = uxn_rom_3; } break;
256 // case 3: { rom = uxn_rom_4; } break;
257 // case 4: { rom = uxn_rom_5; } break;
258 // case 5: { rom = uxn_rom_6; } break;
259 // case 6: { rom = uxn_rom_7; } break;
260 // }
261 // ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
262 // }
263 }
264}
265
266void
267system_deo(Uxn *u, u8 *d, u8 port) {
268 // switch(port) {
269 // case 0x3: {
270 // system_cmd(u->ram, PEEK2(d + 2));
271 // } break;
272 // }
273}
274
275u8
276uxn_dei(Uxn *u, u8 addr) {
277 u8 p = addr & 0x0f, d = addr & 0xf0;
278 switch(d) {
279 case 0x20: return screen_dei(&u->dev[d], p);
280 case 0x30: return audio_dei(0, &u->dev[d], p);
281 case 0x40: return audio_dei(1, &u->dev[d], p);
282 case 0x50: return audio_dei(2, &u->dev[d], p);
283 case 0x60: return audio_dei(3, &u->dev[d], p);
284 case 0xa0: return file_dei(0, &u->dev[d], p);
285 case 0xb0: return file_dei(1, &u->dev[d], p);
286 case 0xc0: return datetime_dei(&u->dev[d], p);
287 }
288 return u->dev[addr];
289}
290
291void
292uxn_deo(Uxn *u, u8 addr) {
293 u8 p = addr & 0x0f, d = addr & 0xf0;
294 switch(d) {
295 case 0x00:
296 system_deo(u, &u->dev[d], p);
297 if(p > 0x7 && p < 0xe) {
298 putcolors(&u->dev[0x8]);
299 }
300 break;
301 case 0x10: console_deo(&u->dev[d], p); break;
302 case 0x20: screen_deo(u->ram, &u->dev[d], p); break;
303 case 0x30: audio_deo(0, &u->dev[d], p, u); break;
304 case 0x40: audio_deo(1, &u->dev[d], p, u); break;
305 case 0x50: audio_deo(2, &u->dev[d], p, u); break;
306 case 0x60: audio_deo(3, &u->dev[d], p, u); break;
307 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break;
308 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break;
309 }
310}
311
312IWRAM_CODE
313void
314handle_input(Uxn *u) {
315 // poll_keys();
316 // if (key_tap(KEY_SELECT)) {
317 // // Reset control variables on method switch.
318 // switch (ctrl_methods[ctrl_idx]) {
319 // case CONTROL_CONTROLLER: {
320 // u8 *d = &u->dev[0x80];
321 // d[2] = 0;
322 // uxn_eval(u, PEEK2(d));
323 // d[3] = 0;
324 // } break;
325 // case CONTROL_MOUSE: {
326 // u8 *d = &u->dev[0x90];
327 // d[6] = 0;
328 // d[7] = 0;
329 // POKE2(d + 0x2, -10);
330 // POKE2(d + 0x4, -10);
331 // uxn_eval(u, PEEK2(d));
332 // } break;
333 // case CONTROL_KEYBOARD: {
334 // toggle_keyboard();
335 // } break;
336 // }
337
338 // // Update ctrl_idx.
339 // ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1;
340
341 // // Initialize controller variables here.
342 // if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
343 // toggle_keyboard();
344 // }
345 // }
346
347 // if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) {
348 // u8 *d = &u->dev[0x80];
349 // // TODO: We don't need ifs if we use KEY_INPUTS directly and maybe just
350 // // swap some things if needed.
351 // u8 *flag = &d[2];
352 // if (key_tap(KEY_A)) {
353 // *flag |= 0x01;
354 // } else {
355 // *flag &= ~0x01;
356 // }
357 // if (key_tap(KEY_B)) {
358 // *flag |= 0x02;
359 // } else {
360 // *flag &= ~0x02;
361 // }
362 // if (key_tap(KEY_L)) {
363 // *flag |= 0x04;
364 // } else {
365 // *flag &= ~0x04;
366 // }
367 // if (key_tap(KEY_R)) {
368 // *flag |= 0x08;
369 // } else {
370 // *flag &= ~0x08;
371 // }
372 // if (key_tap(KEY_UP)) {
373 // *flag |= 0x10;
374 // } else {
375 // *flag &= ~0x10;
376 // }
377 // if (key_tap(KEY_DOWN)) {
378 // *flag |= 0x20;
379 // } else {
380 // *flag &= ~0x20;
381 // }
382 // if (key_tap(KEY_LEFT)) {
383 // *flag |= 0x40;
384 // } else {
385 // *flag &= ~0x40;
386 // }
387 // if (key_tap(KEY_RIGHT)) {
388 // *flag |= 0x80;
389 // } else {
390 // *flag &= ~0x80;
391 // }
392
393 // if (key_prev != key_curr) {
394 // uxn_eval(u, PEEK2(d));
395 // }
396 // d[3] = 0;
397 // } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
398 // u8 *d = &u->dev[0x90];
399 // // Detect "mouse key press".
400 // u8 flag = d[6];
401 // bool event = false;
402 // if (key_tap(KEY_B)) {
403 // event = true;
404 // flag |= 0x01;
405 // } else if (key_released(KEY_B)) {
406 // event = true;
407 // flag &= ~0x01;
408 // }
409 // if (key_tap(KEY_A)) {
410 // event = true;
411 // flag |= 0x10;
412 // } else if (key_released(KEY_A)) {
413 // event = true;
414 // flag &= ~0x10;
415 // }
416
417 // // Handle chording.
418 // d[6] = flag;
419 // if(flag == 0x10 && (d[6] & 0x01)) {
420 // d[7] = 0x01;
421 // }
422 // if(flag == 0x01 && (d[6] & 0x10)) {
423 // d[7] = 0x10;
424 // }
425
426 // // Detect mouse movement.
427 // if (key_pressed(KEY_UP)) {
428 // event = true;
429 // mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
430 // } else if (key_pressed(KEY_DOWN)) {
431 // event = true;
432 // mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
433 // }
434 // if (key_pressed(KEY_LEFT)) {
435 // event = true;
436 // mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
437 // } else if (key_pressed(KEY_RIGHT)) {
438 // event = true;
439 // mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
440 // }
441
442 // // Eval mouse.
443 // POKE2(d + 0x2, mouse.x);
444 // POKE2(d + 0x4, mouse.y);
445 // if (event) {
446 // uxn_eval(u, PEEK2(d));
447 // }
448 // } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
449 // u8 *d = &u->dev[0x80];
450 // if (key_tap(KEY_LEFT)) {
451 // update_cursor(cursor_position - 1);
452 // } else if (key_tap(KEY_RIGHT)) {
453 // update_cursor(cursor_position + 1);
454 // }
455 // if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
456 // update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
457 // } else if (key_tap(KEY_DOWN)
458 // && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
459 // update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
460 // }
461 // if (key_tap(KEY_B)) {
462 // u8 symbol = keyboard[cursor_position].symbol;
463 // switch (symbol) {
464 // case 0x7f: {
465 // // Backspace.
466 // d[3] = 0x08;
467 // } break;
468 // case 0x14: {
469 // // New line.
470 // d[3] = 0x0d;
471 // } break;
472 // case 0x18: {
473 // // Arrow up.
474 // d[2] = 0x10;
475 // } break;
476 // case 0x19: {
477 // // Arrow down.
478 // d[2] = 0x20;
479 // } break;
480 // case 0x1b: {
481 // // Arrow left.
482 // d[2] = 0x40;
483 // } break;
484 // case 0x1a: {
485 // // Arrow right.
486 // d[2] = 0x80;
487 // } break;
488 // default: {
489 // d[3] = symbol;
490 // } break;
491 // }
492 // uxn_eval(u, PEEK2(d));
493 // d[3] = 0;
494 // }
495 // }
496}
497
diff --git a/src/main.c b/src/main.c
index e10c8f0..4a4b58c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -15,499 +15,31 @@
15#include "common.h" 15#include "common.h"
16#include "filesystem.c" 16#include "filesystem.c"
17 17
18#include "uxn.h" 18#include "uxn.c"
19#include "ppu.c" 19#include "ppu.c"
20#include "apu.c" 20#include "apu.c"
21#include "file.c" 21#include "file.c"
22#include "text.h" 22#include "text.h"
23 23
24#include "rom.c" 24#include "rom.c"
25#include "config.c"
26#include "profiling.c"
27#include "devices.c"
25 28
26// 29#define STACK_SIZE 16
27// Config parameters. 30u8 stack[STACK_SIZE] = {0};
28// 31extern void uxn_eval_asm(u16 pc);
29
30#if !defined(TEXT_MODE) || TEXT_MODE == 0
31#define TEXT_LAYER FG_BACK
32#else
33#define TEXT_LAYER BG_BACK
34#endif
35
36#ifndef CONTROL_METHODS
37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
38#endif
39
40#define PROF_ENABLE 0
41#ifndef PROF_ENABLE
42#define PROF_ENABLE 0
43#endif
44
45#if PROF_ENABLE > 0 && PROF_ENABLE < 3
46
47#ifndef PROF_N_FRAMES
48#define PROF_N_FRAMES 15
49#endif
50
51// Profile method 1: Average per N frames.
52#if PROF_ENABLE == 1
53#define TEXT_ENABLE 1
54#define PROF(F,VAR) \
55 do { \
56 u32 __tmp_prof = profile_measure();\
57 (F);\
58 (VAR) += profile_measure() - __tmp_prof;\
59 } while (0)
60
61// Profile method 2: Maximum in N frames.
62#elif PROF_ENABLE == 2
63#define TEXT_ENABLE 1
64#define PROF(F,VAR) \
65 do { \
66 u32 __tmp_prof = profile_measure();\
67 (F);\
68 (VAR) = MAX(profile_measure() - __tmp_prof, (VAR));\
69 } while (0)
70#endif
71
72#ifndef PROF_SHOW_X
73#define PROF_SHOW_X 0
74#endif
75#ifndef PROF_SHOW_Y
76#define PROF_SHOW_Y 0
77#endif
78
79#define PROF_SHOW() \
80 do { \
81 txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\
82 txt_printf("INPUT %.8lu\n", avg_input_cycles);\
83 txt_printf("EVAL %.8lu\n", avg_eval_cycles);\
84 txt_printf("VIDEO\n");\
85 txt_printf(">PIX %.8lu\n", avg_ppu_pixel_cycles);\
86 txt_printf(">FILL %.8lu\n", avg_ppu_fill_cycles);\
87 txt_printf(">1BPP %.8lu\n", avg_ppu_icn_cycles);\
88 txt_printf(">2BPP %.8lu\n", avg_ppu_chr_cycles);\
89 txt_printf(">FLIP %.8lu\n", avg_flip_cycles);\
90 txt_printf("AUDIO %.8lu\n", avg_mix_cycles);\
91 txt_printf("TOTAL %.8lu\n", avg_frame_cycles);\
92 u32 frame_time =\
93 FP_DIV(\
94 FP_NUM(avg_frame_cycles + 1, 2),\
95 FP_NUM(2809, 2),\
96 2) * 166;\
97 u32 fps =\
98 FP_DIV(\
99 FP_NUM(280896 * 60, 2),\
100 FP_NUM(avg_frame_cycles + 1, 2),\
101 2);\
102 txt_printf("TIME %.8lu\n", frame_time >> 2);\
103 txt_printf("FPS %.8lu\n", (fps >> 2) + 1);\
104 screen_fill(BG_BACK, 0, 0, 8 * 16, 8 * 12, 2);\
105 } while (0)
106
107static u32 prof_frame_counter = 0;
108
109static u32 frame_cycles = 0;
110static u32 ppu_pixel_cycles = 0;
111static u32 ppu_fill_cycles = 0;
112static u32 ppu_chr_cycles = 0;
113static u32 ppu_icn_cycles = 0;
114static u32 flip_cycles = 0;
115static u32 eval_cycles = 0;
116static u32 input_cycles = 0;
117static u32 mix_cycles = 0;
118
119static u32 avg_ppu_pixel_cycles = 0;
120static u32 avg_ppu_fill_cycles = 0;
121static u32 avg_ppu_chr_cycles = 0;
122static u32 avg_ppu_icn_cycles = 0;
123static u32 avg_flip_cycles = 0;
124static u32 avg_eval_cycles = 0;
125static u32 avg_input_cycles = 0;
126static u32 avg_mix_cycles = 0;
127static u32 avg_frame_cycles = 0;
128
129#if PROF_ENABLE == 1
130#define FRAME_START()\
131 do { \
132 if (prof_frame_counter == PROF_N_FRAMES) {\
133 avg_ppu_pixel_cycles = ppu_pixel_cycles / prof_frame_counter;\
134 avg_ppu_fill_cycles = ppu_fill_cycles / prof_frame_counter;\
135 avg_ppu_chr_cycles = ppu_chr_cycles / prof_frame_counter;\
136 avg_ppu_icn_cycles = ppu_icn_cycles / prof_frame_counter;\
137 avg_flip_cycles = flip_cycles / prof_frame_counter;\
138 avg_eval_cycles = eval_cycles / prof_frame_counter;\
139 avg_input_cycles = input_cycles / prof_frame_counter;\
140 avg_mix_cycles = mix_cycles / prof_frame_counter;\
141 avg_frame_cycles = frame_cycles / prof_frame_counter;\
142 prof_frame_counter = 0;\
143 frame_cycles = 0;\
144 ppu_pixel_cycles = 0;\
145 ppu_fill_cycles = 0;\
146 ppu_chr_cycles = 0;\
147 ppu_icn_cycles = 0;\
148 flip_cycles = 0;\
149 eval_cycles = 0;\
150 input_cycles = 0;\
151 mix_cycles = 0;\
152 }\
153 profile_start();\
154 } while (0)
155#elif PROF_ENABLE == 2
156#define FRAME_START()\
157 do { \
158 if (prof_frame_counter == PROF_N_FRAMES) {\
159 avg_ppu_pixel_cycles = ppu_pixel_cycles;\
160 avg_ppu_fill_cycles = ppu_fill_cycles;\
161 avg_ppu_chr_cycles = ppu_chr_cycles;\
162 avg_ppu_icn_cycles = ppu_icn_cycles;\
163 avg_flip_cycles = flip_cycles;\
164 avg_eval_cycles = eval_cycles;\
165 avg_input_cycles = input_cycles;\
166 avg_mix_cycles = mix_cycles;\
167 avg_frame_cycles = frame_cycles / prof_frame_counter;\
168 prof_frame_counter = 0;\
169 frame_cycles = 0;\
170 ppu_pixel_cycles = 0;\
171 ppu_fill_cycles = 0;\
172 ppu_chr_cycles = 0;\
173 ppu_icn_cycles = 0;\
174 flip_cycles = 0;\
175 eval_cycles = 0;\
176 input_cycles = 0;\
177 mix_cycles = 0;\
178 }\
179 profile_start();\
180 } while (0)
181#endif
182
183#define FRAME_END() \
184 do { \
185 prof_frame_counter++;\
186 frame_cycles += profile_stop();\
187 } while (0)
188
189#else
190
191// No profiling.
192#define PROF(F,VAR) (F)
193#define PROF_SHOW()
194#define FRAME_START()
195#define FRAME_END()
196#endif
197
198static time_t seconds = 0;
199
200typedef enum {
201 CONTROL_CONTROLLER,
202 CONTROL_MOUSE,
203 CONTROL_KEYBOARD,
204} ControlMethod;
205
206const ControlMethod ctrl_methods[] = {
207 CONTROL_METHODS
208};
209static ControlMethod ctrl_idx = 0;
210 32
211#define MOUSE_DELTA 1 33// TODO: This should be on the IWRAM for maximum speed, as these are operations
212typedef struct Mouse { 34// we will use very often.
213 int x; 35extern u8 wst[256];
214 int y; 36extern u8 rst[256];
215} Mouse; 37extern u8 io_ports[256];
38extern uintptr_t wst_ptr;
39extern uintptr_t rst_ptr;
216 40
217EWRAM_BSS 41EWRAM_BSS
218u8 uxn_ram[0x10300]; 42u8 uxn_ram[KB(64) * 2];
219
220// static Uxn u;
221
222static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
223
224// int
225// uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) {
226// (void)u;
227// txt_printf("HALTED\n");
228// txt_printf("I: %lu\n", instr);
229// txt_printf("E: %lu\n", err);
230// txt_printf("A: %lu\n", addr);
231// while (true);
232// }
233
234IWRAM_CODE
235u8
236screen_dei(u8 *d, u8 port) {
237 // switch(port) {
238 // case 0x2: return (SCREEN_WIDTH >> 8);
239 // case 0x3: return (SCREEN_WIDTH);
240 // case 0x4: return (SCREEN_HEIGHT >> 8);
241 // case 0x5: return (SCREEN_HEIGHT);
242 // default: return d[port];
243 // }
244}
245
246IWRAM_CODE
247void
248screen_deo(u8 *ram, u8 *d, u8 port) {
249 // switch(port) {
250 // case 0xe: {
251 // u8 ctrl = d[0xe];
252 // u8 color = ctrl & 0x3;
253 // u16 x0 = PEEK2(d + 0x8);
254 // u16 y0 = PEEK2(d + 0xa);
255 // u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
256 // if(ctrl & 0x80) {
257 // u16 x1 = SCREEN_WIDTH - 1;
258 // u16 y1 = SCREEN_HEIGHT - 1;
259 // if(ctrl & 0x10) x1 = x0, x0 = 0;
260 // if(ctrl & 0x20) y1 = y0, y0 = 0;
261 // PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
262 // } else {
263 // PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
264 // if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */
265 // if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */
266 // }
267 // break;
268 // }
269 // case 0xf: {
270 // u16 x, y, dx, dy, addr;
271 // u8 n, twobpp = !!(d[0xf] & 0x80);
272 // x = PEEK2(d + 0x8);
273 // y = PEEK2(d + 0xa);
274 // addr = PEEK2(d + 0xc);
275 // n = d[0x6] >> 4;
276 // dx = (d[0x6] & 0x01) << 3;
277 // dy = (d[0x6] & 0x02) << 2;
278 // if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
279 // return;
280 // }
281 // u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK;
282 // u8 color = d[0xf] & 0xf;
283 // u8 flipx = d[0xf] & 0x10;
284 // u8 flipy = d[0xf] & 0x20;
285 // for(size_t i = 0; i <= n; i++) {
286 // u8 *sprite = &ram[addr];
287 // if (twobpp) {
288 // PROF(ppu_2bpp(layer,
289 // x + dy * i,
290 // y + dx * i,
291 // sprite,
292 // color,
293 // flipx, flipy), ppu_chr_cycles);
294 // } else {
295 // PROF(ppu_1bpp(layer,
296 // x + dy * i,
297 // y + dx * i,
298 // sprite,
299 // color,
300 // flipx, flipy), ppu_icn_cycles);
301 // }
302 // addr += (d[0x6] & 0x04) << (1 + twobpp);
303 // }
304 // POKE2(d + 0xc, addr); /* auto addr+length */
305 // POKE2(d + 0x8, x + dx); /* auto x+8 */
306 // POKE2(d + 0xa, y + dy); /* auto y+8 */
307 // break;
308 // }
309 // }
310}
311
312u8
313audio_dei(int instance, u8 *d, u8 port) {
314 // AudioChannel *c = &channels[instance];
315 // switch(port) {
316 // // case 0x4: return apu_get_vu(instance);
317 // case 0x2: {
318 // POKE2(d + 0x2, c->pos);
319 // c->pos <<= 12; // fixed point.
320 // break;
321 // }
322 // }
323 return d[port];
324}
325
326void
327audio_deo(int instance, u8 *d, u8 port, Uxn *u) {
328 // AudioChannel *c = &channels[instance];
329 // if (port == 0xf) {
330 // u16 length = 0;
331 // u16 adsr = 0;
332 // u16 addr = 0;
333 // u8 pitch = d[0xf] & 0x7f;
334 // adsr = PEEK2(d + 0x8);
335 // length = PEEK2(d + 0xa);
336 // addr = PEEK2(d + 0xc);
337 // u8 *data = &u->ram[addr];
338 // u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3;
339 // bool loop = !(d[0xf] & 0x80);
340 // update_channel(c, data, length, pitch, adsr, vol, loop);
341 // }
342}
343
344u8
345datetime_dei(u8 *d, u8 port) {
346 struct tm *t = gmtime(&seconds);
347 switch(port) {
348 case 0x0: return (t->tm_year + 1900) >> 8;
349 case 0x1: return (t->tm_year + 1900);
350 case 0x2: return t->tm_mon;
351 case 0x3: return t->tm_mday;
352 case 0x4: return t->tm_hour;
353 case 0x5: return t->tm_min;
354 case 0x6: return t->tm_sec;
355 case 0x7: return t->tm_wday;
356 case 0x8: return t->tm_yday >> 8;
357 case 0x9: return t->tm_yday;
358 case 0xa: return t->tm_isdst;
359 default: return d[port];
360 }
361}
362
363u8
364file_dei(u8 id, u8 *d, u8 port) {
365 // UxnFile *c = &uxn_file[id];
366 // u16 res;
367 // switch(port) {
368 // case 0xc:
369 // case 0xd: {
370 // res = file_read(c, &d[port], 1);
371 // POKE2(d + 0x2, res);
372 // break;
373 // }
374 // }
375 return d[port];
376}
377
378void
379file_deo(u8 id, u8 *ram, u8 *d, u8 port) {
380 // u16 a, b, res;
381 // UxnFile *f = &uxn_file[id];
382 // switch(port) {
383 // case 0x5: {
384 // a = PEEK2(d + 0x4);
385 // b = PEEK2(d + 0xa);
386 // if(b > 0x10000 - a) {
387 // b = 0x10000 - a;
388 // }
389 // res = file_stat(f, &ram[a], b);
390 // POKE2(d + 0x2, res);
391 // } break;
392 // case 0x6: {
393 // // TODO: no file deletion for now
394 // // res = file_delete();
395 // // POKE2(d + 0x2, res);
396 // } break;
397 // case 0x9: {
398 // a = PEEK2(d + 0x8);
399 // res = file_init(f, &ram[a]);
400 // POKE2(d + 0x2, res);
401 // } break;
402 // case 0xd: {
403 // a = PEEK2(d + 0xc);
404 // b = PEEK2(d + 0xa);
405 // if(b > 0x10000 - a) {
406 // b = 0x10000 - a;
407 // }
408 // res = file_read(f, &ram[a], b);
409 // POKE2(d + 0x2, res);
410 // } break;
411 // case 0xf: {
412 // a = PEEK2(d + 0xe);
413 // b = PEEK2(d + 0xa);
414 // if(b > 0x10000 - a) {
415 // b = 0x10000 - a;
416 // }
417 // res = file_write(f, &ram[a], b, d[0x7]);
418 // POKE2(d + 0x2, res);
419 // } break;
420 // }
421}
422
423void
424console_deo(u8 *d, u8 port) {
425 // switch(port) {
426 // case 0x8:
427 // txt_putc(d[port]);
428 // return;
429 // case 0x9:
430 // txt_printf("ERROR: %c");
431 // txt_putc(d[port]);
432 // return;
433 // }
434}
435
436#define RAM_PAGES 0x10
437
438static void
439system_cmd(u8 *ram, u16 addr) {
440 if(ram[addr] == 0x01) {
441 // NOTE: Handle rom paging on a case by case basis if a rom has to be
442 // split in multiple chunks. The GBA compiler doesn't like allocating
443 // big arrays, but it's fine if we split it into chunks of 64KB, for
444 // example.
445 //
446 // u16 i, length = PEEK2(ram + addr + 1);
447 // u16 a_page = PEEK2(ram + addr + 1 + 2);
448 // u16 a_addr = PEEK2(ram + addr + 1 + 4);
449 // u16 b_addr = PEEK2(ram + addr + 1 + 8);
450 // u8 *rom = uxn_rom;
451 // for(i = 0; i < length; i++) {
452 // switch (a_page % RAM_PAGES) {
453 // case 0: { rom = uxn_rom; } break;
454 // case 1: { rom = uxn_rom_2; } break;
455 // case 2: { rom = uxn_rom_3; } break;
456 // case 3: { rom = uxn_rom_4; } break;
457 // case 4: { rom = uxn_rom_5; } break;
458 // case 5: { rom = uxn_rom_6; } break;
459 // case 6: { rom = uxn_rom_7; } break;
460 // }
461 // ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
462 // }
463 }
464}
465
466void
467system_deo(Uxn *u, u8 *d, u8 port) {
468 // switch(port) {
469 // case 0x3: {
470 // system_cmd(u->ram, PEEK2(d + 2));
471 // } break;
472 // }
473}
474
475u8
476uxn_dei(Uxn *u, u8 addr) {
477 u8 p = addr & 0x0f, d = addr & 0xf0;
478 switch(d) {
479 case 0x20: return screen_dei(&u->dev[d], p);
480 case 0x30: return audio_dei(0, &u->dev[d], p);
481 case 0x40: return audio_dei(1, &u->dev[d], p);
482 case 0x50: return audio_dei(2, &u->dev[d], p);
483 case 0x60: return audio_dei(3, &u->dev[d], p);
484 case 0xa0: return file_dei(0, &u->dev[d], p);
485 case 0xb0: return file_dei(1, &u->dev[d], p);
486 case 0xc0: return datetime_dei(&u->dev[d], p);
487 }
488 return u->dev[addr];
489}
490
491void
492uxn_deo(Uxn *u, u8 addr) {
493 u8 p = addr & 0x0f, d = addr & 0xf0;
494 switch(d) {
495 case 0x00:
496 system_deo(u, &u->dev[d], p);
497 if(p > 0x7 && p < 0xe) {
498 putcolors(&u->dev[0x8]);
499 }
500 break;
501 case 0x10: console_deo(&u->dev[d], p); break;
502 case 0x20: screen_deo(u->ram, &u->dev[d], p); break;
503 case 0x30: audio_deo(0, &u->dev[d], p, u); break;
504 case 0x40: audio_deo(1, &u->dev[d], p, u); break;
505 case 0x50: audio_deo(2, &u->dev[d], p, u); break;
506 case 0x60: audio_deo(3, &u->dev[d], p, u); break;
507 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break;
508 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break;
509 }
510}
511 43
512void 44void
513init_uxn() { 45init_uxn() {
@@ -532,8 +64,9 @@ init_uxn() {
532 // #0004 #0008 ADD 64 // #0004 #0008 ADD
533 // 0xa0, 0x00, 0x04, 0xa0, 0x00, 0x08, 0x18, 65 // 0xa0, 0x00, 0x04, 0xa0, 0x00, 0x08, 0x18,
534 // #0004 #0008 ADD2 66 // #0004 #0008 ADD2
535 0x80, 0xFF, 0xff, 67 // 0x80, 0xFF, 0xff,
536 0xa0, 0x00, 0x08, 0xa0, 0x00, 0x04, 0x38, 68 // 0xa0, 0x00, 0x08, 0xa0, 0x00, 0x04, 0x38,
69 // 0xa0, 0x00, 0x08, 0xa0, 0x00, 0x04, 0x38,
537 // 0xa0, 0x00, 0x08, 0xa0, 0x00, 0x03, 0x39, 70 // 0xa0, 0x00, 0x08, 0xa0, 0x00, 0x03, 0x39,
538 // 0xa0, 0x00, 0x01, 0x38, 71 // 0xa0, 0x00, 0x01, 0x38,
539 // 72 //
@@ -553,204 +86,6 @@ init_uxn() {
553 memcpy(uxn_ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); 86 memcpy(uxn_ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom));
554} 87}
555 88
556IWRAM_CODE
557void
558handle_input(Uxn *u) {
559 // poll_keys();
560 // if (key_tap(KEY_SELECT)) {
561 // // Reset control variables on method switch.
562 // switch (ctrl_methods[ctrl_idx]) {
563 // case CONTROL_CONTROLLER: {
564 // u8 *d = &u->dev[0x80];
565 // d[2] = 0;
566 // uxn_eval(u, PEEK2(d));
567 // d[3] = 0;
568 // } break;
569 // case CONTROL_MOUSE: {
570 // u8 *d = &u->dev[0x90];
571 // d[6] = 0;
572 // d[7] = 0;
573 // POKE2(d + 0x2, -10);
574 // POKE2(d + 0x4, -10);
575 // uxn_eval(u, PEEK2(d));
576 // } break;
577 // case CONTROL_KEYBOARD: {
578 // toggle_keyboard();
579 // } break;
580 // }
581
582 // // Update ctrl_idx.
583 // ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1;
584
585 // // Initialize controller variables here.
586 // if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
587 // toggle_keyboard();
588 // }
589 // }
590
591 // if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) {
592 // u8 *d = &u->dev[0x80];
593 // // TODO: We don't need ifs if we use KEY_INPUTS directly and maybe just
594 // // swap some things if needed.
595 // u8 *flag = &d[2];
596 // if (key_tap(KEY_A)) {
597 // *flag |= 0x01;
598 // } else {
599 // *flag &= ~0x01;
600 // }
601 // if (key_tap(KEY_B)) {
602 // *flag |= 0x02;
603 // } else {
604 // *flag &= ~0x02;
605 // }
606 // if (key_tap(KEY_L)) {
607 // *flag |= 0x04;
608 // } else {
609 // *flag &= ~0x04;
610 // }
611 // if (key_tap(KEY_R)) {
612 // *flag |= 0x08;
613 // } else {
614 // *flag &= ~0x08;
615 // }
616 // if (key_tap(KEY_UP)) {
617 // *flag |= 0x10;
618 // } else {
619 // *flag &= ~0x10;
620 // }
621 // if (key_tap(KEY_DOWN)) {
622 // *flag |= 0x20;
623 // } else {
624 // *flag &= ~0x20;
625 // }
626 // if (key_tap(KEY_LEFT)) {
627 // *flag |= 0x40;
628 // } else {
629 // *flag &= ~0x40;
630 // }
631 // if (key_tap(KEY_RIGHT)) {
632 // *flag |= 0x80;
633 // } else {
634 // *flag &= ~0x80;
635 // }
636
637 // if (key_prev != key_curr) {
638 // uxn_eval(u, PEEK2(d));
639 // }
640 // d[3] = 0;
641 // } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
642 // u8 *d = &u->dev[0x90];
643 // // Detect "mouse key press".
644 // u8 flag = d[6];
645 // bool event = false;
646 // if (key_tap(KEY_B)) {
647 // event = true;
648 // flag |= 0x01;
649 // } else if (key_released(KEY_B)) {
650 // event = true;
651 // flag &= ~0x01;
652 // }
653 // if (key_tap(KEY_A)) {
654 // event = true;
655 // flag |= 0x10;
656 // } else if (key_released(KEY_A)) {
657 // event = true;
658 // flag &= ~0x10;
659 // }
660
661 // // Handle chording.
662 // d[6] = flag;
663 // if(flag == 0x10 && (d[6] & 0x01)) {
664 // d[7] = 0x01;
665 // }
666 // if(flag == 0x01 && (d[6] & 0x10)) {
667 // d[7] = 0x10;
668 // }
669
670 // // Detect mouse movement.
671 // if (key_pressed(KEY_UP)) {
672 // event = true;
673 // mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
674 // } else if (key_pressed(KEY_DOWN)) {
675 // event = true;
676 // mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
677 // }
678 // if (key_pressed(KEY_LEFT)) {
679 // event = true;
680 // mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
681 // } else if (key_pressed(KEY_RIGHT)) {
682 // event = true;
683 // mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
684 // }
685
686 // // Eval mouse.
687 // POKE2(d + 0x2, mouse.x);
688 // POKE2(d + 0x4, mouse.y);
689 // if (event) {
690 // uxn_eval(u, PEEK2(d));
691 // }
692 // } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
693 // u8 *d = &u->dev[0x80];
694 // if (key_tap(KEY_LEFT)) {
695 // update_cursor(cursor_position - 1);
696 // } else if (key_tap(KEY_RIGHT)) {
697 // update_cursor(cursor_position + 1);
698 // }
699 // if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
700 // update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
701 // } else if (key_tap(KEY_DOWN)
702 // && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
703 // update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
704 // }
705 // if (key_tap(KEY_B)) {
706 // u8 symbol = keyboard[cursor_position].symbol;
707 // switch (symbol) {
708 // case 0x7f: {
709 // // Backspace.
710 // d[3] = 0x08;
711 // } break;
712 // case 0x14: {
713 // // New line.
714 // d[3] = 0x0d;
715 // } break;
716 // case 0x18: {
717 // // Arrow up.
718 // d[2] = 0x10;
719 // } break;
720 // case 0x19: {
721 // // Arrow down.
722 // d[2] = 0x20;
723 // } break;
724 // case 0x1b: {
725 // // Arrow left.
726 // d[2] = 0x40;
727 // } break;
728 // case 0x1a: {
729 // // Arrow right.
730 // d[2] = 0x80;
731 // } break;
732 // default: {
733 // d[3] = symbol;
734 // } break;
735 // }
736 // uxn_eval(u, PEEK2(d));
737 // d[3] = 0;
738 // }
739 // }
740}
741
742#define STACK_SIZE 16
743u8 stack[STACK_SIZE] = {0};
744extern void uxn_eval_asm(u16 pc);
745
746// TODO: This should be on the IWRAM for maximum speed, as these are operations
747// we will use very often.
748extern u8 wst[256];
749extern u8 rst[256];
750extern u8 io_ports[256];
751extern uintptr_t wst_ptr;
752extern uintptr_t rst_ptr;
753
754int 89int
755main(void) { 90main(void) {
756 // Adjust system wait times. 91 // Adjust system wait times.
diff --git a/src/profiling.c b/src/profiling.c
new file mode 100644
index 0000000..2d230df
--- /dev/null
+++ b/src/profiling.c
@@ -0,0 +1,157 @@
1#ifndef PROF_ENABLE
2#define PROF_ENABLE 0
3#endif
4
5#if PROF_ENABLE > 0 && PROF_ENABLE < 3
6
7#ifndef PROF_N_FRAMES
8#define PROF_N_FRAMES 15
9#endif
10
11// Profile method 1: Average per N frames.
12#if PROF_ENABLE == 1
13#define TEXT_ENABLE 1
14#define PROF(F,VAR) \
15 do { \
16 u32 __tmp_prof = profile_measure();\
17 (F);\
18 (VAR) += profile_measure() - __tmp_prof;\
19 } while (0)
20
21// Profile method 2: Maximum in N frames.
22#elif PROF_ENABLE == 2
23#define TEXT_ENABLE 1
24#define PROF(F,VAR) \
25 do { \
26 u32 __tmp_prof = profile_measure();\
27 (F);\
28 (VAR) = MAX(profile_measure() - __tmp_prof, (VAR));\
29 } while (0)
30#endif
31
32#ifndef PROF_SHOW_X
33#define PROF_SHOW_X 0
34#endif
35#ifndef PROF_SHOW_Y
36#define PROF_SHOW_Y 0
37#endif
38
39#define PROF_SHOW() \
40 do { \
41 txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\
42 txt_printf("INPUT %.8lu\n", avg_input_cycles);\
43 txt_printf("EVAL %.8lu\n", avg_eval_cycles);\
44 txt_printf("VIDEO\n");\
45 txt_printf(">PIX %.8lu\n", avg_ppu_pixel_cycles);\
46 txt_printf(">FILL %.8lu\n", avg_ppu_fill_cycles);\
47 txt_printf(">1BPP %.8lu\n", avg_ppu_icn_cycles);\
48 txt_printf(">2BPP %.8lu\n", avg_ppu_chr_cycles);\
49 txt_printf(">FLIP %.8lu\n", avg_flip_cycles);\
50 txt_printf("AUDIO %.8lu\n", avg_mix_cycles);\
51 txt_printf("TOTAL %.8lu\n", avg_frame_cycles);\
52 u32 frame_time =\
53 FP_DIV(\
54 FP_NUM(avg_frame_cycles + 1, 2),\
55 FP_NUM(2809, 2),\
56 2) * 166;\
57 u32 fps =\
58 FP_DIV(\
59 FP_NUM(280896 * 60, 2),\
60 FP_NUM(avg_frame_cycles + 1, 2),\
61 2);\
62 txt_printf("TIME %.8lu\n", frame_time >> 2);\
63 txt_printf("FPS %.8lu\n", (fps >> 2) + 1);\
64 screen_fill(BG_BACK, 0, 0, 8 * 16, 8 * 12, 2);\
65 } while (0)
66
67static u32 prof_frame_counter = 0;
68
69static u32 frame_cycles = 0;
70static u32 ppu_pixel_cycles = 0;
71static u32 ppu_fill_cycles = 0;
72static u32 ppu_chr_cycles = 0;
73static u32 ppu_icn_cycles = 0;
74static u32 flip_cycles = 0;
75static u32 eval_cycles = 0;
76static u32 input_cycles = 0;
77static u32 mix_cycles = 0;
78
79static u32 avg_ppu_pixel_cycles = 0;
80static u32 avg_ppu_fill_cycles = 0;
81static u32 avg_ppu_chr_cycles = 0;
82static u32 avg_ppu_icn_cycles = 0;
83static u32 avg_flip_cycles = 0;
84static u32 avg_eval_cycles = 0;
85static u32 avg_input_cycles = 0;
86static u32 avg_mix_cycles = 0;
87static u32 avg_frame_cycles = 0;
88
89#if PROF_ENABLE == 1
90#define FRAME_START()\
91 do { \
92 if (prof_frame_counter == PROF_N_FRAMES) {\
93 avg_ppu_pixel_cycles = ppu_pixel_cycles / prof_frame_counter;\
94 avg_ppu_fill_cycles = ppu_fill_cycles / prof_frame_counter;\
95 avg_ppu_chr_cycles = ppu_chr_cycles / prof_frame_counter;\
96 avg_ppu_icn_cycles = ppu_icn_cycles / prof_frame_counter;\
97 avg_flip_cycles = flip_cycles / prof_frame_counter;\
98 avg_eval_cycles = eval_cycles / prof_frame_counter;\
99 avg_input_cycles = input_cycles / prof_frame_counter;\
100 avg_mix_cycles = mix_cycles / prof_frame_counter;\
101 avg_frame_cycles = frame_cycles / prof_frame_counter;\
102 prof_frame_counter = 0;\
103 frame_cycles = 0;\
104 ppu_pixel_cycles = 0;\
105 ppu_fill_cycles = 0;\
106 ppu_chr_cycles = 0;\
107 ppu_icn_cycles = 0;\
108 flip_cycles = 0;\
109 eval_cycles = 0;\
110 input_cycles = 0;\
111 mix_cycles = 0;\
112 }\
113 profile_start();\
114 } while (0)
115#elif PROF_ENABLE == 2
116#define FRAME_START()\
117 do { \
118 if (prof_frame_counter == PROF_N_FRAMES) {\
119 avg_ppu_pixel_cycles = ppu_pixel_cycles;\
120 avg_ppu_fill_cycles = ppu_fill_cycles;\
121 avg_ppu_chr_cycles = ppu_chr_cycles;\
122 avg_ppu_icn_cycles = ppu_icn_cycles;\
123 avg_flip_cycles = flip_cycles;\
124 avg_eval_cycles = eval_cycles;\
125 avg_input_cycles = input_cycles;\
126 avg_mix_cycles = mix_cycles;\
127 avg_frame_cycles = frame_cycles / prof_frame_counter;\
128 prof_frame_counter = 0;\
129 frame_cycles = 0;\
130 ppu_pixel_cycles = 0;\
131 ppu_fill_cycles = 0;\
132 ppu_chr_cycles = 0;\
133 ppu_icn_cycles = 0;\
134 flip_cycles = 0;\
135 eval_cycles = 0;\
136 input_cycles = 0;\
137 mix_cycles = 0;\
138 }\
139 profile_start();\
140 } while (0)
141#endif
142
143#define FRAME_END() \
144 do { \
145 prof_frame_counter++;\
146 frame_cycles += profile_stop();\
147 } while (0)
148
149#else
150
151// No profiling.
152#define PROF(F,VAR) (F)
153#define PROF_SHOW()
154#define FRAME_START()
155#define FRAME_END()
156#endif
157
diff --git a/src/uxn-core.s b/src/uxn-core.s
index a9fc3f9..32ec26b 100644
--- a/src/uxn-core.s
+++ b/src/uxn-core.s
@@ -30,532 +30,525 @@ io_ports: .space 256
30.global uxn_eval_asm 30.global uxn_eval_asm
31uxn_eval_asm: 31uxn_eval_asm:
32 @ Initialization. 32 @ Initialization.
33 push {r4-r7} 33 push {r4-r7}
34 ldr r1, wst_ptr 34 ldr r1, wst_ptr
35 ldr r2, =uxn_ram 35 ldr r2, =uxn_ram
36 add r0, r0, r2 36 add r0, r0, r2
37 37
38uxn_decode: 38uxn_decode:
39 ldrb r3, [r0], #1 @ current OP value / table index 39 ldrb r3, [r0], #1 @ current OP value / table index
40
41 @ TODO: Setup wst/rst? or fill operations accordingly?
42 @ str r3, [r1], #1 @ Push to stack: Debugging
43 40
44 @ Decode OP based on table lookup. 41 @ Decode OP based on table lookup.
45 adr r4, op_table @ decoding table 42 adr r4, op_table @ decoding table
46 ldr r4, [r4, r3, lsl #2] @ op_table[idx * 4] 43 ldr r4, [r4, r3, lsl #2] @ op_table[idx * 4]
47 bx r4 @ op_table[idx * 4]() 44 bx r4 @ op_table[idx * 4]()
48 45
49uxn_ret: 46uxn_ret:
50 @ Update stack pointer and return. 47 @ Update stack pointer and return.
51 adr r0, wst_ptr 48 adr r0, wst_ptr
52 str r1, [r0] 49 str r1, [r0]
53 pop {r4-r7} 50 pop {r4-r7}
54 bx lr 51 bx lr
55 52
56@ 53@
57@ OP implementations. 54@ OP implementations.
58@ 55@
59 56
60brk: 57brk:
61 b uxn_ret 58 b uxn_ret
62 59
63jci: 60jci:
64 b uxn_decode 61 b uxn_decode
65 62
66jmi: 63jmi:
67 b uxn_decode 64 b uxn_decode
68 65
69jsi: 66jsi:
70 b uxn_decode 67 b uxn_decode
71 68
72litr: 69litr:
73 ldrb r3, [r0], #1 70 ldrb r3, [r0], #1
74 strb r3, [r1], #1 71 strb r3, [r1], #1
75 b uxn_decode 72 b uxn_decode
76 73
77lit2r: 74lit2r:
78 ldrb r3, [r0], #1 75 ldrb r3, [r0], #1
79 ldrb r4, [r0], #1 76 ldrb r4, [r0], #1
80 strb r3, [r1], #1 77 strb r3, [r1], #1
81 strb r4, [r1], #1 78 strb r4, [r1], #1
82 b uxn_decode 79 b uxn_decode
83 80
84inc: 81inc:
85 b uxn_decode 82 b uxn_decode
86 83
87inc2: 84inc2:
88 b uxn_decode 85 b uxn_decode
89 86
90pop: 87pop:
91 b uxn_decode 88 b uxn_decode
92 89
93pop2: 90pop2:
94 b uxn_decode 91 b uxn_decode
95 92
96nip: 93nip:
97 b uxn_decode 94 b uxn_decode
98 95
99nip2: 96nip2:
100 b uxn_decode 97 b uxn_decode
101 98
102swp: 99swp:
103 b uxn_decode 100 b uxn_decode
104 101
105swp2: 102swp2:
106 b uxn_decode 103 b uxn_decode
107 104
108rot: 105rot:
109 b uxn_decode 106 b uxn_decode
110 107
111rot2: 108rot2:
112 b uxn_decode 109 b uxn_decode
113 110
114dup: 111dup:
115 b uxn_decode 112 b uxn_decode
116 113
117dup2: 114dup2:
118 b uxn_decode 115 b uxn_decode
119 116
120ovr: 117ovr:
121 b uxn_decode 118 b uxn_decode
122 119
123ovr2: 120ovr2:
124 b uxn_decode 121 b uxn_decode
125 122
126equ: 123equ:
127 b uxn_decode 124 b uxn_decode
128 125
129equ2: 126equ2:
130 b uxn_decode 127 b uxn_decode
131 128
132neq: 129neq:
133 b uxn_decode 130 b uxn_decode
134 131
135neq2: 132neq2:
136 b uxn_decode 133 b uxn_decode
137 134
138gth: 135gth:
139 b uxn_decode 136 b uxn_decode
140 137
141gth2: 138gth2:
142 b uxn_decode 139 b uxn_decode
143 140
144lth: 141lth:
145 b uxn_decode 142 b uxn_decode
146 143
147lth2: 144lth2:
148 b uxn_decode 145 b uxn_decode
149 146
150jmp: 147jmp:
151 b uxn_decode 148 b uxn_decode
152 149
153jmp2: 150jmp2:
154 b uxn_decode 151 b uxn_decode
155 152
156jcn: 153jcn:
157 b uxn_decode 154 b uxn_decode
158 155
159jcn2: 156jcn2:
160 b uxn_decode 157 b uxn_decode
161 158
162jsr: 159jsr:
163 b uxn_decode 160 b uxn_decode
164 161
165jsr2: 162jsr2:
166 b uxn_decode 163 b uxn_decode
167 164
168sth: 165sth:
169 b uxn_decode 166 b uxn_decode
170 167
171sth2: 168sth2:
172 b uxn_decode 169 b uxn_decode
173 170
174ldz: 171ldz:
175 b uxn_decode 172 b uxn_decode
176 173
177ldz2: 174ldz2:
178 b uxn_decode 175 b uxn_decode
179 176
180stz: 177stz:
181 b uxn_decode 178 b uxn_decode
182 179
183stz2: 180stz2:
184 b uxn_decode 181 b uxn_decode
185 182
186ldr: 183ldr:
187 b uxn_decode 184 b uxn_decode
188 185
189ldr2: 186ldr2:
190 b uxn_decode 187 b uxn_decode
191 188
192str: 189str:
193 b uxn_decode 190 b uxn_decode
194 191
195str2: 192str2:
196 b uxn_decode 193 b uxn_decode
197 194
198lda: 195lda:
199 b uxn_decode 196 b uxn_decode
200 197
201lda2: 198lda2:
202 b uxn_decode 199 b uxn_decode
203 200
204sta: 201sta:
205 b uxn_decode 202 b uxn_decode
206 203
207sta2: 204sta2:
208 b uxn_decode 205 b uxn_decode
209 206
210dei: 207dei:
211 b uxn_decode 208 b uxn_decode
212 209
213dei2: 210dei2:
214 b uxn_decode 211 b uxn_decode
215 212
216deo: 213deo:
217 b uxn_decode 214 b uxn_decode
218 215
219deo2: 216deo2:
220 b uxn_decode 217 b uxn_decode
221 218
222add: 219add:
223 ldr r3, [r1, #-1]! 220 ldrb r3, [r1, #-1]!
224 ldr r4, [r1, #-1]! 221 ldrb r4, [r1, #-1]!
225 add r3, r3, r4 222 add r3, r3, r4
226 strb r3, [r1], #1 223 strb r3, [r1], #1
227 b uxn_decode 224 b uxn_decode
228 225
229add2: 226add2:
230 ldrb r3, [r1, #-1]! 227 ldrb r3, [r1, #-1]!
231 lsl r3, #8 228 ldrb r5, [r1, #-1]!
232 ldrb r5, [r1, #-1]! 229 orr r3, r5, r3, lsl #8
233 add r3, r5 230 ldrb r4, [r1, #-1]!
234 ldrb r4, [r1, #-1]! 231 ldrb r5, [r1, #-1]!
235 ldrb r5, [r1, #-1]! 232 orr r4, r5, r4, lsl #8
236 lsl r4, #8 233 add r3, r3, r4
237 add r4, r5 234 strb r3, [r1], #1
238 add r3, r3, r4 235 lsr r3, #8
239 strb r3, [r1], #1 236 strb r3, [r1], #1
240 lsr r3, #8 237 b uxn_decode
241 strb r3, [r1], #1
242 b uxn_decode
243 238
244sub: 239sub:
245 ldr r3, [r1, #-1]! 240 ldr r3, [r1, #-1]!
246 ldr r4, [r1, #-1]! 241 ldr r4, [r1, #-1]!
247 sub r4, r4, r3 242 sub r4, r4, r3
248 strb r4, [r1], #1 243 strb r4, [r1], #1
249 b uxn_decode 244 b uxn_decode
250 245
251sub2: 246sub2:
252 ldrb r3, [r1, #-1]! 247 ldrb r3, [r1, #-1]!
253 ldrb r5, [r1, #-1]! 248 ldrb r5, [r1, #-1]!
254 lsl r3, #8 249 orr r3, r5, r3, lsl #8
255 add r3, r5 250 ldrb r4, [r1, #-1]!
256 ldrb r4, [r1, #-1]! 251 ldrb r5, [r1, #-1]!
257 ldrb r5, [r1, #-1]! 252 orr r4, r5, r4, lsl #8
258 lsl r4, #8 253 sub r3, r4, r3
259 add r4, r5 254 strb r3, [r1], #1
260 sub r3, r4, r3 255 lsr r3, #8
261 strb r3, [r1], #1 256 strb r3, [r1], #1
262 lsr r3, #8 257 b uxn_decode
263 strb r3, [r1], #1
264 b uxn_decode
265 258
266mul: 259mul:
267 b uxn_decode 260 b uxn_decode
268 261
269mul2: 262mul2:
270 b uxn_decode 263 b uxn_decode
271 264
272div: 265div:
273 b uxn_decode 266 b uxn_decode
274 267
275div2: 268div2:
276 b uxn_decode 269 b uxn_decode
277 270
278and: 271and:
279 b uxn_decode 272 b uxn_decode
280 273
281and2: 274and2:
282 b uxn_decode 275 b uxn_decode
283 276
284ora: 277ora:
285 b uxn_decode 278 b uxn_decode
286 279
287ora2: 280ora2:
288 b uxn_decode 281 b uxn_decode
289 282
290eor: 283eor:
291 b uxn_decode 284 b uxn_decode
292 285
293eor2: 286eor2:
294 b uxn_decode 287 b uxn_decode
295 288
296sft: 289sft:
297 b uxn_decode 290 b uxn_decode
298 291
299sft2: 292sft2:
300 b uxn_decode 293 b uxn_decode
301 294
302@ OP table 295@ OP table
303op_table: 296op_table:
304 .word brk @ 0x00 297 .word brk @ 0x00
305 .word inc @ 0x01 298 .word inc @ 0x01
306 .word pop @ 0x02 299 .word pop @ 0x02
307 .word nip @ 0x03 300 .word nip @ 0x03
308 .word swp @ 0x04 301 .word swp @ 0x04
309 .word rot @ 0x05 302 .word rot @ 0x05
310 .word dup @ 0x06 303 .word dup @ 0x06
311 .word ovr @ 0x07 304 .word ovr @ 0x07
312 .word equ @ 0x08 305 .word equ @ 0x08
313 .word neq @ 0x09 306 .word neq @ 0x09
314 .word gth @ 0x0a 307 .word gth @ 0x0a
315 .word lth @ 0x0b 308 .word lth @ 0x0b
316 .word jmp @ 0x0c 309 .word jmp @ 0x0c
317 .word jcn @ 0x0d 310 .word jcn @ 0x0d
318 .word jsr @ 0x0e 311 .word jsr @ 0x0e
319 .word sth @ 0x0f 312 .word sth @ 0x0f
320 .word ldz @ 0x00 313 .word ldz @ 0x00
321 .word stz @ 0x11 314 .word stz @ 0x11
322 .word ldr @ 0x12 315 .word ldr @ 0x12
323 .word str @ 0x13 316 .word str @ 0x13
324 .word lda @ 0x14 317 .word lda @ 0x14
325 .word sta @ 0x15 318 .word sta @ 0x15
326 .word dei @ 0x16 319 .word dei @ 0x16
327 .word deo @ 0x17 320 .word deo @ 0x17
328 .word add @ 0x18 321 .word add @ 0x18
329 .word sub @ 0x19 322 .word sub @ 0x19
330 .word mul @ 0x1a 323 .word mul @ 0x1a
331 .word div @ 0x1b 324 .word div @ 0x1b
332 .word and @ 0x1c 325 .word and @ 0x1c
333 .word ora @ 0x1d 326 .word ora @ 0x1d
334 .word eor @ 0x1e 327 .word eor @ 0x1e
335 .word sft @ 0x1f 328 .word sft @ 0x1f
336 .word brk @ 0x20 329 .word brk @ 0x20
337 .word inc2 @ 0x21 330 .word inc2 @ 0x21
338 .word pop2 @ 0x22 331 .word pop2 @ 0x22
339 .word nip2 @ 0x23 332 .word nip2 @ 0x23
340 .word swp2 @ 0x24 333 .word swp2 @ 0x24
341 .word rot2 @ 0x25 334 .word rot2 @ 0x25
342 .word dup2 @ 0x26 335 .word dup2 @ 0x26
343 .word ovr2 @ 0x27 336 .word ovr2 @ 0x27
344 .word equ2 @ 0x28 337 .word equ2 @ 0x28
345 .word neq2 @ 0x29 338 .word neq2 @ 0x29
346 .word gth2 @ 0x2a 339 .word gth2 @ 0x2a
347 .word lth2 @ 0x2b 340 .word lth2 @ 0x2b
348 .word jmp2 @ 0x2c 341 .word jmp2 @ 0x2c
349 .word jcn2 @ 0x2d 342 .word jcn2 @ 0x2d
350 .word jsr2 @ 0x2e 343 .word jsr2 @ 0x2e
351 .word sth2 @ 0x2f 344 .word sth2 @ 0x2f
352 .word ldz2 @ 0x30 345 .word ldz2 @ 0x30
353 .word stz2 @ 0x31 346 .word stz2 @ 0x31
354 .word ldr2 @ 0x32 347 .word ldr2 @ 0x32
355 .word str2 @ 0x33 348 .word str2 @ 0x33
356 .word lda2 @ 0x34 349 .word lda2 @ 0x34
357 .word sta2 @ 0x35 350 .word sta2 @ 0x35
358 .word dei2 @ 0x36 351 .word dei2 @ 0x36
359 .word deo2 @ 0x37 352 .word deo2 @ 0x37
360 .word add2 @ 0x38 353 .word add2 @ 0x38
361 .word sub2 @ 0x39 354 .word sub2 @ 0x39
362 .word mul2 @ 0x3a 355 .word mul2 @ 0x3a
363 .word div2 @ 0x3b 356 .word div2 @ 0x3b
364 .word and2 @ 0x3c 357 .word and2 @ 0x3c
365 .word ora2 @ 0x3d 358 .word ora2 @ 0x3d
366 .word eor2 @ 0x3e 359 .word eor2 @ 0x3e
367 .word sft2 @ 0x3f 360 .word sft2 @ 0x3f
368@ TODO: Can we mask this instead of having empty space? 361@ TODO: Can we mask this instead of having empty space?
369 .word brk @ 0x40 362 .word brk @ 0x40
370 .word brk @ 0x41 363 .word brk @ 0x41
371 .word brk @ 0x42 364 .word brk @ 0x42
372 .word brk @ 0x43 365 .word brk @ 0x43
373 .word brk @ 0x44 366 .word brk @ 0x44
374 .word brk @ 0x45 367 .word brk @ 0x45
375 .word brk @ 0x46 368 .word brk @ 0x46
376 .word brk @ 0x47 369 .word brk @ 0x47
377 .word brk @ 0x48 370 .word brk @ 0x48
378 .word brk @ 0x49 371 .word brk @ 0x49
379 .word brk @ 0x4a 372 .word brk @ 0x4a
380 .word brk @ 0x4b 373 .word brk @ 0x4b
381 .word brk @ 0x4c 374 .word brk @ 0x4c
382 .word brk @ 0x4d 375 .word brk @ 0x4d
383 .word brk @ 0x4e 376 .word brk @ 0x4e
384 .word brk @ 0x4f 377 .word brk @ 0x4f
385 .word brk @ 0x50 378 .word brk @ 0x50
386 .word brk @ 0x51 379 .word brk @ 0x51
387 .word brk @ 0x52 380 .word brk @ 0x52
388 .word brk @ 0x53 381 .word brk @ 0x53
389 .word brk @ 0x54 382 .word brk @ 0x54
390 .word brk @ 0x55 383 .word brk @ 0x55
391 .word brk @ 0x56 384 .word brk @ 0x56
392 .word brk @ 0x57 385 .word brk @ 0x57
393 .word brk @ 0x58 386 .word brk @ 0x58
394 .word brk @ 0x59 387 .word brk @ 0x59
395 .word brk @ 0x5a 388 .word brk @ 0x5a
396 .word brk @ 0x5b 389 .word brk @ 0x5b
397 .word brk @ 0x5c 390 .word brk @ 0x5c
398 .word brk @ 0x5d 391 .word brk @ 0x5d
399 .word brk @ 0x5e 392 .word brk @ 0x5e
400 .word brk @ 0x5f 393 .word brk @ 0x5f
401 .word brk @ 0x60 394 .word brk @ 0x60
402 .word brk @ 0x61 395 .word brk @ 0x61
403 .word brk @ 0x62 396 .word brk @ 0x62
404 .word brk @ 0x63 397 .word brk @ 0x63
405 .word brk @ 0x64 398 .word brk @ 0x64
406 .word brk @ 0x65 399 .word brk @ 0x65
407 .word brk @ 0x66 400 .word brk @ 0x66
408 .word brk @ 0x67 401 .word brk @ 0x67
409 .word brk @ 0x68 402 .word brk @ 0x68
410 .word brk @ 0x69 403 .word brk @ 0x69
411 .word brk @ 0x6a 404 .word brk @ 0x6a
412 .word brk @ 0x6b 405 .word brk @ 0x6b
413 .word brk @ 0x6c 406 .word brk @ 0x6c
414 .word brk @ 0x6d 407 .word brk @ 0x6d
415 .word brk @ 0x6e 408 .word brk @ 0x6e
416 .word brk @ 0x6f 409 .word brk @ 0x6f
417 .word brk @ 0x70 410 .word brk @ 0x70
418 .word brk @ 0x71 411 .word brk @ 0x71
419 .word brk @ 0x72 412 .word brk @ 0x72
420 .word brk @ 0x73 413 .word brk @ 0x73
421 .word brk @ 0x74 414 .word brk @ 0x74
422 .word brk @ 0x75 415 .word brk @ 0x75
423 .word brk @ 0x76 416 .word brk @ 0x76
424 .word brk @ 0x77 417 .word brk @ 0x77
425 .word brk @ 0x78 418 .word brk @ 0x78
426 .word brk @ 0x79 419 .word brk @ 0x79
427 .word brk @ 0x7a 420 .word brk @ 0x7a
428 .word brk @ 0x7b 421 .word brk @ 0x7b
429 .word brk @ 0x7c 422 .word brk @ 0x7c
430 .word brk @ 0x7d 423 .word brk @ 0x7d
431 .word brk @ 0x7e 424 .word brk @ 0x7e
432 .word brk @ 0x7f 425 .word brk @ 0x7f
433 .word litr @ 0x80 426 .word litr @ 0x80
434 .word brk @ 0x81 427 .word brk @ 0x81
435 .word brk @ 0x82 428 .word brk @ 0x82
436 .word brk @ 0x83 429 .word brk @ 0x83
437 .word brk @ 0x84 430 .word brk @ 0x84
438 .word brk @ 0x85 431 .word brk @ 0x85
439 .word brk @ 0x86 432 .word brk @ 0x86
440 .word brk @ 0x87 433 .word brk @ 0x87
441 .word brk @ 0x88 434 .word brk @ 0x88
442 .word brk @ 0x89 435 .word brk @ 0x89
443 .word brk @ 0x8a 436 .word brk @ 0x8a
444 .word brk @ 0x8b 437 .word brk @ 0x8b
445 .word brk @ 0x8c 438 .word brk @ 0x8c
446 .word brk @ 0x8d 439 .word brk @ 0x8d
447 .word brk @ 0x8e 440 .word brk @ 0x8e
448 .word brk @ 0x8f 441 .word brk @ 0x8f
449 .word brk @ 0x90 442 .word brk @ 0x90
450 .word brk @ 0x91 443 .word brk @ 0x91
451 .word brk @ 0x92 444 .word brk @ 0x92
452 .word brk @ 0x93 445 .word brk @ 0x93
453 .word brk @ 0x94 446 .word brk @ 0x94
454 .word brk @ 0x95 447 .word brk @ 0x95
455 .word brk @ 0x96 448 .word brk @ 0x96
456 .word brk @ 0x97 449 .word brk @ 0x97
457 .word brk @ 0x98 450 .word brk @ 0x98
458 .word brk @ 0x99 451 .word brk @ 0x99
459 .word brk @ 0x9a 452 .word brk @ 0x9a
460 .word brk @ 0x9b 453 .word brk @ 0x9b
461 .word brk @ 0x9c 454 .word brk @ 0x9c
462 .word brk @ 0x9d 455 .word brk @ 0x9d
463 .word brk @ 0x9e 456 .word brk @ 0x9e
464 .word brk @ 0x9f 457 .word brk @ 0x9f
465 .word lit2r @ 0xa0 458 .word lit2r @ 0xa0
466 .word brk @ 0xa1 459 .word brk @ 0xa1
467 .word brk @ 0xa2 460 .word brk @ 0xa2
468 .word brk @ 0xa3 461 .word brk @ 0xa3
469 .word brk @ 0xa4 462 .word brk @ 0xa4
470 .word brk @ 0xa5 463 .word brk @ 0xa5
471 .word brk @ 0xa6 464 .word brk @ 0xa6
472 .word brk @ 0xa7 465 .word brk @ 0xa7
473 .word brk @ 0xa8 466 .word brk @ 0xa8
474 .word brk @ 0xa9 467 .word brk @ 0xa9
475 .word brk @ 0xaa 468 .word brk @ 0xaa
476 .word brk @ 0xab 469 .word brk @ 0xab
477 .word brk @ 0xac 470 .word brk @ 0xac
478 .word brk @ 0xad 471 .word brk @ 0xad
479 .word brk @ 0xae 472 .word brk @ 0xae
480 .word brk @ 0xaf 473 .word brk @ 0xaf
481 .word brk @ 0xb0 474 .word brk @ 0xb0
482 .word brk @ 0xb1 475 .word brk @ 0xb1
483 .word brk @ 0xb2 476 .word brk @ 0xb2
484 .word brk @ 0xb3 477 .word brk @ 0xb3
485 .word brk @ 0xb4 478 .word brk @ 0xb4
486 .word brk @ 0xb5 479 .word brk @ 0xb5
487 .word brk @ 0xb6 480 .word brk @ 0xb6
488 .word brk @ 0xb7 481 .word brk @ 0xb7
489 .word brk @ 0xb8 482 .word brk @ 0xb8
490 .word brk @ 0xb9 483 .word brk @ 0xb9
491 .word brk @ 0xba 484 .word brk @ 0xba
492 .word brk @ 0xbb 485 .word brk @ 0xbb
493 .word brk @ 0xbc 486 .word brk @ 0xbc
494 .word brk @ 0xbd 487 .word brk @ 0xbd
495 .word brk @ 0xbe 488 .word brk @ 0xbe
496 .word brk @ 0xbf 489 .word brk @ 0xbf
497 .word brk @ 0xc0 490 .word brk @ 0xc0
498 .word brk @ 0xc1 491 .word brk @ 0xc1
499 .word brk @ 0xc2 492 .word brk @ 0xc2
500 .word brk @ 0xc3 493 .word brk @ 0xc3
501 .word brk @ 0xc4 494 .word brk @ 0xc4
502 .word brk @ 0xc5 495 .word brk @ 0xc5
503 .word brk @ 0xc6 496 .word brk @ 0xc6
504 .word brk @ 0xc7 497 .word brk @ 0xc7
505 .word brk @ 0xc8 498 .word brk @ 0xc8
506 .word brk @ 0xc9 499 .word brk @ 0xc9
507 .word brk @ 0xca 500 .word brk @ 0xca
508 .word brk @ 0xcb 501 .word brk @ 0xcb
509 .word brk @ 0xcc 502 .word brk @ 0xcc
510 .word brk @ 0xcd 503 .word brk @ 0xcd
511 .word brk @ 0xce 504 .word brk @ 0xce
512 .word brk @ 0xcf 505 .word brk @ 0xcf
513 .word brk @ 0xd0 506 .word brk @ 0xd0
514 .word brk @ 0xd1 507 .word brk @ 0xd1
515 .word brk @ 0xd2 508 .word brk @ 0xd2
516 .word brk @ 0xd3 509 .word brk @ 0xd3
517 .word brk @ 0xd4 510 .word brk @ 0xd4
518 .word brk @ 0xd5 511 .word brk @ 0xd5
519 .word brk @ 0xd6 512 .word brk @ 0xd6
520 .word brk @ 0xd7 513 .word brk @ 0xd7
521 .word brk @ 0xd8 514 .word brk @ 0xd8
522 .word brk @ 0xd9 515 .word brk @ 0xd9
523 .word brk @ 0xda 516 .word brk @ 0xda
524 .word brk @ 0xdb 517 .word brk @ 0xdb
525 .word brk @ 0xdc 518 .word brk @ 0xdc
526 .word brk @ 0xdd 519 .word brk @ 0xdd
527 .word brk @ 0xde 520 .word brk @ 0xde
528 .word brk @ 0xdf 521 .word brk @ 0xdf
529 .word brk @ 0xe0 522 .word brk @ 0xe0
530 .word brk @ 0xe1 523 .word brk @ 0xe1
531 .word brk @ 0xe2 524 .word brk @ 0xe2
532 .word brk @ 0xe3 525 .word brk @ 0xe3
533 .word brk @ 0xe4 526 .word brk @ 0xe4
534 .word brk @ 0xe5 527 .word brk @ 0xe5
535 .word brk @ 0xe6 528 .word brk @ 0xe6
536 .word brk @ 0xe7 529 .word brk @ 0xe7
537 .word brk @ 0xe8 530 .word brk @ 0xe8
538 .word brk @ 0xe9 531 .word brk @ 0xe9
539 .word brk @ 0xea 532 .word brk @ 0xea
540 .word brk @ 0xeb 533 .word brk @ 0xeb
541 .word brk @ 0xec 534 .word brk @ 0xec
542 .word brk @ 0xed 535 .word brk @ 0xed
543 .word brk @ 0xee 536 .word brk @ 0xee
544 .word brk @ 0xef 537 .word brk @ 0xef
545 .word brk @ 0xf0 538 .word brk @ 0xf0
546 .word brk @ 0xf1 539 .word brk @ 0xf1
547 .word brk @ 0xf2 540 .word brk @ 0xf2
548 .word brk @ 0xf3 541 .word brk @ 0xf3
549 .word brk @ 0xf4 542 .word brk @ 0xf4
550 .word brk @ 0xf5 543 .word brk @ 0xf5
551 .word brk @ 0xf6 544 .word brk @ 0xf6
552 .word brk @ 0xf7 545 .word brk @ 0xf7
553 .word brk @ 0xf8 546 .word brk @ 0xf8
554@ TODO: Can we mask this instead of having empty space? 547@ TODO: Can we mask this instead of having empty space?
555 .word lit2r @ 0xf9 548 .word lit2r @ 0xf9
556 .word litr @ 0xfa 549 .word litr @ 0xfa
557 .word lit2r @ 0xfb 550 .word lit2r @ 0xfb
558 .word litr @ 0xfc 551 .word litr @ 0xfc
559 .word jsi @ 0xfd 552 .word jsi @ 0xfd
560 .word jmi @ 0xfe 553 .word jmi @ 0xfe
561 .word jci @ 0xff 554 .word jci @ 0xff