diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 701 |
1 files changed, 18 insertions, 683 deletions
@@ -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. | 30 | u8 stack[STACK_SIZE] = {0}; |
28 | // | 31 | extern 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 | |||
107 | static u32 prof_frame_counter = 0; | ||
108 | |||
109 | static u32 frame_cycles = 0; | ||
110 | static u32 ppu_pixel_cycles = 0; | ||
111 | static u32 ppu_fill_cycles = 0; | ||
112 | static u32 ppu_chr_cycles = 0; | ||
113 | static u32 ppu_icn_cycles = 0; | ||
114 | static u32 flip_cycles = 0; | ||
115 | static u32 eval_cycles = 0; | ||
116 | static u32 input_cycles = 0; | ||
117 | static u32 mix_cycles = 0; | ||
118 | |||
119 | static u32 avg_ppu_pixel_cycles = 0; | ||
120 | static u32 avg_ppu_fill_cycles = 0; | ||
121 | static u32 avg_ppu_chr_cycles = 0; | ||
122 | static u32 avg_ppu_icn_cycles = 0; | ||
123 | static u32 avg_flip_cycles = 0; | ||
124 | static u32 avg_eval_cycles = 0; | ||
125 | static u32 avg_input_cycles = 0; | ||
126 | static u32 avg_mix_cycles = 0; | ||
127 | static 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 | |||
198 | static time_t seconds = 0; | ||
199 | |||
200 | typedef enum { | ||
201 | CONTROL_CONTROLLER, | ||
202 | CONTROL_MOUSE, | ||
203 | CONTROL_KEYBOARD, | ||
204 | } ControlMethod; | ||
205 | |||
206 | const ControlMethod ctrl_methods[] = { | ||
207 | CONTROL_METHODS | ||
208 | }; | ||
209 | static 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 |
212 | typedef struct Mouse { | 34 | // we will use very often. |
213 | int x; | 35 | extern u8 wst[256]; |
214 | int y; | 36 | extern u8 rst[256]; |
215 | } Mouse; | 37 | extern u8 io_ports[256]; |
38 | extern uintptr_t wst_ptr; | ||
39 | extern uintptr_t rst_ptr; | ||
216 | 40 | ||
217 | EWRAM_BSS | 41 | EWRAM_BSS |
218 | u8 uxn_ram[0x10300]; | 42 | u8 uxn_ram[KB(64) * 2]; |
219 | |||
220 | // static Uxn u; | ||
221 | |||
222 | static 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 | |||
234 | IWRAM_CODE | ||
235 | u8 | ||
236 | screen_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 | |||
246 | IWRAM_CODE | ||
247 | void | ||
248 | screen_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 | |||
312 | u8 | ||
313 | audio_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 | |||
326 | void | ||
327 | audio_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 | |||
344 | u8 | ||
345 | datetime_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 | |||
363 | u8 | ||
364 | file_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 | |||
378 | void | ||
379 | file_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 | |||
423 | void | ||
424 | console_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 | |||
438 | static void | ||
439 | system_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 | |||
466 | void | ||
467 | system_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 | |||
475 | u8 | ||
476 | uxn_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 | |||
491 | void | ||
492 | uxn_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 | ||
512 | void | 44 | void |
513 | init_uxn() { | 45 | init_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 | ||
556 | IWRAM_CODE | ||
557 | void | ||
558 | handle_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 | ||
743 | u8 stack[STACK_SIZE] = {0}; | ||
744 | extern 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. | ||
748 | extern u8 wst[256]; | ||
749 | extern u8 rst[256]; | ||
750 | extern u8 io_ports[256]; | ||
751 | extern uintptr_t wst_ptr; | ||
752 | extern uintptr_t rst_ptr; | ||
753 | |||
754 | int | 89 | int |
755 | main(void) { | 90 | main(void) { |
756 | // Adjust system wait times. | 91 | // Adjust system wait times. |