aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c701
1 files changed, 18 insertions, 683 deletions
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.