diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 527 |
1 files changed, 70 insertions, 457 deletions
@@ -1,474 +1,79 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (c) 2021 Bad Diode | 2 | Copyright (c) 2021 Bad Diode |
3 | 3 | ||
4 | Permission to use, copy, modify, and distribute this software for any | 4 | Permission to use, copy, modify, and distribute this software for any |
5 | purpose with or without fee is hereby granted, provided that the above | 5 | purpose with or without fee is hereby granted, provided that the above |
6 | copyright notice and this permission notice appear in all copies. | 6 | copyright notice and this permission notice appear in all copies. |
7 | 7 | ||
8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | WITH REGARD TO THIS SOFTWARE. | 9 | WITH REGARD TO THIS SOFTWARE. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <string.h> | 12 | #include <string.h> |
13 | #include <time.h> | 13 | #include <time.h> |
14 | 14 | ||
15 | #include "common.h" | 15 | #include "common.h" |
16 | #include "bitmap.h" | ||
17 | #include "filesystem.c" | 16 | #include "filesystem.c" |
18 | 17 | ||
18 | #include "uxn-core.c" | ||
19 | |||
19 | #include "rom.c" | 20 | #include "rom.c" |
20 | #include "uxn.c" | ||
21 | #include "ppu.c" | 21 | #include "ppu.c" |
22 | #include "apu.c" | 22 | #include "apu.c" |
23 | #include "file.c" | 23 | #include "file.c" |
24 | #include "text.h" | 24 | #include "text.h" |
25 | 25 | ||
26 | // | 26 | #include "config.c" |
27 | // Config parameters. | 27 | #include "profiling.c" |
28 | // | 28 | #include "input.c" |
29 | 29 | #include "devices.c" | |
30 | #if !defined(TEXT_MODE) || TEXT_MODE == 0 | 30 | #include "debug.c" |
31 | #define TEXT_LAYER ppu.fg | ||
32 | #else | ||
33 | #define TEXT_LAYER ppu.bg | ||
34 | #endif | ||
35 | |||
36 | #ifndef CONTROL_METHODS | ||
37 | #define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD | ||
38 | #endif | ||
39 | |||
40 | #ifdef PROF_ENABLE | ||
41 | #if PROF_ENABLE == 0 | ||
42 | #define PROF(F,VAR) (profile_start(),(F),(VAR) = profile_stop()) | ||
43 | #elif PROF_ENABLE == 1 | ||
44 | #define PROF(F,VAR) (profile_start(),(F),(VAR) = MAX(profile_stop(), (VAR))) | ||
45 | #endif | ||
46 | #ifndef PROF_SHOW_X | ||
47 | #define PROF_SHOW_X 0 | ||
48 | #endif | ||
49 | #ifndef PROF_SHOW_Y | ||
50 | #define PROF_SHOW_Y 0 | ||
51 | #endif | ||
52 | #define PROF_SHOW() \ | ||
53 | do { \ | ||
54 | txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\ | ||
55 | txt_printf("INPUT: %lu ", input_cycles);\ | ||
56 | txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+1);\ | ||
57 | txt_printf("EVAL: %lu ", eval_cycles);\ | ||
58 | txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+2);\ | ||
59 | txt_printf("FLIP: %lu ", flip_cycles);\ | ||
60 | txt_position((PROF_SHOW_X), (PROF_SHOW_Y)+3);\ | ||
61 | txt_printf("MIX: %lu ", mix_cycles);\ | ||
62 | } while (0) | ||
63 | #define PROF_INIT() \ | ||
64 | u32 flip_cycles = 0;\ | ||
65 | u32 eval_cycles = 0;\ | ||
66 | u32 input_cycles = 0;\ | ||
67 | u32 mix_cycles = 0; | ||
68 | #else | ||
69 | #define PROF(F,VAR) (F) | ||
70 | #define PROF_SHOW() | ||
71 | #define PROF_INIT() | ||
72 | #endif | ||
73 | |||
74 | static time_t seconds = 0; | ||
75 | |||
76 | typedef enum { | ||
77 | CONTROL_CONTROLLER, | ||
78 | CONTROL_MOUSE, | ||
79 | CONTROL_KEYBOARD, | ||
80 | } ControlMethod; | ||
81 | |||
82 | const ControlMethod ctrl_methods[] = { | ||
83 | CONTROL_METHODS | ||
84 | }; | ||
85 | static ControlMethod ctrl_idx = 0; | ||
86 | |||
87 | #define MOUSE_DELTA 1 | ||
88 | typedef struct Mouse { | ||
89 | int x; | ||
90 | int y; | ||
91 | } Mouse; | ||
92 | |||
93 | static Ppu ppu; | ||
94 | static Device *devscreen; | ||
95 | static Device *devctrl; | ||
96 | static Device *devmouse; | ||
97 | static Device *devaudio; | ||
98 | |||
99 | static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}; | ||
100 | |||
101 | void | ||
102 | nil_talk(Device *d, u8 b0, u8 w) { | ||
103 | (void)d; | ||
104 | (void)b0; | ||
105 | (void)w; | ||
106 | } | ||
107 | |||
108 | void | ||
109 | console_talk(Device *d, u8 b0, u8 w) { | ||
110 | char stmp[2]; | ||
111 | if(!w) { | ||
112 | return; | ||
113 | } | ||
114 | switch(b0) { | ||
115 | case 0x8: stmp[0] = d->dat[0x8]; stmp[1] = 0; txt_printf(stmp); break; | ||
116 | case 0x9: txt_printf("0x%02x", d->dat[0x9]); break; | ||
117 | case 0xb: txt_printf("0x%04x", mempeek16(d->dat, 0xa)); break; | ||
118 | case 0xd: txt_printf("%s", &d->mem[mempeek16(d->dat, 0xc)]); break; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | void | ||
123 | system_talk(Device *d, u8 b0, u8 w) { | ||
124 | if(!w) { | ||
125 | d->dat[0x2] = d->u->wst.ptr; | ||
126 | d->dat[0x3] = d->u->rst.ptr; | ||
127 | } else { | ||
128 | putcolors(&d->dat[0x8]); | ||
129 | } | ||
130 | (void)b0; | ||
131 | } | ||
132 | |||
133 | IWRAM_CODE | ||
134 | void | ||
135 | screen_talk(Device *d, u8 b0, u8 w) { | ||
136 | if (w) { | ||
137 | switch (b0) { | ||
138 | case 0x1: { | ||
139 | d->vector = mempeek16(d->dat, 0x0); | ||
140 | } break; | ||
141 | case 0xe: { | ||
142 | u16 x, y; | ||
143 | u8 layer = d->dat[0xe] & 0x40; | ||
144 | DEVPEEK16(x, 0x8); | ||
145 | DEVPEEK16(y, 0xa); | ||
146 | ppu_pixel(layer ? ppu.fg : ppu.bg, x, y, d->dat[0xe] & 0x3); | ||
147 | if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 1); /* auto x+1 */ | ||
148 | if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 1); /* auto y+1 */ | ||
149 | } break; | ||
150 | case 0xf: { | ||
151 | u16 x, y, dx, dy, addr; | ||
152 | u8 twobpp = !!(d->dat[0xf] & 0x80); | ||
153 | DEVPEEK16(x, 0x8); | ||
154 | DEVPEEK16(y, 0xa); | ||
155 | DEVPEEK16(addr, 0xc); | ||
156 | u8 n = d->dat[0x6] >> 4; | ||
157 | dx = (d->dat[0x6] & 0x01) << 3; | ||
158 | dy = (d->dat[0x6] & 0x02) << 2; | ||
159 | if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) { | ||
160 | return; | ||
161 | } | ||
162 | u8 *layer = (d->dat[0xf] & 0x40) ? ppu.fg : ppu.bg; | ||
163 | u8 color = d->dat[0xf] & 0xf; | ||
164 | u8 flipx = d->dat[0xf] & 0x10; | ||
165 | u8 flipy = d->dat[0xf] & 0x20; | ||
166 | for(size_t i = 0; i <= n; i++) { | ||
167 | u8 *sprite = &d->mem[addr]; | ||
168 | if (twobpp) { | ||
169 | ppu_2bpp(layer, x + dy * i, y + dx * i, sprite, color, flipx, flipy); | ||
170 | } else { | ||
171 | ppu_1bpp(layer, x + dy * i, y + dx * i, sprite, color, flipx, flipy); | ||
172 | } | ||
173 | addr += (d->dat[0x6] & 0x04) << (1 + twobpp); | ||
174 | } | ||
175 | DEVPOKE16(0xc, addr); /* auto addr+length */ | ||
176 | DEVPOKE16(0x8, x + dx); /* auto x+8 */ | ||
177 | DEVPOKE16(0xa, y + dy); /* auto y+8 */ | ||
178 | } break; | ||
179 | default: break; | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void | ||
185 | audio_talk(Device *d, u8 b0, u8 w) { | ||
186 | AudioChannel *c = &channels[d - devaudio]; | ||
187 | if(!w) { | ||
188 | if(b0 == 0x2) { | ||
189 | mempoke16(d->dat, 0x2, c->pos); | ||
190 | c->pos <<= 12; // fixed point. | ||
191 | } else if(b0 == 0x4) { | ||
192 | // d->dat[0x4] = apu_get_vu(c); | ||
193 | } | ||
194 | } else if(b0 == 0xf) { | ||
195 | u16 length = mempeek16(d->dat, 0xa); | ||
196 | u8 *data = &d->mem[mempeek16(d->dat, 0xc)]; | ||
197 | u8 pitch = d->dat[0xf] & 0x7f; | ||
198 | u16 adsr = mempeek16(d->dat, 0x8); | ||
199 | u32 vol = MAX(d->dat[0xe] >> 4, d->dat[0xe] & 0xf) * 4 / 3; | ||
200 | bool loop = !(d->dat[0xf] & 0x80); | ||
201 | update_channel(c, data, length, pitch, adsr, vol, loop); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | void | ||
206 | datetime_talk(Device *d, u8 b0, u8 w) { | ||
207 | (void)b0; | ||
208 | (void)w; | ||
209 | struct tm *t = gmtime(&seconds); | ||
210 | t->tm_year += 1900; | ||
211 | DEVPOKE16(0x0, t->tm_year); | ||
212 | d->dat[0x2] = t->tm_mon; | ||
213 | d->dat[0x3] = t->tm_mday; | ||
214 | d->dat[0x4] = t->tm_hour; | ||
215 | d->dat[0x5] = t->tm_min; | ||
216 | d->dat[0x6] = t->tm_sec; | ||
217 | d->dat[0x7] = t->tm_wday; | ||
218 | DEVPOKE16(0x08, t->tm_yday); | ||
219 | d->dat[0xa] = t->tm_isdst; | ||
220 | } | ||
221 | |||
222 | void | ||
223 | file_talk(Device *d, u8 b0, u8 w) { | ||
224 | if (w) { | ||
225 | u16 a, b, res; | ||
226 | switch(b0) { | ||
227 | case 0x5: { | ||
228 | DEVPEEK16(a, 0x4); | ||
229 | DEVPEEK16(b, 0xa); | ||
230 | if(b > 0x10000 - a) { | ||
231 | b = 0x10000 - a; | ||
232 | } | ||
233 | res = file_stat(&d->mem[a], b); | ||
234 | DEVPOKE16(0x2, res); | ||
235 | } break; | ||
236 | case 0x6: { | ||
237 | // res = file_delete(); | ||
238 | // DEVPOKE16(0x2, res); | ||
239 | } break; | ||
240 | case 0x9: { | ||
241 | DEVPEEK16(a, 0x8); | ||
242 | res = file_init(&d->mem[a]); | ||
243 | DEVPOKE16(0x2, res); | ||
244 | } break; | ||
245 | case 0xd: { | ||
246 | DEVPEEK16(a, 0xc); | ||
247 | DEVPEEK16(b, 0xa); | ||
248 | if(b > 0x10000 - a) { | ||
249 | b = 0x10000 - a; | ||
250 | } | ||
251 | res = file_read(&d->mem[a], b); | ||
252 | DEVPOKE16(0x2, res); | ||
253 | } break; | ||
254 | case 0xf: { | ||
255 | DEVPEEK16(a, 0xe); | ||
256 | DEVPEEK16(b, 0xa); | ||
257 | if(b > 0x10000 - a) { | ||
258 | b = 0x10000 - a; | ||
259 | } | ||
260 | res = file_write(&d->mem[a], b, d->dat[0x7]); | ||
261 | DEVPOKE16(0x2, res); | ||
262 | } break; | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | |||
267 | void | ||
268 | init_uxn(Uxn *u) { | ||
269 | // Initialize PPU. | ||
270 | initppu(&ppu, 30, 20, 0); | ||
271 | |||
272 | // Enable sound. | ||
273 | init_sound(); | ||
274 | |||
275 | // Copy rom to VM. | ||
276 | memcpy(u->ram.dat + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); | ||
277 | |||
278 | // Prepare devices. | ||
279 | uxn_port(u, 0x0, "system", system_talk); | ||
280 | uxn_port(u, 0x1, "console", console_talk); | ||
281 | devscreen = uxn_port(u, 0x2, "screen", screen_talk); | ||
282 | devaudio = uxn_port(u, 0x3, "audio0", audio_talk); | ||
283 | uxn_port(u, 0x4, "audio1", audio_talk); | ||
284 | uxn_port(u, 0x5, "audio2", audio_talk); | ||
285 | uxn_port(u, 0x6, "audio3", audio_talk); | ||
286 | uxn_port(u, 0x7, "---", nil_talk); | ||
287 | devctrl = uxn_port(u, 0x8, "controller", nil_talk); | ||
288 | devmouse = uxn_port(u, 0x9, "mouse", nil_talk); | ||
289 | uxn_port(u, 0xa, "file1", file_talk); | ||
290 | uxn_port(u, 0xb, "file2", file_talk); // TODO: support second file device | ||
291 | uxn_port(u, 0xc, "datetime", datetime_talk); | ||
292 | uxn_port(u, 0xd, "---", nil_talk); | ||
293 | uxn_port(u, 0xe, "---", nil_talk); | ||
294 | uxn_port(u, 0xf, "---", nil_talk); | ||
295 | mempoke16(devscreen->dat, 2, ppu.hor * 8); | ||
296 | mempoke16(devscreen->dat, 4, ppu.ver * 8); | ||
297 | } | ||
298 | 31 | ||
299 | IWRAM_CODE | ||
300 | void | 32 | void |
301 | handle_input(Uxn *u) { | 33 | init_uxn() { |
302 | poll_keys(); | 34 | // Initialize uxn. |
303 | if (key_tap(KEY_SELECT)) { | 35 | u32 fill = 0; |
304 | // Reset control variables on method switch. | 36 | dma_fill(uxn_ram, fill, sizeof(uxn_ram), 3); |
305 | switch (ctrl_methods[ctrl_idx]) { | 37 | uxn_rom = _binary_build_uxn_rom_start; |
306 | case CONTROL_CONTROLLER: { | 38 | uxn_rom_size = (size_t)_binary_build_uxn_rom_size; |
307 | devctrl->dat[2] = 0; | 39 | size_t size = MIN(0x10000 - PAGE_PROGRAM, uxn_rom_size); |
308 | uxn_eval(u, mempeek16(devctrl->dat, 0)); | 40 | memcpy(uxn_ram + PAGE_PROGRAM, uxn_rom, size); |
309 | devctrl->dat[3] = 0; | 41 | |
310 | } break; | 42 | // Initialize stack and device memory. |
311 | case CONTROL_MOUSE: { | 43 | for (size_t i = 0; i < 256; i++) { |
312 | devmouse->dat[6] = 0; | 44 | wst[i] = 0; |
313 | devmouse->dat[7] = 0; | 45 | rst[i] = 0; |
314 | mempoke16(devmouse->dat, 0x2, -10); | 46 | device_data[i] = 0; |
315 | mempoke16(devmouse->dat, 0x4, -10); | ||
316 | uxn_eval(u, mempeek16(devmouse->dat, 0)); | ||
317 | } break; | ||
318 | case CONTROL_KEYBOARD: { | ||
319 | toggle_keyboard(); | ||
320 | } break; | ||
321 | } | ||
322 | |||
323 | // Update ctrl_idx. | ||
324 | ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1; | ||
325 | |||
326 | // Initialize controller variables here. | ||
327 | if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) { | ||
328 | toggle_keyboard(); | ||
329 | } | ||
330 | } | 47 | } |
331 | 48 | ||
332 | if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) { | 49 | // Setup deo/dei maps. |
333 | // TODO: We don't need ifs if we use KEY_INPUTS directly and mayvbe just | 50 | for (size_t i = 0; i < 16; i++) { |
334 | // swap some things if needed. | 51 | deo_map[i] = (uintptr_t) deo_stub; |
335 | u8 *flag = &devctrl->dat[2]; | 52 | dei_map[i] = (uintptr_t) dei_stub; |
336 | if (key_pressed(KEY_A)) { | ||
337 | *flag |= 0x01; | ||
338 | } else { | ||
339 | *flag &= ~0x01; | ||
340 | } | ||
341 | if (key_pressed(KEY_B)) { | ||
342 | *flag |= 0x02; | ||
343 | } else { | ||
344 | *flag &= ~0x02; | ||
345 | } | ||
346 | if (key_pressed(KEY_L)) { | ||
347 | *flag |= 0x04; | ||
348 | } else { | ||
349 | *flag &= ~0x04; | ||
350 | } | ||
351 | if (key_pressed(KEY_R)) { | ||
352 | *flag |= 0x08; | ||
353 | } else { | ||
354 | *flag &= ~0x08; | ||
355 | } | ||
356 | if (key_pressed(KEY_UP)) { | ||
357 | *flag |= 0x10; | ||
358 | } else { | ||
359 | *flag &= ~0x10; | ||
360 | } | ||
361 | if (key_pressed(KEY_DOWN)) { | ||
362 | *flag |= 0x20; | ||
363 | } else { | ||
364 | *flag &= ~0x20; | ||
365 | } | ||
366 | if (key_pressed(KEY_LEFT)) { | ||
367 | *flag |= 0x40; | ||
368 | } else { | ||
369 | *flag &= ~0x40; | ||
370 | } | ||
371 | if (key_pressed(KEY_RIGHT)) { | ||
372 | *flag |= 0x80; | ||
373 | } else { | ||
374 | *flag &= ~0x80; | ||
375 | } | ||
376 | |||
377 | uxn_eval(u, mempeek16(devctrl->dat, 0)); | ||
378 | devctrl->dat[3] = 0; | ||
379 | } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) { | ||
380 | // Detect "mouse key press". | ||
381 | u8 flag = devmouse->dat[6]; | ||
382 | if (key_tap(KEY_B)) { | ||
383 | flag |= 0x01; | ||
384 | } else if (key_released(KEY_B)) { | ||
385 | flag &= ~0x01; | ||
386 | } | ||
387 | if (key_tap(KEY_A)) { | ||
388 | flag |= 0x10; | ||
389 | } else if (key_released(KEY_A)) { | ||
390 | flag &= ~0x10; | ||
391 | } | ||
392 | |||
393 | // Handle chording. | ||
394 | devmouse->dat[6] = flag; | ||
395 | if(flag == 0x10 && (devmouse->dat[6] & 0x01)) { | ||
396 | devmouse->dat[7] = 0x01; | ||
397 | } | ||
398 | if(flag == 0x01 && (devmouse->dat[6] & 0x10)) { | ||
399 | devmouse->dat[7] = 0x10; | ||
400 | } | ||
401 | |||
402 | // Detect mouse movement. | ||
403 | if (key_pressed(KEY_UP)) { | ||
404 | mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); | ||
405 | } else if (key_pressed(KEY_DOWN)) { | ||
406 | mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); | ||
407 | } | ||
408 | if (key_pressed(KEY_LEFT)) { | ||
409 | mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8); | ||
410 | } else if (key_pressed(KEY_RIGHT)) { | ||
411 | mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8); | ||
412 | } | ||
413 | |||
414 | // Eval mouse. | ||
415 | mempoke16(devmouse->dat, 0x2, mouse.x); | ||
416 | mempoke16(devmouse->dat, 0x4, mouse.y); | ||
417 | uxn_eval(u, mempeek16(devmouse->dat, 0)); | ||
418 | } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) { | ||
419 | if (key_tap(KEY_LEFT)) { | ||
420 | update_cursor(cursor_position - 1); | ||
421 | } else if (key_tap(KEY_RIGHT)) { | ||
422 | update_cursor(cursor_position + 1); | ||
423 | } | ||
424 | if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) { | ||
425 | update_cursor(cursor_position - KEYBOARD_ROW_SIZE); | ||
426 | } else if (key_tap(KEY_DOWN) | ||
427 | && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) { | ||
428 | update_cursor(cursor_position + KEYBOARD_ROW_SIZE); | ||
429 | } | ||
430 | if (key_tap(KEY_B)) { | ||
431 | u8 symbol = keyboard[cursor_position].symbol; | ||
432 | switch (symbol) { | ||
433 | case 0x7f: { | ||
434 | // Backspace. | ||
435 | devctrl->dat[3] = 0x08; | ||
436 | } break; | ||
437 | case 0x14: { | ||
438 | // New line. | ||
439 | devctrl->dat[3] = 0x0d; | ||
440 | } break; | ||
441 | case 0x18: { | ||
442 | // Arrow up. | ||
443 | devctrl->dat[2] = 0x10; | ||
444 | } break; | ||
445 | case 0x19: { | ||
446 | // Arrow down. | ||
447 | devctrl->dat[2] = 0x20; | ||
448 | } break; | ||
449 | case 0x1b: { | ||
450 | // Arrow left. | ||
451 | devctrl->dat[2] = 0x40; | ||
452 | } break; | ||
453 | case 0x1a: { | ||
454 | // Arrow right. | ||
455 | devctrl->dat[2] = 0x80; | ||
456 | } break; | ||
457 | default: { | ||
458 | devctrl->dat[3] = symbol; | ||
459 | } break; | ||
460 | } | ||
461 | uxn_eval(u, mempeek16(devctrl->dat, 0)); | ||
462 | devctrl->dat[3] = 0; | ||
463 | } | ||
464 | } | 53 | } |
54 | deo_map[0x0] = (uintptr_t) deo_system; | ||
55 | dei_map[0x0] = (uintptr_t) dei_system; | ||
56 | deo_map[0x1] = (uintptr_t) deo_console; | ||
57 | deo_map[0x2] = (uintptr_t) deo_screen; | ||
58 | dei_map[0x2] = (uintptr_t) dei_screen; | ||
59 | deo_map[0x3] = (uintptr_t) deo_audio; | ||
60 | dei_map[0x3] = (uintptr_t) dei_audio; | ||
61 | deo_map[0x4] = (uintptr_t) deo_audio; | ||
62 | dei_map[0x4] = (uintptr_t) dei_audio; | ||
63 | deo_map[0x5] = (uintptr_t) deo_audio; | ||
64 | dei_map[0x5] = (uintptr_t) dei_audio; | ||
65 | deo_map[0x6] = (uintptr_t) deo_audio; | ||
66 | dei_map[0x6] = (uintptr_t) dei_audio; | ||
67 | deo_map[0xa] = (uintptr_t) deo_file; | ||
68 | dei_map[0xa] = (uintptr_t) dei_file; | ||
69 | deo_map[0xb] = (uintptr_t) deo_file; | ||
70 | dei_map[0xb] = (uintptr_t) dei_file; | ||
71 | dei_map[0xc] = (uintptr_t) dei_datetime; | ||
72 | dei_map[0x9] = (uintptr_t) dei_mouse; | ||
465 | } | 73 | } |
466 | 74 | ||
467 | static Uxn u; | 75 | int |
468 | EWRAM_BSS | 76 | main(void) { |
469 | static u8 umem[KB(65)]; | ||
470 | |||
471 | int main(void) { | ||
472 | // Adjust system wait times. | 77 | // Adjust system wait times. |
473 | SYSTEM_WAIT = SYSTEM_WAIT_CARTRIDGE; | 78 | SYSTEM_WAIT = SYSTEM_WAIT_CARTRIDGE; |
474 | 79 | ||
@@ -479,34 +84,42 @@ int main(void) { | |||
479 | irq_init(); | 84 | irq_init(); |
480 | irs_set(IRQ_VBLANK, sound_vsync); | 85 | irs_set(IRQ_VBLANK, sound_vsync); |
481 | 86 | ||
482 | // Initialize VM. | 87 | // Initialize PPU. |
483 | dma_fill(&u, 0, sizeof(u), 3); | 88 | video_init(); |
484 | u.ram.dat = umem; | ||
485 | init_uxn(&u); | ||
486 | 89 | ||
487 | // Initialize text engine. | 90 | // Initialize text engine. |
91 | #if !defined(TEXT_DISABLE) || TEXT_DISABLE == 0 || PROF_ENABLE > 0 | ||
488 | txt_init(1, TEXT_LAYER); | 92 | txt_init(1, TEXT_LAYER); |
489 | txt_position(0,0); | 93 | txt_position(0,0); |
94 | #endif | ||
95 | |||
96 | // Initialize UXN. | ||
97 | init_uxn(); | ||
490 | 98 | ||
491 | // Initialize sound mixer. | 99 | // Enable sound. |
100 | #if !defined(SOUND_DISABLE) || SOUND_DISABLE == 0 | ||
492 | init_sound(); | 101 | init_sound(); |
102 | #endif | ||
493 | 103 | ||
494 | // Main loop. | 104 | // Main loop. |
495 | uxn_eval(&u, PAGE_PROGRAM); | ||
496 | PROF_INIT(); | ||
497 | u8 frame_counter = 0; | 105 | u8 frame_counter = 0; |
106 | PROF(uxn_eval_asm(PAGE_PROGRAM), eval_cycles); | ||
498 | while(true) { | 107 | while(true) { |
499 | bios_vblank_wait(); | 108 | bios_vblank_wait(); |
500 | PROF(handle_input(&u), input_cycles); | 109 | FRAME_START(); |
501 | PROF(uxn_eval(&u, mempeek16(devscreen->dat, 0)), eval_cycles); | 110 | PROF(handle_input(), input_cycles); |
111 | PROF(uxn_eval_asm(PEEK2(&device_data[0x20])), eval_cycles); | ||
112 | #if !defined(SOUND_DISABLE) || SOUND_DISABLE == 0 | ||
502 | PROF(sound_mix(), mix_cycles); | 113 | PROF(sound_mix(), mix_cycles); |
114 | #endif | ||
503 | PROF_SHOW(); | 115 | PROF_SHOW(); |
504 | PROF(flipbuf(&ppu), flip_cycles); | 116 | PROF(flipbuf(), flip_cycles); |
505 | frame_counter++; | 117 | frame_counter++; |
506 | if (frame_counter == 60) { | 118 | if (frame_counter == 60) { |
507 | seconds++; | 119 | seconds++; |
508 | frame_counter = 0; | 120 | frame_counter = 0; |
509 | } | 121 | } |
122 | FRAME_END(); | ||
510 | } | 123 | } |
511 | 124 | ||
512 | return 0; | 125 | return 0; |