diff options
author | Bad Diode <bd@badd10de.dev> | 2023-08-27 19:47:34 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-08-27 19:47:34 +0200 |
commit | 9fc5ff0b00e1ca72c75721d3bdc4ff2287b48fc2 (patch) | |
tree | dfb87fde586d011f4a46d23e590c6423c80b8317 | |
parent | 4305d585d87c6bbc197b0fe2d9f144d6d0b772e2 (diff) | |
download | uxngba-9fc5ff0b00e1ca72c75721d3bdc4ff2287b48fc2.tar.gz uxngba-9fc5ff0b00e1ca72c75721d3bdc4ff2287b48fc2.zip |
Testing barebones uxn_eval implementation in ASM
-rw-r--r-- | src/main.c | 806 | ||||
-rw-r--r-- | src/uxn-core.s | 567 |
2 files changed, 1005 insertions, 368 deletions
@@ -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 | ||
216 | EWRAM_BSS | 217 | EWRAM_BSS |
217 | static u8 umem[0x10300]; | 218 | u8 uxn_ram[0x10300]; |
218 | 219 | ||
219 | static Uxn u; | 220 | // static Uxn u; |
220 | 221 | ||
221 | static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}; | 222 | static Mouse mouse = {SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2}; |
222 | 223 | ||
223 | int | 224 | // int |
224 | uxn_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 | ||
233 | IWRAM_CODE | 234 | IWRAM_CODE |
234 | u8 | 235 | u8 |
235 | screen_dei(u8 *d, u8 port) { | 236 | screen_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 | ||
245 | IWRAM_CODE | 246 | IWRAM_CODE |
246 | void | 247 | void |
247 | screen_deo(u8 *ram, u8 *d, u8 port) { | 248 | screen_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 | ||
311 | u8 | 312 | u8 |
312 | audio_dei(int instance, u8 *d, u8 port) { | 313 | audio_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 | ||
325 | void | 326 | void |
326 | audio_deo(int instance, u8 *d, u8 port, Uxn *u) { | 327 | audio_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 | ||
343 | u8 | 344 | u8 |
@@ -361,75 +362,75 @@ datetime_dei(u8 *d, u8 port) { | |||
361 | 362 | ||
362 | u8 | 363 | u8 |
363 | file_dei(u8 id, u8 *d, u8 port) { | 364 | file_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 | ||
377 | void | 378 | void |
378 | file_deo(u8 id, u8 *ram, u8 *d, u8 port) { | 379 | file_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 | ||
422 | void | 423 | void |
423 | console_deo(u8 *d, u8 port) { | 424 | console_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 | ||
465 | void | 466 | void |
466 | system_deo(Uxn *u, u8 *d, u8 port) { | 467 | system_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 | ||
474 | u8 | 475 | u8 |
@@ -509,201 +510,221 @@ uxn_deo(Uxn *u, u8 addr) { | |||
509 | } | 510 | } |
510 | 511 | ||
511 | void | 512 | void |
512 | init_uxn(Uxn *u) { | 513 | init_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 | ||
522 | IWRAM_CODE | 530 | IWRAM_CODE |
523 | void | 531 | void |
524 | handle_input(Uxn *u) { | 532 | handle_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; | 717 | u8 stack[STACK_SIZE] = {0}; |
629 | if(flag == 0x10 && (d[6] & 0x01)) { | 718 | extern void uxn_init_asm(void); |
630 | d[7] = 0x01; | 719 | extern 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; | 723 | extern u8 wst[256]; |
639 | mouse.y = CLAMP(mouse.y - MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); | 724 | extern u8 rst[256]; |
640 | } else if (key_pressed(KEY_DOWN)) { | 725 | extern u8 io_ports[256]; |
641 | event = true; | 726 | extern uintptr_t wst_ptr; |
642 | mouse.y = CLAMP(mouse.y + MOUSE_DELTA, 0, SCREEN_HEIGHT - 8); | 727 | extern 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 | ||
708 | int | 729 | int |
709 | main(void) { | 730 | main(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; |
diff --git a/src/uxn-core.s b/src/uxn-core.s new file mode 100644 index 0000000..2e7a165 --- /dev/null +++ b/src/uxn-core.s | |||
@@ -0,0 +1,567 @@ | |||
1 | .file "uxn-core.s" | ||
2 | .section .iwram, "ax", %progbits | ||
3 | .extern uxn_ram | ||
4 | .align | ||
5 | |||
6 | @ | ||
7 | @ Core variables | ||
8 | @ | ||
9 | |||
10 | .global wst | ||
11 | wst: .space 256 | ||
12 | .global wst_ptr | ||
13 | wst_ptr: .word wst | ||
14 | |||
15 | .global rst | ||
16 | rst: .space 256 | ||
17 | .global rst_ptr | ||
18 | rst_ptr: .word rst | ||
19 | |||
20 | .global io_ports | ||
21 | io_ports: .space 256 | ||
22 | |||
23 | @ | ||
24 | @ r0 is our custom stack pointer | ||
25 | @ r1 is the value we want to insert/extract | ||
26 | @ | ||
27 | @ When the stack grows downwards: | ||
28 | @ push {r1} == str r1, [sp, #-4]! | ||
29 | @ pop {r1} == ldr r1, [sp], #4 | ||
30 | @ | ||
31 | @ In our case the stack grow upwards: | ||
32 | @ | ||
33 | @ 8bit: | ||
34 | @ push {r1} == strb r1, [sp], #1 | ||
35 | @ pop {r1} == ldrb r1, [sp, #-1]! | ||
36 | @ | ||
37 | @ 32bit: | ||
38 | @ push {r1} == str r1, [sp], #4 | ||
39 | @ pop {r1} == ldr r1, [sp, #-4]! | ||
40 | @ | ||
41 | |||
42 | .global uxn_init_asm | ||
43 | uxn_init_asm: | ||
44 | @ DEBUG: Initialize the stack for testing purposes. | ||
45 | ldr r0, wst_ptr | ||
46 | mov r1, #4 | ||
47 | strb r1, [r0], #1 | ||
48 | sub r1, r1, #1 | ||
49 | strb r1, [r0], #1 | ||
50 | sub r1, r1, #1 | ||
51 | strb r1, [r0], #1 | ||
52 | sub r1, r1, #1 | ||
53 | strb r1, [r0], #1 | ||
54 | adr r1, wst_ptr | ||
55 | str r0, [r1] | ||
56 | bx lr | ||
57 | |||
58 | @ UXN evaluation function. | ||
59 | @ | ||
60 | @ r0: PC pointer (argument is offset from RAM). | ||
61 | @ r1: Stack pointer (wst/rst). | ||
62 | @ r2: Ram ptr. | ||
63 | @ r3-r7: Scratch registers. | ||
64 | .global uxn_eval_asm | ||
65 | uxn_eval_asm: | ||
66 | @ Initialization. | ||
67 | push {r4-r7} | ||
68 | ldr r1, wst_ptr | ||
69 | ldr r2, =uxn_ram | ||
70 | add r0, r0, r2 | ||
71 | |||
72 | uxn_decode: | ||
73 | ldrb r3, [r0], #1 @ current OP value / table index | ||
74 | |||
75 | @ TODO: Setup wst/rst? or fill operations accordingly? | ||
76 | @ str r3, [r1], #1 @ Push to stack: Debugging | ||
77 | |||
78 | @ Decode OP based on table lookup. | ||
79 | adr r4, op_table @ decoding table | ||
80 | ldr r4, [r4, r3, lsl #2] @ op_table[idx * 4] | ||
81 | bx r4 @ op_table[idx * 4]() | ||
82 | |||
83 | uxn_ret: | ||
84 | @ Update stack pointer and return. | ||
85 | adr r0, wst_ptr | ||
86 | str r1, [r0] | ||
87 | pop {r4-r7} | ||
88 | bx lr | ||
89 | |||
90 | @ | ||
91 | @ OP implementations. | ||
92 | @ | ||
93 | |||
94 | brk: | ||
95 | b uxn_ret | ||
96 | |||
97 | jci: | ||
98 | b uxn_ret | ||
99 | |||
100 | jmi: | ||
101 | b uxn_ret | ||
102 | |||
103 | jsi: | ||
104 | b uxn_ret | ||
105 | |||
106 | litr: | ||
107 | ldrb r3, [r0], #1 | ||
108 | strb r3, [r1], #1 | ||
109 | b uxn_decode | ||
110 | |||
111 | lit2r: | ||
112 | b uxn_ret | ||
113 | |||
114 | inc: | ||
115 | b uxn_ret | ||
116 | |||
117 | inc2: | ||
118 | b uxn_ret | ||
119 | |||
120 | pop: | ||
121 | b uxn_ret | ||
122 | |||
123 | pop2: | ||
124 | b uxn_ret | ||
125 | |||
126 | nip: | ||
127 | b uxn_ret | ||
128 | |||
129 | nip2: | ||
130 | b uxn_ret | ||
131 | |||
132 | swp: | ||
133 | b uxn_ret | ||
134 | |||
135 | swp2: | ||
136 | b uxn_ret | ||
137 | |||
138 | rot: | ||
139 | b uxn_ret | ||
140 | |||
141 | rot2: | ||
142 | b uxn_ret | ||
143 | |||
144 | dup: | ||
145 | b uxn_ret | ||
146 | |||
147 | dup2: | ||
148 | b uxn_ret | ||
149 | |||
150 | ovr: | ||
151 | b uxn_ret | ||
152 | |||
153 | ovr2: | ||
154 | b uxn_ret | ||
155 | |||
156 | equ: | ||
157 | b uxn_ret | ||
158 | |||
159 | equ2: | ||
160 | b uxn_ret | ||
161 | |||
162 | neq: | ||
163 | b uxn_ret | ||
164 | |||
165 | neq2: | ||
166 | b uxn_ret | ||
167 | |||
168 | gth: | ||
169 | b uxn_ret | ||
170 | |||
171 | gth2: | ||
172 | b uxn_ret | ||
173 | |||
174 | lth: | ||
175 | b uxn_ret | ||
176 | |||
177 | lth2: | ||
178 | b uxn_ret | ||
179 | |||
180 | jmp: | ||
181 | b uxn_ret | ||
182 | |||
183 | jmp2: | ||
184 | b uxn_ret | ||
185 | |||
186 | jcn: | ||
187 | b uxn_ret | ||
188 | |||
189 | jcn2: | ||
190 | b uxn_ret | ||
191 | |||
192 | jsr: | ||
193 | b uxn_ret | ||
194 | |||
195 | jsr2: | ||
196 | b uxn_ret | ||
197 | |||
198 | sth: | ||
199 | b uxn_ret | ||
200 | |||
201 | sth2: | ||
202 | b uxn_ret | ||
203 | |||
204 | ldz: | ||
205 | b uxn_ret | ||
206 | |||
207 | ldz2: | ||
208 | b uxn_ret | ||
209 | |||
210 | stz: | ||
211 | b uxn_ret | ||
212 | |||
213 | stz2: | ||
214 | b uxn_ret | ||
215 | |||
216 | ldr: | ||
217 | b uxn_ret | ||
218 | |||
219 | ldr2: | ||
220 | b uxn_ret | ||
221 | |||
222 | str: | ||
223 | b uxn_ret | ||
224 | |||
225 | str2: | ||
226 | b uxn_ret | ||
227 | |||
228 | lda: | ||
229 | b uxn_ret | ||
230 | |||
231 | lda2: | ||
232 | b uxn_ret | ||
233 | |||
234 | sta: | ||
235 | b uxn_ret | ||
236 | |||
237 | sta2: | ||
238 | b uxn_ret | ||
239 | |||
240 | dei: | ||
241 | b uxn_ret | ||
242 | |||
243 | dei2: | ||
244 | b uxn_ret | ||
245 | |||
246 | deo: | ||
247 | b uxn_ret | ||
248 | |||
249 | deo2: | ||
250 | b uxn_ret | ||
251 | |||
252 | add: | ||
253 | ldr r3, [r1, #-1]! | ||
254 | ldr r4, [r1, #-1]! | ||
255 | add r3, r3, r4 | ||
256 | strb r3, [r1], #1 | ||
257 | b uxn_ret @ NOTE: This should return to the next loop iteration. | ||
258 | |||
259 | add2: | ||
260 | b uxn_ret | ||
261 | |||
262 | sub: | ||
263 | @ ldr r2, [r0, #-1]! | ||
264 | @ ldr r1, [r0, #-1]! | ||
265 | @ sub r1, r1, r2 | ||
266 | @ strb r1, [r0], #1 | ||
267 | b uxn_ret @ NOTE: This should return to the next loop iteration. | ||
268 | |||
269 | sub2: | ||
270 | b uxn_ret | ||
271 | |||
272 | mul: | ||
273 | b uxn_ret | ||
274 | |||
275 | mul2: | ||
276 | b uxn_ret | ||
277 | |||
278 | div: | ||
279 | b uxn_ret | ||
280 | |||
281 | div2: | ||
282 | b uxn_ret | ||
283 | |||
284 | and: | ||
285 | b uxn_ret | ||
286 | |||
287 | and2: | ||
288 | b uxn_ret | ||
289 | |||
290 | ora: | ||
291 | b uxn_ret | ||
292 | |||
293 | ora2: | ||
294 | b uxn_ret | ||
295 | |||
296 | eor: | ||
297 | b uxn_ret | ||
298 | |||
299 | eor2: | ||
300 | b uxn_ret | ||
301 | |||
302 | sft: | ||
303 | b uxn_ret | ||
304 | |||
305 | sft2: | ||
306 | b uxn_ret | ||
307 | |||
308 | @ OP table | ||
309 | op_table: | ||
310 | .word brk @ 0x00 | ||
311 | .word inc @ 0x01 | ||
312 | .word pop @ 0x02 | ||
313 | .word nip @ 0x03 | ||
314 | .word swp @ 0x04 | ||
315 | .word rot @ 0x05 | ||
316 | .word dup @ 0x06 | ||
317 | .word ovr @ 0x07 | ||
318 | .word equ @ 0x08 | ||
319 | .word neq @ 0x09 | ||
320 | .word gth @ 0x0a | ||
321 | .word lth @ 0x0b | ||
322 | .word jmp @ 0x0c | ||
323 | .word jcn @ 0x0d | ||
324 | .word jsr @ 0x0e | ||
325 | .word sth @ 0x0f | ||
326 | .word ldz @ 0x00 | ||
327 | .word stz @ 0x11 | ||
328 | .word ldr @ 0x12 | ||
329 | .word str @ 0x13 | ||
330 | .word lda @ 0x14 | ||
331 | .word sta @ 0x15 | ||
332 | .word dei @ 0x16 | ||
333 | .word deo @ 0x17 | ||
334 | .word add @ 0x18 | ||
335 | .word sub @ 0x19 | ||
336 | .word mul @ 0x1a | ||
337 | .word div @ 0x1b | ||
338 | .word and @ 0x1c | ||
339 | .word ora @ 0x1d | ||
340 | .word eor @ 0x1e | ||
341 | .word sft @ 0x1f | ||
342 | .word brk @ 0x20 | ||
343 | .word inc2 @ 0x21 | ||
344 | .word pop2 @ 0x22 | ||
345 | .word nip2 @ 0x23 | ||
346 | .word swp2 @ 0x24 | ||
347 | .word rot2 @ 0x25 | ||
348 | .word dup2 @ 0x26 | ||
349 | .word ovr2 @ 0x27 | ||
350 | .word equ2 @ 0x28 | ||
351 | .word neq2 @ 0x29 | ||
352 | .word gth2 @ 0x2a | ||
353 | .word lth2 @ 0x2b | ||
354 | .word jmp2 @ 0x2c | ||
355 | .word jcn2 @ 0x2d | ||
356 | .word jsr2 @ 0x2e | ||
357 | .word sth2 @ 0x2f | ||
358 | .word ldz2 @ 0x30 | ||
359 | .word stz2 @ 0x31 | ||
360 | .word ldr2 @ 0x32 | ||
361 | .word str2 @ 0x33 | ||
362 | .word lda2 @ 0x34 | ||
363 | .word sta2 @ 0x35 | ||
364 | .word dei2 @ 0x36 | ||
365 | .word deo2 @ 0x37 | ||
366 | .word add2 @ 0x38 | ||
367 | .word sub2 @ 0x39 | ||
368 | .word mul2 @ 0x3a | ||
369 | .word div2 @ 0x3b | ||
370 | .word and2 @ 0x3c | ||
371 | .word ora2 @ 0x3d | ||
372 | .word eor2 @ 0x3e | ||
373 | .word sft2 @ 0x3f | ||
374 | @ TODO: Can we mask this instead of having empty space? | ||
375 | .word brk @ 0x40 | ||
376 | .word brk @ 0x41 | ||
377 | .word brk @ 0x42 | ||
378 | .word brk @ 0x43 | ||
379 | .word brk @ 0x44 | ||
380 | .word brk @ 0x45 | ||
381 | .word brk @ 0x46 | ||
382 | .word brk @ 0x47 | ||
383 | .word brk @ 0x48 | ||
384 | .word brk @ 0x49 | ||
385 | .word brk @ 0x4a | ||
386 | .word brk @ 0x4b | ||
387 | .word brk @ 0x4c | ||
388 | .word brk @ 0x4d | ||
389 | .word brk @ 0x4e | ||
390 | .word brk @ 0x4f | ||
391 | .word brk @ 0x50 | ||
392 | .word brk @ 0x51 | ||
393 | .word brk @ 0x52 | ||
394 | .word brk @ 0x53 | ||
395 | .word brk @ 0x54 | ||
396 | .word brk @ 0x55 | ||
397 | .word brk @ 0x56 | ||
398 | .word brk @ 0x57 | ||
399 | .word brk @ 0x58 | ||
400 | .word brk @ 0x59 | ||
401 | .word brk @ 0x5a | ||
402 | .word brk @ 0x5b | ||
403 | .word brk @ 0x5c | ||
404 | .word brk @ 0x5d | ||
405 | .word brk @ 0x5e | ||
406 | .word brk @ 0x5f | ||
407 | .word brk @ 0x60 | ||
408 | .word brk @ 0x61 | ||
409 | .word brk @ 0x62 | ||
410 | .word brk @ 0x63 | ||
411 | .word brk @ 0x64 | ||
412 | .word brk @ 0x65 | ||
413 | .word brk @ 0x66 | ||
414 | .word brk @ 0x67 | ||
415 | .word brk @ 0x68 | ||
416 | .word brk @ 0x69 | ||
417 | .word brk @ 0x6a | ||
418 | .word brk @ 0x6b | ||
419 | .word brk @ 0x6c | ||
420 | .word brk @ 0x6d | ||
421 | .word brk @ 0x6e | ||
422 | .word brk @ 0x6f | ||
423 | .word brk @ 0x70 | ||
424 | .word brk @ 0x71 | ||
425 | .word brk @ 0x72 | ||
426 | .word brk @ 0x73 | ||
427 | .word brk @ 0x74 | ||
428 | .word brk @ 0x75 | ||
429 | .word brk @ 0x76 | ||
430 | .word brk @ 0x77 | ||
431 | .word brk @ 0x78 | ||
432 | .word brk @ 0x79 | ||
433 | .word brk @ 0x7a | ||
434 | .word brk @ 0x7b | ||
435 | .word brk @ 0x7c | ||
436 | .word brk @ 0x7d | ||
437 | .word brk @ 0x7e | ||
438 | .word brk @ 0x7f | ||
439 | .word litr @ 0x80 | ||
440 | .word brk @ 0x81 | ||
441 | .word brk @ 0x82 | ||
442 | .word brk @ 0x83 | ||
443 | .word brk @ 0x84 | ||
444 | .word brk @ 0x85 | ||
445 | .word brk @ 0x86 | ||
446 | .word brk @ 0x87 | ||
447 | .word brk @ 0x88 | ||
448 | .word brk @ 0x89 | ||
449 | .word brk @ 0x8a | ||
450 | .word brk @ 0x8b | ||
451 | .word brk @ 0x8c | ||
452 | .word brk @ 0x8d | ||
453 | .word brk @ 0x8e | ||
454 | .word brk @ 0x8f | ||
455 | .word brk @ 0x90 | ||
456 | .word brk @ 0x91 | ||
457 | .word brk @ 0x92 | ||
458 | .word brk @ 0x93 | ||
459 | .word brk @ 0x94 | ||
460 | .word brk @ 0x95 | ||
461 | .word brk @ 0x96 | ||
462 | .word brk @ 0x97 | ||
463 | .word brk @ 0x98 | ||
464 | .word brk @ 0x99 | ||
465 | .word brk @ 0x9a | ||
466 | .word brk @ 0x9b | ||
467 | .word brk @ 0x9c | ||
468 | .word brk @ 0x9d | ||
469 | .word brk @ 0x9e | ||
470 | .word brk @ 0x9f | ||
471 | .word brk @ 0xa0 | ||
472 | .word brk @ 0xa1 | ||
473 | .word brk @ 0xa2 | ||
474 | .word brk @ 0xa3 | ||
475 | .word brk @ 0xa4 | ||
476 | .word brk @ 0xa5 | ||
477 | .word brk @ 0xa6 | ||
478 | .word brk @ 0xa7 | ||
479 | .word brk @ 0xa8 | ||
480 | .word brk @ 0xa9 | ||
481 | .word brk @ 0xaa | ||
482 | .word brk @ 0xab | ||
483 | .word brk @ 0xac | ||
484 | .word brk @ 0xad | ||
485 | .word brk @ 0xae | ||
486 | .word brk @ 0xaf | ||
487 | .word brk @ 0xb0 | ||
488 | .word brk @ 0xb1 | ||
489 | .word brk @ 0xb2 | ||
490 | .word brk @ 0xb3 | ||
491 | .word brk @ 0xb4 | ||
492 | .word brk @ 0xb5 | ||
493 | .word brk @ 0xb6 | ||
494 | .word brk @ 0xb7 | ||
495 | .word brk @ 0xb8 | ||
496 | .word brk @ 0xb9 | ||
497 | .word brk @ 0xba | ||
498 | .word brk @ 0xbb | ||
499 | .word brk @ 0xbc | ||
500 | .word brk @ 0xbd | ||
501 | .word brk @ 0xbe | ||
502 | .word brk @ 0xbf | ||
503 | .word brk @ 0xc0 | ||
504 | .word brk @ 0xc1 | ||
505 | .word brk @ 0xc2 | ||
506 | .word brk @ 0xc3 | ||
507 | .word brk @ 0xc4 | ||
508 | .word brk @ 0xc5 | ||
509 | .word brk @ 0xc6 | ||
510 | .word brk @ 0xc7 | ||
511 | .word brk @ 0xc8 | ||
512 | .word brk @ 0xc9 | ||
513 | .word brk @ 0xca | ||
514 | .word brk @ 0xcb | ||
515 | .word brk @ 0xcc | ||
516 | .word brk @ 0xcd | ||
517 | .word brk @ 0xce | ||
518 | .word brk @ 0xcf | ||
519 | .word brk @ 0xd0 | ||
520 | .word brk @ 0xd1 | ||
521 | .word brk @ 0xd2 | ||
522 | .word brk @ 0xd3 | ||
523 | .word brk @ 0xd4 | ||
524 | .word brk @ 0xd5 | ||
525 | .word brk @ 0xd6 | ||
526 | .word brk @ 0xd7 | ||
527 | .word brk @ 0xd8 | ||
528 | .word brk @ 0xd9 | ||
529 | .word brk @ 0xda | ||
530 | .word brk @ 0xdb | ||
531 | .word brk @ 0xdc | ||
532 | .word brk @ 0xdd | ||
533 | .word brk @ 0xde | ||
534 | .word brk @ 0xdf | ||
535 | .word brk @ 0xe0 | ||
536 | .word brk @ 0xe1 | ||
537 | .word brk @ 0xe2 | ||
538 | .word brk @ 0xe3 | ||
539 | .word brk @ 0xe4 | ||
540 | .word brk @ 0xe5 | ||
541 | .word brk @ 0xe6 | ||
542 | .word brk @ 0xe7 | ||
543 | .word brk @ 0xe8 | ||
544 | .word brk @ 0xe9 | ||
545 | .word brk @ 0xea | ||
546 | .word brk @ 0xeb | ||
547 | .word brk @ 0xec | ||
548 | .word brk @ 0xed | ||
549 | .word brk @ 0xee | ||
550 | .word brk @ 0xef | ||
551 | .word brk @ 0xf0 | ||
552 | .word brk @ 0xf1 | ||
553 | .word brk @ 0xf2 | ||
554 | .word brk @ 0xf3 | ||
555 | .word brk @ 0xf4 | ||
556 | .word brk @ 0xf5 | ||
557 | .word brk @ 0xf6 | ||
558 | .word brk @ 0xf7 | ||
559 | .word brk @ 0xf8 | ||
560 | @ TODO: Can we mask this instead of having empty space? | ||
561 | .word lit2r @ 0xf9 | ||
562 | .word litr @ 0xfa | ||
563 | .word lit2r @ 0xfb | ||
564 | .word litr @ 0xfc | ||
565 | .word jsi @ 0xfd | ||
566 | .word jmi @ 0xfe | ||
567 | .word jci @ 0xff | ||