@@ 3,6 3,8 @@
#include "devices/apu.h"
#include "devices/ppu.h"
+#define PEEK16(d) ((d)[0] << 8 | (d)[1])
+#define RAM_PAGES 0x10
#define POLYPHONY 4
#define BOOT_ROM_FILENAME "boot.rom"
@@ 34,6 36,19 @@ emu_error(char *msg, const char *err)
}
static int
+system_load(Uxn *u, char *filename)
+{
+ int l, i = 0;
+ SDFile *f = pd->file->open(filename, kFileRead | kFileReadData);
+ if(!f)
+ return 0;
+ l = pd->file->read(f, u->ram + PAGE_PROGRAM, 0x10000 - PAGE_PROGRAM);
+ while(l && ++i < RAM_PAGES)
+ l = pd->file->read(f, u->ram + 0x10000 * i, 0x10000);
+ return 1;
+}
+
+static int
load(Uxn *u, char *filepath)
{
SDFile *f = pd->file->open(filepath, kFileRead | kFileReadData);
@@ 45,6 60,31 @@ load(Uxn *u, char *filepath)
}
static void
+system_cmd(Uint8 *ram, Uint16 addr)
+{
+ if(ram[addr] == 0x01) {
+ Uint16 i, length = PEEK16(ram + addr + 1);
+ Uint16 a_page = PEEK16(ram + addr + 1 + 2), a_addr = PEEK16(ram + addr + 1 + 4);
+ Uint16 b_page = PEEK16(ram + addr + 1 + 6), b_addr = PEEK16(ram + addr + 1 + 8);
+ int src = (a_page % RAM_PAGES) * 0x10000, dst = (b_page % RAM_PAGES) * 0x10000;
+ for(i = 0; i < length; i++)
+ ram[dst + (Uint16)(b_addr + i)] = ram[src + (Uint16)(a_addr + i)];
+ }
+}
+
+static void
+system_deo(Uint8 *d, Uint8 port)
+{
+ Uint16 a;
+ switch(port) {
+ case 0x3:
+ PEKDEV(a, 0x2);
+ system_cmd(u.ram, a);
+ break;
+ }
+}
+
+static void
console_deo(Uint8 *d, Uint8 port)
{
if(port == 0x8)
@@ 144,6 184,7 @@ emu_deo(Uxn *u, Uint8 addr, Uint8 v)
Uint16 mask = 0x1 << (d >> 4);
u->dev[addr] = v;
switch(d) {
+ case 0x00: system_deo(&u->dev[d], p); break;
case 0x10: console_deo(&u->dev[d], p); break;
case 0x20: screen_deo(&u->dev[d], p); break;
case 0x30: audio_deo(&u->dev[d], p); break;
@@ 154,9 195,9 @@ static int
emu_start(Uxn *u, char *filename)
{
free(u->ram);
- if(!uxn_boot(u, (Uint8 *)calloc(0x10300, sizeof(Uint8)), emu_dei, emu_deo))
- return emu_error("Boot", "Failed");
- if(!load(u, filename))
+ if(!uxn_boot(u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), emu_dei, emu_deo))
+ return emu_error("Boot", "Failed to start uxn.");
+ if(!system_load(u, filename))
return emu_error("Load", "Failed");
if(!uxn_eval(u, PAGE_PROGRAM))
return emu_error("Boot", "Failed to start rom.");
@@ 1,7 1,7 @@
#include "uxn.h"
/*
-Copyright (u) 2022 Devine Lu Linvega, Andrew Alderwick, Andrew Richards
+Copyright (u) 2022-2023 Devine Lu Linvega, Andrew Alderwick, Andrew Richards
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ 11,47 11,53 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
-/* clang-format off */
+/* a,b,c: general use. bs: byte/short bool. src, dst: stack ptrs, swapped in return mode.
+ pc: program counter. sp: ptr to src stack ptr. kptr: "keep" mode copy of src stack ptr.
+ x,y: macro in params. d: macro in device. j: macro temp variables. o: macro out param. */
-#define PUSH8(s, x) { if(s->ptr == 0xff) { errcode = 2; goto err; } s->dat[s->ptr++] = (x); }
-#define PUSH16(s, x) { if((j = s->ptr) >= 0xfe) { errcode = 2; goto err; } k = (x); s->dat[j] = k >> 8; s->dat[j + 1] = k; s->ptr = j + 2; }
+#define HALT(c) { return uxn_halt(u, instr, (c), pc - 1); }
+#define JUMP(x) { if(bs) pc = (x); else pc += (Sint8)(x); }
+#define PUSH8(s, x) { if(s->ptr == 0xff) HALT(2) s->dat[s->ptr++] = (x); }
+#define PUSH16(s, x) { if((j = s->ptr) >= 0xfe) HALT(2) k = (x); s->dat[j] = k >> 8; s->dat[j + 1] = k; s->ptr = j + 2; }
#define PUSH(s, x) { if(bs) { PUSH16(s, (x)) } else { PUSH8(s, (x)) } }
-#define POP8(o) { if(!(j = *sp)) { errcode = 1; goto err; } o = (Uint16)src->dat[--j]; *sp = j; }
-#define POP16(o) { if((j = *sp) <= 1) { errcode = 1; goto err; } o = src->dat[j - 1]; o += src->dat[j - 2] << 8; *sp = j - 2; }
+#define POP8(o) { if(!(j = *sp)) HALT(1) o = (Uint16)src->dat[--j]; *sp = j; }
+#define POP16(o) { if((j = *sp) <= 1) HALT(1) o = (src->dat[j - 2] << 8) + src->dat[j - 1]; *sp = j - 2; }
#define POP(o) { if(bs) { POP16(o) } else { POP8(o) } }
#define POKE(x, y) { if(bs) { u->ram[(x)] = (y) >> 8; u->ram[(x) + 1] = (y); } else { u->ram[(x)] = y; } }
#define PEEK16(o, x) { o = (u->ram[(x)] << 8) + u->ram[(x) + 1]; }
-#define PEEK(o, x) { if(bs) { PEEK16(o, x) } else { o = u->ram[(x)]; } }
-#define DEVR(o, x) { o = u->dei(u, x); if (bs) o = (o << 8) + u->dei(u, ((x) + 1) & 0xFF); }
-#define DEVW(x, y) { if (bs) { u->deo(u, (x), (y) >> 8); u->deo(u, ((x) + 1) & 0xFF, (y)); } else { u->deo(u, x, (y)); } }
-#define JUMP(x) { if(bs) pc = (x); else pc += (Sint8)(x); }
+#define PEEK(o, x) { if(bs) PEEK16(o, x) else o = u->ram[(x)]; }
+#define DEVR(o, x) { o = u->dei(u, x); if (bs) o = (o << 8) + u->dei(u, (x) + 1); }
+#define DEVW(x, y) { if (bs) { u->deo(u, (x), (y) >> 8); u->deo(u, (x) + 1, (y)); } else { u->deo(u, x, (y)); } }
int
uxn_eval(Uxn *u, Uint16 pc)
{
- unsigned int a, b, c, j, k, bs, instr, errcode;
Uint8 kptr, *sp;
+ Uint16 a, b, c, j, k, bs, instr, opcode;
Stack *src, *dst;
if(!pc || u->dev[0x0f]) return 0;
- while((instr = u->ram[pc++])) {
+ for(;;) {
+ instr = u->ram[pc++];
/* Return Mode */
- if(instr & 0x40) {
- src = u->rst; dst = u->wst;
- } else {
- src = u->wst; dst = u->rst;
- }
+ if(instr & 0x40) { src = u->rst; dst = u->wst; }
+ else { src = u->wst; dst = u->rst; }
/* Keep Mode */
- if(instr & 0x80) {
- kptr = src->ptr;
- sp = &kptr;
- } else {
- sp = &src->ptr;
- }
+ if(instr & 0x80) { kptr = src->ptr; sp = &kptr; }
+ else sp = &src->ptr;
/* Short Mode */
- bs = instr & 0x20 ? 1 : 0;
- switch(instr & 0x1f) {
- /* Stack */
- case 0x00: /* LIT */ PEEK(a, pc) PUSH(src, a) pc += 1 + bs; break;
+ bs = instr & 0x20;
+ opcode = instr & 0x1f;
+ switch(opcode - (!opcode * (instr >> 5))) {
+ /* Literals/Calls */
+ case -0x0: /* BRK */ return 1;
+ case -0x1: /* JCI */ POP8(b) if(!b) { pc += 2; break; }
+ case -0x2: /* JMI */ PEEK16(a, pc) pc += a + 2; break;
+ case -0x3: /* JSI */ PUSH16(u->rst, pc + 2) PEEK16(a, pc) pc += a + 2; break;
+ case -0x4: /* LIT */
+ case -0x6: /* LITr */ a = u->ram[pc++]; PUSH8(src, a) break;
+ case -0x5: /* LIT2 */
+ case -0x7: /* LIT2r */ PEEK16(a, pc) PUSH16(src, a) pc += 2; break;
+ /* ALU */
case 0x01: /* INC */ POP(a) PUSH(src, a + 1) break;
case 0x02: /* POP */ POP(a) break;
case 0x03: /* NIP */ POP(a) POP(b) PUSH(src, a) break;
@@ 59,7 65,6 @@ uxn_eval(Uxn *u, Uint16 pc)
case 0x05: /* ROT */ POP(a) POP(b) POP(c) PUSH(src, b) PUSH(src, a) PUSH(src, c) break;
case 0x06: /* DUP */ POP(a) PUSH(src, a) PUSH(src, a) break;
case 0x07: /* OVR */ POP(a) POP(b) PUSH(src, b) PUSH(src, a) PUSH(src, b) break;
- /* Logic */
case 0x08: /* EQU */ POP(a) POP(b) PUSH8(src, b == a) break;
case 0x09: /* NEQ */ POP(a) POP(b) PUSH8(src, b != a) break;
case 0x0a: /* GTH */ POP(a) POP(b) PUSH8(src, b > a) break;
@@ 68,45 73,38 @@ uxn_eval(Uxn *u, Uint16 pc)
case 0x0d: /* JCN */ POP(a) POP8(b) if(b) JUMP(a) break;
case 0x0e: /* JSR */ POP(a) PUSH16(dst, pc) JUMP(a) break;
case 0x0f: /* STH */ POP(a) PUSH(dst, a) break;
- /* Memory */
case 0x10: /* LDZ */ POP8(a) PEEK(b, a) PUSH(src, b) break;
case 0x11: /* STZ */ POP8(a) POP(b) POKE(a, b) break;
- case 0x12: /* LDR */ POP8(a) PEEK(b, pc + (Sint8)a) PUSH(src, b) break;
+ case 0x12: /* LDR */ POP8(a) b = pc + (Sint8)a; PEEK(c, b) PUSH(src, c) break;
case 0x13: /* STR */ POP8(a) POP(b) c = pc + (Sint8)a; POKE(c, b) break;
case 0x14: /* LDA */ POP16(a) PEEK(b, a) PUSH(src, b) break;
case 0x15: /* STA */ POP16(a) POP(b) POKE(a, b) break;
case 0x16: /* DEI */ POP8(a) DEVR(b, a) PUSH(src, b) break;
case 0x17: /* DEO */ POP8(a) POP(b) DEVW(a, b) break;
- /* Arithmetic */
case 0x18: /* ADD */ POP(a) POP(b) PUSH(src, b + a) break;
case 0x19: /* SUB */ POP(a) POP(b) PUSH(src, b - a) break;
case 0x1a: /* MUL */ POP(a) POP(b) PUSH(src, (Uint32)b * a) break;
- case 0x1b: /* DIV */ POP(a) POP(b) if(a == 0) { errcode = 3; goto err; } PUSH(src, b / a) break;
+ case 0x1b: /* DIV */ POP(a) POP(b) if(!a) HALT(3) PUSH(src, b / a) break;
case 0x1c: /* AND */ POP(a) POP(b) PUSH(src, b & a) break;
case 0x1d: /* ORA */ POP(a) POP(b) PUSH(src, b | a) break;
case 0x1e: /* EOR */ POP(a) POP(b) PUSH(src, b ^ a) break;
case 0x1f: /* SFT */ POP8(a) POP(b) PUSH(src, b >> (a & 0x0f) << ((a & 0xf0) >> 4)) break;
}
}
- return 1;
-err:
- return uxn_halt(u, instr, errcode, pc - 1);
}
-/* clang-format on */
-
int
-uxn_boot(Uxn *u, Uint8 *ram, Uint8 (*dei)(struct Uxn *, Uint8), void (*deo)(struct Uxn *, Uint8, Uint8))
+uxn_boot(Uxn *u, Uint8 *ram, Dei *dei, Deo *deo)
{
Uint32 i;
char *cptr = (char *)u;
for(i = 0; i < sizeof(*u); i++)
cptr[i] = 0x00;
+ u->wst = (Stack *)(ram + 0xf0000);
+ u->rst = (Stack *)(ram + 0xf0100);
+ u->dev = (Uint8 *)(ram + 0xf0200);
u->ram = ram;
- u->wst = (Stack *)(ram + 0x10000);
- u->rst = (Stack *)(ram + 0x10100);
- u->dev = (Uint8 *)(ram + 0x10200);
u->dei = dei;
u->deo = deo;
return 1;
-}
+}<
\ No newline at end of file
@@ 26,7 26,7 @@ typedef unsigned int Uint32;
/* clang-format on */
typedef struct {
- Uint8 dat[254], err, ptr;
+ Uint8 dat[255], ptr;
} Stack;
typedef struct Uxn {
@@ 39,6 39,6 @@ typedef struct Uxn {
typedef Uint8 Dei(Uxn *u, Uint8 addr);
typedef void Deo(Uxn *u, Uint8 addr, Uint8 value);
-int uxn_boot(Uxn *u, Uint8 *ram, Dei *dei, Deo *deo);
-int uxn_eval(Uxn *u, Uint16 pc);
int uxn_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr);
+int uxn_boot(Uxn *u, Uint8 *ram, Dei *dei, Deo *deo);
+int uxn_eval(Uxn *u, Uint16 pc);<
\ No newline at end of file