aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c806
1 files changed, 438 insertions, 368 deletions
diff --git a/src/main.c b/src/main.c
index a2a43d4..21c8e0e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -15,7 +15,7 @@
15#include "common.h" 15#include "common.h"
16#include "filesystem.c" 16#include "filesystem.c"
17 17
18#include "uxn.c" 18#include "uxn.h"
19#include "ppu.c" 19#include "ppu.c"
20#include "apu.c" 20#include "apu.c"
21#include "file.c" 21#include "file.c"
@@ -37,6 +37,7 @@
37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD 37#define CONTROL_METHODS CONTROL_CONTROLLER,CONTROL_MOUSE,CONTROL_KEYBOARD
38#endif 38#endif
39 39
40#define PROF_ENABLE 0
40#ifndef PROF_ENABLE 41#ifndef PROF_ENABLE
41#define PROF_ENABLE 0 42#define PROF_ENABLE 0
42#endif 43#endif
@@ -214,130 +215,130 @@ typedef struct Mouse {
214} Mouse; 215} Mouse;
215 216
216EWRAM_BSS 217EWRAM_BSS
217static u8 umem[0x10300]; 218u8 uxn_ram[0x10300];
218 219
219static Uxn u; 220// static Uxn u;
220 221
221static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}; 222static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2};
222 223
223int 224// int
224uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) { 225// uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) {
225 (void)u; 226// (void)u;
226 txt_printf("HALTED\n"); 227// txt_printf("HALTED\n");
227 txt_printf("I: %lu\n", instr); 228// txt_printf("I: %lu\n", instr);
228 txt_printf("E: %lu\n", err); 229// txt_printf("E: %lu\n", err);
229 txt_printf("A: %lu\n", addr); 230// txt_printf("A: %lu\n", addr);
230 while (true); 231// while (true);
231} 232// }
232 233
233IWRAM_CODE 234IWRAM_CODE
234u8 235u8
235screen_dei(u8 *d, u8 port) { 236screen_dei(u8 *d, u8 port) {
236 switch(port) { 237 // switch(port) {
237 case 0x2: return (SCREEN_WIDTH >> 8); 238 // case 0x2: return (SCREEN_WIDTH >> 8);
238 case 0x3: return (SCREEN_WIDTH); 239 // case 0x3: return (SCREEN_WIDTH);
239 case 0x4: return (SCREEN_HEIGHT >> 8); 240 // case 0x4: return (SCREEN_HEIGHT >> 8);
240 case 0x5: return (SCREEN_HEIGHT); 241 // case 0x5: return (SCREEN_HEIGHT);
241 default: return d[port]; 242 // default: return d[port];
242 } 243 // }
243} 244}
244 245
245IWRAM_CODE 246IWRAM_CODE
246void 247void
247screen_deo(u8 *ram, u8 *d, u8 port) { 248screen_deo(u8 *ram, u8 *d, u8 port) {
248 switch(port) { 249 // switch(port) {
249 case 0xe: { 250 // case 0xe: {
250 u8 ctrl = d[0xe]; 251 // u8 ctrl = d[0xe];
251 u8 color = ctrl & 0x3; 252 // u8 color = ctrl & 0x3;
252 u16 x0 = PEEK2(d + 0x8); 253 // u16 x0 = PEEK2(d + 0x8);
253 u16 y0 = PEEK2(d + 0xa); 254 // u16 y0 = PEEK2(d + 0xa);
254 u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK; 255 // u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
255 if(ctrl & 0x80) { 256 // if(ctrl & 0x80) {
256 u16 x1 = SCREEN_WIDTH - 1; 257 // u16 x1 = SCREEN_WIDTH - 1;
257 u16 y1 = SCREEN_HEIGHT - 1; 258 // u16 y1 = SCREEN_HEIGHT - 1;
258 if(ctrl & 0x10) x1 = x0, x0 = 0; 259 // if(ctrl & 0x10) x1 = x0, x0 = 0;
259 if(ctrl & 0x20) y1 = y0, y0 = 0; 260 // if(ctrl & 0x20) y1 = y0, y0 = 0;
260 PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles); 261 // PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
261 } else { 262 // } else {
262 PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles); 263 // PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
263 if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */ 264 // if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */
264 if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */ 265 // if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */
265 } 266 // }
266 break; 267 // break;
267 } 268 // }
268 case 0xf: { 269 // case 0xf: {
269 u16 x, y, dx, dy, addr; 270 // u16 x, y, dx, dy, addr;
270 u8 n, twobpp = !!(d[0xf] & 0x80); 271 // u8 n, twobpp = !!(d[0xf] & 0x80);
271 x = PEEK2(d + 0x8); 272 // x = PEEK2(d + 0x8);
272 y = PEEK2(d + 0xa); 273 // y = PEEK2(d + 0xa);
273 addr = PEEK2(d + 0xc); 274 // addr = PEEK2(d + 0xc);
274 n = d[0x6] >> 4; 275 // n = d[0x6] >> 4;
275 dx = (d[0x6] & 0x01) << 3; 276 // dx = (d[0x6] & 0x01) << 3;
276 dy = (d[0x6] & 0x02) << 2; 277 // dy = (d[0x6] & 0x02) << 2;
277 if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) { 278 // if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
278 return; 279 // return;
279 } 280 // }
280 u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK; 281 // u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK;
281 u8 color = d[0xf] & 0xf; 282 // u8 color = d[0xf] & 0xf;
282 u8 flipx = d[0xf] & 0x10; 283 // u8 flipx = d[0xf] & 0x10;
283 u8 flipy = d[0xf] & 0x20; 284 // u8 flipy = d[0xf] & 0x20;
284 for(size_t i = 0; i <= n; i++) { 285 // for(size_t i = 0; i <= n; i++) {
285 u8 *sprite = &ram[addr]; 286 // u8 *sprite = &ram[addr];
286 if (twobpp) { 287 // if (twobpp) {
287 PROF(ppu_2bpp(layer, 288 // PROF(ppu_2bpp(layer,
288 x + dy * i, 289 // x + dy * i,
289 y + dx * i, 290 // y + dx * i,
290 sprite, 291 // sprite,
291 color, 292 // color,
292 flipx, flipy), ppu_chr_cycles); 293 // flipx, flipy), ppu_chr_cycles);
293 } else { 294 // } else {
294 PROF(ppu_1bpp(layer, 295 // PROF(ppu_1bpp(layer,
295 x + dy * i, 296 // x + dy * i,
296 y + dx * i, 297 // y + dx * i,
297 sprite, 298 // sprite,
298 color, 299 // color,
299 flipx, flipy), ppu_icn_cycles); 300 // flipx, flipy), ppu_icn_cycles);
300 } 301 // }
301 addr += (d[0x6] & 0x04) << (1 + twobpp); 302 // addr += (d[0x6] & 0x04) << (1 + twobpp);
302 } 303 // }
303 POKE2(d + 0xc, addr); /* auto addr+length */ 304 // POKE2(d + 0xc, addr); /* auto addr+length */
304 POKE2(d + 0x8, x + dx); /* auto x+8 */ 305 // POKE2(d + 0x8, x + dx); /* auto x+8 */
305 POKE2(d + 0xa, y + dy); /* auto y+8 */ 306 // POKE2(d + 0xa, y + dy); /* auto y+8 */
306 break; 307 // break;
307 } 308 // }
308 } 309 // }
309} 310}
310 311
311u8 312u8
312audio_dei(int instance, u8 *d, u8 port) { 313audio_dei(int instance, u8 *d, u8 port) {
313 AudioChannel *c = &channels[instance]; 314 // AudioChannel *c = &channels[instance];
314 switch(port) { 315 // switch(port) {
315 // case 0x4: return apu_get_vu(instance); 316 // // case 0x4: return apu_get_vu(instance);
316 case 0x2: { 317 // case 0x2: {
317 POKE2(d + 0x2, c->pos); 318 // POKE2(d + 0x2, c->pos);
318 c->pos <<= 12; // fixed point. 319 // c->pos <<= 12; // fixed point.
319 break; 320 // break;
320 } 321 // }
321 } 322 // }
322 return d[port]; 323 return d[port];
323} 324}
324 325
325void 326void
326audio_deo(int instance, u8 *d, u8 port, Uxn *u) { 327audio_deo(int instance, u8 *d, u8 port, Uxn *u) {
327 AudioChannel *c = &channels[instance]; 328 // AudioChannel *c = &channels[instance];
328 if (port == 0xf) { 329 // if (port == 0xf) {
329 u16 length = 0; 330 // u16 length = 0;
330 u16 adsr = 0; 331 // u16 adsr = 0;
331 u16 addr = 0; 332 // u16 addr = 0;
332 u8 pitch = d[0xf] & 0x7f; 333 // u8 pitch = d[0xf] & 0x7f;
333 adsr = PEEK2(d + 0x8); 334 // adsr = PEEK2(d + 0x8);
334 length = PEEK2(d + 0xa); 335 // length = PEEK2(d + 0xa);
335 addr = PEEK2(d + 0xc); 336 // addr = PEEK2(d + 0xc);
336 u8 *data = &u->ram[addr]; 337 // u8 *data = &u->ram[addr];
337 u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3; 338 // u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3;
338 bool loop = !(d[0xf] & 0x80); 339 // bool loop = !(d[0xf] & 0x80);
339 update_channel(c, data, length, pitch, adsr, vol, loop); 340 // update_channel(c, data, length, pitch, adsr, vol, loop);
340 } 341 // }
341} 342}
342 343
343u8 344u8
@@ -361,75 +362,75 @@ datetime_dei(u8 *d, u8 port) {
361 362
362u8 363u8
363file_dei(u8 id, u8 *d, u8 port) { 364file_dei(u8 id, u8 *d, u8 port) {
364 UxnFile *c = &uxn_file[id]; 365 // UxnFile *c = &uxn_file[id];
365 u16 res; 366 // u16 res;
366 switch(port) { 367 // switch(port) {
367 case 0xc: 368 // case 0xc:
368 case 0xd: { 369 // case 0xd: {
369 res = file_read(c, &d[port], 1); 370 // res = file_read(c, &d[port], 1);
370 POKE2(d + 0x2, res); 371 // POKE2(d + 0x2, res);
371 break; 372 // break;
372 } 373 // }
373 } 374 // }
374 return d[port]; 375 return d[port];
375} 376}
376 377
377void 378void
378file_deo(u8 id, u8 *ram, u8 *d, u8 port) { 379file_deo(u8 id, u8 *ram, u8 *d, u8 port) {
379 u16 a, b, res; 380 // u16 a, b, res;
380 UxnFile *f = &uxn_file[id]; 381 // UxnFile *f = &uxn_file[id];
381 switch(port) { 382 // switch(port) {
382 case 0x5: { 383 // case 0x5: {
383 a = PEEK2(d + 0x4); 384 // a = PEEK2(d + 0x4);
384 b = PEEK2(d + 0xa); 385 // b = PEEK2(d + 0xa);
385 if(b > 0x10000 - a) { 386 // if(b > 0x10000 - a) {
386 b = 0x10000 - a; 387 // b = 0x10000 - a;
387 } 388 // }
388 res = file_stat(f, &ram[a], b); 389 // res = file_stat(f, &ram[a], b);
389 POKE2(d + 0x2, res); 390 // POKE2(d + 0x2, res);
390 } break; 391 // } break;
391 case 0x6: { 392 // case 0x6: {
392 // TODO: no file deletion for now 393 // // TODO: no file deletion for now
393 // res = file_delete(); 394 // // res = file_delete();
394 // POKE2(d + 0x2, res); 395 // // POKE2(d + 0x2, res);
395 } break; 396 // } break;
396 case 0x9: { 397 // case 0x9: {
397 a = PEEK2(d + 0x8); 398 // a = PEEK2(d + 0x8);
398 res = file_init(f, &ram[a]); 399 // res = file_init(f, &ram[a]);
399 POKE2(d + 0x2, res); 400 // POKE2(d + 0x2, res);
400 } break; 401 // } break;
401 case 0xd: { 402 // case 0xd: {
402 a = PEEK2(d + 0xc); 403 // a = PEEK2(d + 0xc);
403 b = PEEK2(d + 0xa); 404 // b = PEEK2(d + 0xa);
404 if(b > 0x10000 - a) { 405 // if(b > 0x10000 - a) {
405 b = 0x10000 - a; 406 // b = 0x10000 - a;
406 } 407 // }
407 res = file_read(f, &ram[a], b); 408 // res = file_read(f, &ram[a], b);
408 POKE2(d + 0x2, res); 409 // POKE2(d + 0x2, res);
409 } break; 410 // } break;
410 case 0xf: { 411 // case 0xf: {
411 a = PEEK2(d + 0xe); 412 // a = PEEK2(d + 0xe);
412 b = PEEK2(d + 0xa); 413 // b = PEEK2(d + 0xa);
413 if(b > 0x10000 - a) { 414 // if(b > 0x10000 - a) {
414 b = 0x10000 - a; 415 // b = 0x10000 - a;
415 } 416 // }
416 res = file_write(f, &ram[a], b, d[0x7]); 417 // res = file_write(f, &ram[a], b, d[0x7]);
417 POKE2(d + 0x2, res); 418 // POKE2(d + 0x2, res);
418 } break; 419 // } break;
419 } 420 // }
420} 421}
421 422
422void 423void
423console_deo(u8 *d, u8 port) { 424console_deo(u8 *d, u8 port) {
424 switch(port) { 425 // switch(port) {
425 case 0x8: 426 // case 0x8:
426 txt_putc(d[port]); 427 // txt_putc(d[port]);
427 return; 428 // return;
428 case 0x9: 429 // case 0x9:
429 txt_printf("ERROR: %c"); 430 // txt_printf("ERROR: %c");
430 txt_putc(d[port]); 431 // txt_putc(d[port]);
431 return; 432 // return;
432 } 433 // }
433} 434}
434 435
435#define RAM_PAGES 0x10 436#define RAM_PAGES 0x10
@@ -464,11 +465,11 @@ system_cmd(u8 *ram, u16 addr) {
464 465
465void 466void
466system_deo(Uxn *u, u8 *d, u8 port) { 467system_deo(Uxn *u, u8 *d, u8 port) {
467 switch(port) { 468 // switch(port) {
468 case 0x3: { 469 // case 0x3: {
469 system_cmd(u->ram, PEEK2(d + 2)); 470 // system_cmd(u->ram, PEEK2(d + 2));
470 } break; 471 // } break;
471 } 472 // }
472} 473}
473 474
474u8 475u8
@@ -509,201 +510,221 @@ uxn_deo(Uxn *u, u8 addr) {
509} 510}
510 511
511void 512void
512init_uxn(Uxn *u) { 513init_uxn() {
513 // Initialize uxn. 514 // Initialize uxn.
514 u32 fill = 0; 515 u32 fill = 0;
515 dma_fill(umem, fill, 0x10300, 3); 516 dma_fill(uxn_ram, fill, 0x10300, 3);
516 uxn_boot(u, umem, uxn_dei, uxn_deo); 517 // uxn_boot(u, uxn_ram, uxn_dei, uxn_deo);
517 518
518 // Copy rom to VM. 519 // Copy rom to VM.
519 memcpy(u->ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); 520 u8 uxn_rom[] = {
521 // Hello world (h)
522 // 0x80, 0x68, 0x80, 0x18, 0x17,
523 //
524 // ADD test
525 0x80, 0x04, 0x80, 0x03, 0x80, 0x02, 0x80, 0x01, 0x18
526 };
527 memcpy(uxn_ram + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom));
520} 528}
521 529
522IWRAM_CODE 530IWRAM_CODE
523void 531void
524handle_input(Uxn *u) { 532handle_input(Uxn *u) {
525 poll_keys(); 533 // poll_keys();
526 if (key_tap(KEY_SELECT)) { 534 // if (key_tap(KEY_SELECT)) {
527 // Reset control variables on method switch. 535 // // Reset control variables on method switch.
528 switch (ctrl_methods[ctrl_idx]) { 536 // switch (ctrl_methods[ctrl_idx]) {
529 case CONTROL_CONTROLLER: { 537 // case CONTROL_CONTROLLER: {
530 u8 *d = &u->dev[0x80]; 538 // u8 *d = &u->dev[0x80];
531 d[2] = 0; 539 // d[2] = 0;
532 uxn_eval(u, PEEK2(d)); 540 // uxn_eval(u, PEEK2(d));
533 d[3] = 0; 541 // d[3] = 0;
534 } break; 542 // } break;
535 case CONTROL_MOUSE: { 543 // case CONTROL_MOUSE: {
536 u8 *d = &u->dev[0x90]; 544 // u8 *d = &u->dev[0x90];
537 d[6] = 0; 545 // d[6] = 0;
538 d[7] = 0; 546 // d[7] = 0;
539 POKE2(d + 0x2, -10); 547 // POKE2(d + 0x2, -10);
540 POKE2(d + 0x4, -10); 548 // POKE2(d + 0x4, -10);
541 uxn_eval(u, PEEK2(d)); 549 // uxn_eval(u, PEEK2(d));
542 } break; 550 // } break;
543 case CONTROL_KEYBOARD: { 551 // case CONTROL_KEYBOARD: {
544 toggle_keyboard(); 552 // toggle_keyboard();
545 } break; 553 // } break;
546 } 554 // }
547 555
548 // Update ctrl_idx. 556 // // Update ctrl_idx.
549 ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1; 557 // ctrl_idx = (ctrl_idx + 1 > (int)LEN(ctrl_methods) - 1) ? 0 : ctrl_idx + 1;
550 558
551 // Initialize controller variables here. 559 // // Initialize controller variables here.
552 if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) { 560 // if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
553 toggle_keyboard(); 561 // toggle_keyboard();
554 } 562 // }
555 } 563 // }
556 564
557 if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) { 565 // if (ctrl_methods[ctrl_idx] == CONTROL_CONTROLLER) {
558 u8 *d = &u->dev[0x80]; 566 // u8 *d = &u->dev[0x80];
559 // TODO: We don't need ifs if we use KEY_INPUTS directly and maybe just 567 // // TODO: We don't need ifs if we use KEY_INPUTS directly and maybe just
560 // swap some things if needed. 568 // // swap some things if needed.
561 u8 *flag = &d[2]; 569 // u8 *flag = &d[2];
562 if (key_tap(KEY_A)) { 570 // if (key_tap(KEY_A)) {
563 *flag |= 0x01; 571 // *flag |= 0x01;
564 } else { 572 // } else {
565 *flag &= ~0x01; 573 // *flag &= ~0x01;
566 } 574 // }
567 if (key_tap(KEY_B)) { 575 // if (key_tap(KEY_B)) {
568 *flag |= 0x02; 576 // *flag |= 0x02;
569 } else { 577 // } else {
570 *flag &= ~0x02; 578 // *flag &= ~0x02;
571 } 579 // }
572 if (key_tap(KEY_L)) { 580 // if (key_tap(KEY_L)) {
573 *flag |= 0x04; 581 // *flag |= 0x04;
574 } else { 582 // } else {
575 *flag &= ~0x04; 583 // *flag &= ~0x04;
576 } 584 // }
577 if (key_tap(KEY_R)) { 585 // if (key_tap(KEY_R)) {
578 *flag |= 0x08; 586 // *flag |= 0x08;
579 } else { 587 // } else {
580 *flag &= ~0x08; 588 // *flag &= ~0x08;
581 } 589 // }
582 if (key_tap(KEY_UP)) { 590 // if (key_tap(KEY_UP)) {
583 *flag |= 0x10; 591 // *flag |= 0x10;
584 } else { 592 // } else {
585 *flag &= ~0x10; 593 // *flag &= ~0x10;
586 } 594 // }
587 if (key_tap(KEY_DOWN)) { 595 // if (key_tap(KEY_DOWN)) {
588 *flag |= 0x20; 596 // *flag |= 0x20;
589 } else { 597 // } else {
590 *flag &= ~0x20; 598 // *flag &= ~0x20;
591 } 599 // }
592 if (key_tap(KEY_LEFT)) { 600 // if (key_tap(KEY_LEFT)) {
593 *flag |= 0x40; 601 // *flag |= 0x40;
594 } else { 602 // } else {
595 *flag &= ~0x40; 603 // *flag &= ~0x40;
596 } 604 // }
597 if (key_tap(KEY_RIGHT)) { 605 // if (key_tap(KEY_RIGHT)) {
598 *flag |= 0x80; 606 // *flag |= 0x80;
599 } else { 607 // } else {
600 *flag &= ~0x80; 608 // *flag &= ~0x80;
601 } 609 // }
602 610
603 if (key_prev != key_curr) { 611 // if (key_prev != key_curr) {
604 uxn_eval(u, PEEK2(d)); 612 // uxn_eval(u, PEEK2(d));
605 } 613 // }
606 d[3] = 0; 614 // d[3] = 0;
607 } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) { 615 // } else if (ctrl_methods[ctrl_idx] == CONTROL_MOUSE) {
608 u8 *d = &u->dev[0x90]; 616 // u8 *d = &u->dev[0x90];
609 // Detect "mouse key press". 617 // // Detect "mouse key press".
610 u8 flag = d[6]; 618 // u8 flag = d[6];
611 bool event = false; 619 // bool event = false;
612 if (key_tap(KEY_B)) { 620 // if (key_tap(KEY_B)) {
613 event = true; 621 // event = true;
614 flag |= 0x01; 622 // flag |= 0x01;
615 } else if (key_released(KEY_B)) { 623 // } else if (key_released(KEY_B)) {
616 event = true; 624 // event = true;
617 flag &= ~0x01; 625 // flag &= ~0x01;
618 } 626 // }
619 if (key_tap(KEY_A)) { 627 // if (key_tap(KEY_A)) {
620 event = true; 628 // event = true;
621 flag |= 0x10; 629 // flag |= 0x10;
622 } else if (key_released(KEY_A)) { 630 // } else if (key_released(KEY_A)) {
623 event = true; 631 // event = true;
624 flag &= ~0x10; 632 // flag &= ~0x10;
625 } 633 // }
634
635 // // Handle chording.
636 // d[6] = flag;
637 // if(flag == 0x10 && (d[6] & 0x01)) {
638 // d[7] = 0x01;
639 // }
640 // if(flag == 0x01 && (d[6] & 0x10)) {
641 // d[7] = 0x10;
642 // }
643
644 // // Detect mouse movement.
645 // if (key_pressed(KEY_UP)) {
646 // event = true;
647 // mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
648 // } else if (key_pressed(KEY_DOWN)) {
649 // event = true;
650 // mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8);
651 // }
652 // if (key_pressed(KEY_LEFT)) {
653 // event = true;
654 // mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
655 // } else if (key_pressed(KEY_RIGHT)) {
656 // event = true;
657 // mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
658 // }
659
660 // // Eval mouse.
661 // POKE2(d + 0x2, mouse.x);
662 // POKE2(d + 0x4, mouse.y);
663 // if (event) {
664 // uxn_eval(u, PEEK2(d));
665 // }
666 // } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
667 // u8 *d = &u->dev[0x80];
668 // if (key_tap(KEY_LEFT)) {
669 // update_cursor(cursor_position - 1);
670 // } else if (key_tap(KEY_RIGHT)) {
671 // update_cursor(cursor_position + 1);
672 // }
673 // if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
674 // update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
675 // } else if (key_tap(KEY_DOWN)
676 // && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
677 // update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
678 // }
679 // if (key_tap(KEY_B)) {
680 // u8 symbol = keyboard[cursor_position].symbol;
681 // switch (symbol) {
682 // case 0x7f: {
683 // // Backspace.
684 // d[3] = 0x08;
685 // } break;
686 // case 0x14: {
687 // // New line.
688 // d[3] = 0x0d;
689 // } break;
690 // case 0x18: {
691 // // Arrow up.
692 // d[2] = 0x10;
693 // } break;
694 // case 0x19: {
695 // // Arrow down.
696 // d[2] = 0x20;
697 // } break;
698 // case 0x1b: {
699 // // Arrow left.
700 // d[2] = 0x40;
701 // } break;
702 // case 0x1a: {
703 // // Arrow right.
704 // d[2] = 0x80;
705 // } break;
706 // default: {
707 // d[3] = symbol;
708 // } break;
709 // }
710 // uxn_eval(u, PEEK2(d));
711 // d[3] = 0;
712 // }
713 // }
714}
626 715
627 // Handle chording. 716#define STACK_SIZE 16
628 d[6] = flag; 717u8 stack[STACK_SIZE] = {0};
629 if(flag == 0x10 && (d[6] & 0x01)) { 718extern void uxn_init_asm(void);
630 d[7] = 0x01; 719extern void uxn_eval_asm(u16 pc);
631 }
632 if(flag == 0x01 && (d[6] & 0x10)) {
633 d[7] = 0x10;
634 }
635 720
636 // Detect mouse movement. 721// TODO: This should be on the IWRAM for maximum speed, as these are operations
637 if (key_pressed(KEY_UP)) { 722// we will use very often.
638 event = true; 723extern u8 wst[256];
639 mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); 724extern u8 rst[256];
640 } else if (key_pressed(KEY_DOWN)) { 725extern u8 io_ports[256];
641 event = true; 726extern uintptr_t wst_ptr;
642 mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); 727extern uintptr_t rst_ptr;
643 }
644 if (key_pressed(KEY_LEFT)) {
645 event = true;
646 mouse.x = CLAMP(mouse.x - MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
647 } else if (key_pressed(KEY_RIGHT)) {
648 event = true;
649 mouse.x = CLAMP(mouse.x + MOUSE_DELTA, 0, SCREEN_WIDTH - 8);
650 }
651
652 // Eval mouse.
653 POKE2(d + 0x2, mouse.x);
654 POKE2(d + 0x4, mouse.y);
655 if (event) {
656 uxn_eval(u, PEEK2(d));
657 }
658 } else if (ctrl_methods[ctrl_idx] == CONTROL_KEYBOARD) {
659 u8 *d = &u->dev[0x80];
660 if (key_tap(KEY_LEFT)) {
661 update_cursor(cursor_position - 1);
662 } else if (key_tap(KEY_RIGHT)) {
663 update_cursor(cursor_position + 1);
664 }
665 if (key_tap(KEY_UP) && cursor_position >= KEYBOARD_ROW_SIZE) {
666 update_cursor(cursor_position - KEYBOARD_ROW_SIZE);
667 } else if (key_tap(KEY_DOWN)
668 && cursor_position < LEN(keyboard) - KEYBOARD_ROW_SIZE) {
669 update_cursor(cursor_position + KEYBOARD_ROW_SIZE);
670 }
671 if (key_tap(KEY_B)) {
672 u8 symbol = keyboard[cursor_position].symbol;
673 switch (symbol) {
674 case 0x7f: {
675 // Backspace.
676 d[3] = 0x08;
677 } break;
678 case 0x14: {
679 // New line.
680 d[3] = 0x0d;
681 } break;
682 case 0x18: {
683 // Arrow up.
684 d[2] = 0x10;
685 } break;
686 case 0x19: {
687 // Arrow down.
688 d[2] = 0x20;
689 } break;
690 case 0x1b: {
691 // Arrow left.
692 d[2] = 0x40;
693 } break;
694 case 0x1a: {
695 // Arrow right.
696 d[2] = 0x80;
697 } break;
698 default: {
699 d[3] = symbol;
700 } break;
701 }
702 uxn_eval(u, PEEK2(d));
703 d[3] = 0;
704 }
705 }
706}
707 728
708int 729int
709main(void) { 730main(void) {
@@ -721,38 +742,87 @@ main(void) {
721 video_init(); 742 video_init();
722 743
723 // Initialize text engine. 744 // Initialize text engine.
724#ifdef TEXT_ENABLE 745// #ifdef TEXT_ENABLE
725 txt_init(1, TEXT_LAYER); 746 txt_init(1, TEXT_LAYER);
726 txt_position(0,0); 747 txt_position(0,0);
727#endif 748// #endif
728 749
729 // Initialize UXN. 750 // Initialize UXN.
730 init_uxn(&u); 751 init_uxn();
731 752
732 // Enable sound. 753 // Enable sound.
733 init_sound(); 754 init_sound();
734 755
735 // Main loop. 756 // Main loop.
736 uxn_eval(&u, PAGE_PROGRAM); 757 // uxn_eval(&u, PAGE_PROGRAM);
737 u8 frame_counter = 0; 758 u8 frame_counter = 0;
738 // NOTE: A VBLANK is 83776 cycles, anything other than that will make it so 759 // NOTE: A VBLANK is 83776 cycles, anything other than that will make it so
739 // we fail to render at 60FPS. 760 // we fail to render at 60FPS.
761
762 // TODO: Initialize memory.
763 // Initialize stack.
764 for (size_t i = 0; i < 256; i++) {
765 wst[i] = 0;
766 rst[i] = 0;
767 io_ports[i] = 0;
768 }
769 uxn_init_asm();
770
771 txt_printf("ROM\n\n");
772 for (size_t i = 0; i < 8; i++) {
773 txt_printf("%02x ", uxn_ram[i + PAGE_PROGRAM]);
774 }
775 txt_printf("\n\n");
776
777 txt_printf("STACK (BEFORE)\n");
778 txt_printf("PTR: %d\n", wst_ptr - (uintptr_t)wst);
779 for (size_t i = 0; i < STACK_SIZE; i++) {
780 if (i % 4 == 0) {
781 txt_printf("\n");
782 }
783 txt_printf("%02x ", wst[i]);
784 }
785 txt_printf("\n\n");
786
787 uxn_eval_asm(PAGE_PROGRAM);
788 txt_printf("STACK (AFTER)\n");
789 txt_printf("PTR: %d\n", wst_ptr - (uintptr_t)wst);
790 for (size_t i = 0; i < STACK_SIZE; i++) {
791 if (i % 4 == 0) {
792 txt_printf("\n");
793 }
794 txt_printf("%02x ", wst[i]);
795 }
796
797 uintptr_t stack_base = wst;
798 uintptr_t stack_size = wst_ptr - stack_base;
740 while(true) { 799 while(true) {
800 txt_position(0,0);
801 // bios_vblank_wait();
802 // FRAME_START();
803 // // PROF(handle_input(&u), input_cycles);
804 // // PROF(uxn_eval(&u, PEEK2(&u.dev[0x20])), eval_cycles);
805 // // PROF(sound_mix(), mix_cycles);
806 // // // TODO: allow configuration to do VSYNC at 15 or 30 fps to avoid too
807 // // // much memory copying on demanding uxn roms.
808 // // PROF_SHOW();
809 // // PROF(flipbuf(), flip_cycles);
810 // // frame_counter++;
811 // // if (frame_counter == 60) {
812 // // seconds++;
813 // // frame_counter = 0;
814 // // }
815 // FRAME_END();
741 bios_vblank_wait(); 816 bios_vblank_wait();
742 FRAME_START(); 817 FRAME_START();
743 PROF(handle_input(&u), input_cycles); 818 flipbuf();
744 PROF(uxn_eval(&u, PEEK2(&u.dev[0x20])), eval_cycles); 819 // screen_fill(0);
745 PROF(sound_mix(), mix_cycles); 820 // txt_printf("WST: 0x%08x\n", wst);
746 // TODO: allow configuration to do VSYNC at 15 or 30 fps to avoid too 821 // txt_printf("PTR: 0x%08x\n", wst_ptr);
747 // much memory copying on demanding uxn roms.
748 PROF_SHOW();
749 PROF(flipbuf(), flip_cycles);
750 frame_counter++;
751 if (frame_counter == 60) {
752 seconds++;
753 frame_counter = 0;
754 }
755 FRAME_END(); 822 FRAME_END();
823 PROF_SHOW();
824 // txt_render();
825 // txt_clear();
756 } 826 }
757 827
758 return 0; 828 return 0;