aboutsummaryrefslogtreecommitdiffstats
path: root/src/uxn
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-05-18 16:40:24 +0200
committerBad Diode <bd@badd10de.dev>2021-05-18 16:40:24 +0200
commit0c7265cf0de9d4ec95d28c5e103c00a63f4a1697 (patch)
tree4a1145e849e078395430a8d718c4bd69a06fb29f /src/uxn
downloaduxngba-0c7265cf0de9d4ec95d28c5e103c00a63f4a1697.tar.gz
uxngba-0c7265cf0de9d4ec95d28c5e103c00a63f4a1697.zip
Proof of concept of UXN on the GBA
Diffstat (limited to 'src/uxn')
-rw-r--r--src/uxn/devices/ppu.c180
-rw-r--r--src/uxn/devices/ppu.h36
-rw-r--r--src/uxn/roms/console.c5
-rw-r--r--src/uxn/roms/dvd.c22
-rw-r--r--src/uxn/uxn.c196
-rw-r--r--src/uxn/uxn.h55
6 files changed, 494 insertions, 0 deletions
diff --git a/src/uxn/devices/ppu.c b/src/uxn/devices/ppu.c
new file mode 100644
index 0000000..b977f97
--- /dev/null
+++ b/src/uxn/devices/ppu.c
@@ -0,0 +1,180 @@
1#include "ppu.h"
2
3/*
4Copyright (c) 2021 Devine Lu Linvega
5Copyright (c) 2021 Andrew Alderwick
6
7Permission to use, copy, modify, and distribute this software for any
8purpose with or without fee is hereby granted, provided that the above
9copyright notice and this permission notice appear in all copies.
10
11THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12WITH REGARD TO THIS SOFTWARE.
13*/
14
15static Uint8 font[][8] = {
16 {0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c},
17 {0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
18 {0x00, 0x7c, 0x82, 0x02, 0x7c, 0x80, 0x80, 0xfe},
19 {0x00, 0x7c, 0x82, 0x02, 0x1c, 0x02, 0x82, 0x7c},
20 {0x00, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04},
21 {0x00, 0xfe, 0x80, 0x80, 0x7c, 0x02, 0x82, 0x7c},
22 {0x00, 0x7c, 0x82, 0x80, 0xfc, 0x82, 0x82, 0x7c},
23 {0x00, 0x7c, 0x82, 0x02, 0x1e, 0x02, 0x02, 0x02},
24 {0x00, 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c},
25 {0x00, 0x7c, 0x82, 0x82, 0x7e, 0x02, 0x82, 0x7c},
26 {0x00, 0x7c, 0x82, 0x02, 0x7e, 0x82, 0x82, 0x7e},
27 {0x00, 0xfc, 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc},
28 {0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c},
29 {0x00, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc},
30 {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c},
31 {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80}};
32
33Uint8
34readpixel(Uint8 *sprite, Uint8 h, Uint8 v)
35{
36 Uint8 ch1 = ((sprite[v] >> h) & 0x1);
37 Uint8 ch2 = (((sprite[v + 8] >> h) & 0x1) << 1);
38 return ch1 + ch2;
39}
40
41void
42clear(Ppu *p)
43{
44 int i, sz = p->height * p->width, rows = sz / 4;
45 for(i = 0; i < sz; ++i)
46 p->output[i] = p->colors[0];
47 for(i = 0; i < rows; i++) {
48 p->fg[i] = 0;
49 p->bg[i] = 0;
50 }
51}
52
53void
54putcolors(Ppu *p, Uint8 *addr)
55{
56 int i;
57 for(i = 0; i < 4; ++i) {
58 Uint8
59 r = (*(addr + i / 2) >> (!(i % 2) << 2)) & 0x0f,
60 g = (*(addr + 2 + i / 2) >> (!(i % 2) << 2)) & 0x0f,
61 b = (*(addr + 4 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
62 p->colors[i] = rgb15(r,g,b);
63 }
64 // p->colors[0] = COLOR_BLUE;
65 // p->colors[1] = COLOR_WHITE;
66 // p->colors[2] = COLOR_RED;
67 // p->colors[3] = COLOR_CYAN;
68}
69
70void
71putpixel(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 color)
72{
73 Uint16 row = (y % 8) + ((x / 8 + y / 8 * p->hor) * 16), col = 7 - (x % 8);
74 if(x >= p->hor * 8 || y >= p->ver * 8 || row > (p->hor * p->ver * 16) - 8)
75 return;
76 if(color == 0 || color == 2)
77 layer[row] &= ~(1UL << col);
78 else
79 layer[row] |= 1UL << col;
80 if(color == 0 || color == 1)
81 layer[row + 8] &= ~(1UL << col);
82 else
83 layer[row + 8] |= 1UL << col;
84}
85
86void
87puticn(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
88{
89 Uint16 v, h;
90 for(v = 0; v < 8; v++)
91 for(h = 0; h < 8; h++) {
92 Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1);
93 if(ch1 == 1 || (color != 0x05 && color != 0x0a && color != 0x0f))
94 putpixel(p,
95 layer,
96 x + (flipx ? 7 - h : h),
97 y + (flipy ? 7 - v : v),
98 ch1 ? color % 4 : color / 4);
99 }
100}
101
102void
103putchr(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
104{
105 Uint16 v, h;
106 for(v = 0; v < 8; v++)
107 for(h = 0; h < 8; h++) {
108 Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1) * color;
109 Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1) * color;
110 putpixel(p,
111 layer,
112 x + (flipx ? 7 - h : h),
113 y + (flipy ? 7 - v : v),
114 (((ch1 + ch2 * 2) + color / 4) & 0x3));
115 }
116}
117
118/* output */
119
120void
121drawpixel(Ppu *p, Uint16 x, Uint16 y, Uint8 color)
122{
123 if(x >= p->pad && x <= p->width - p->pad - 1 && y >= p->pad && y <= p->height - p->pad - 1)
124 p->output[y * p->width + x] = p->colors[color];
125}
126
127void
128drawdebugger(Ppu *p, Uint8 *stack, Uint8 ptr)
129{
130 Uint8 i, x, y, b;
131 for(i = 0; i < 0x20; ++i) { /* memory */
132 x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i];
133 puticn(p, p->bg, x, y, font[(b >> 4) & 0xf], 1 + (ptr == i) * 0x7, 0, 0);
134 puticn(p, p->bg, x + 8, y, font[b & 0xf], 1 + (ptr == i) * 0x7, 0, 0);
135 }
136 for(x = 0; x < 0x20; ++x) {
137 drawpixel(p, x, p->height / 2, 2);
138 drawpixel(p, p->width - x, p->height / 2, 2);
139 drawpixel(p, p->width / 2, p->height - x, 2);
140 drawpixel(p, p->width / 2, x, 2);
141 drawpixel(p, p->width / 2 - 16 + x, p->height / 2, 2);
142 drawpixel(p, p->width / 2, p->height / 2 - 16 + x, 2);
143 }
144}
145
146void
147drawppu(Ppu *p)
148{
149 Uint16 x, y;
150 for(y = 0; y < p->ver; ++y)
151 for(x = 0; x < p->hor; ++x) {
152 Uint8 v, h;
153 Uint16 key = (y * p->hor + x) * 16;
154 for(v = 0; v < 8; v++)
155 for(h = 0; h < 8; h++) {
156 Uint8 color = readpixel(&p->fg[key], h, v);
157 if(color == 0)
158 color = readpixel(&p->bg[key], h, v);
159 drawpixel(p, x * 8 + p->pad + 7 - h, y * 8 + p->pad + v, color);
160 }
161 }
162}
163
164int
165initppu(Ppu *p, Uint8 hor, Uint8 ver, Uint8 pad)
166{
167 p->hor = hor;
168 p->ver = ver;
169 p->pad = pad;
170 p->width = (8 * p->hor + p->pad * 2);
171 p->height = (8 * p->ver + p->pad * 2);
172 if(!(p->output = malloc(p->width * p->height * sizeof(Uint16))))
173 return 0;
174 if(!(p->bg = malloc(p->width * p->height * sizeof(Uint8) / 4)))
175 return 0;
176 if(!(p->fg = malloc(p->width * p->height * sizeof(Uint8) / 4)))
177 return 0;
178 clear(p);
179 return 1;
180}
diff --git a/src/uxn/devices/ppu.h b/src/uxn/devices/ppu.h
new file mode 100644
index 0000000..187d364
--- /dev/null
+++ b/src/uxn/devices/ppu.h
@@ -0,0 +1,36 @@
1#ifndef UXNGBA_PPU_H
2#define UXNGBA_PPU_H
3
4#include <stdio.h>
5#include <stdlib.h>
6
7/*
8Copyright (c) 2021 Devine Lu Linvega
9Copyright (c) 2021 Andrew Alderwick
10
11Permission to use, copy, modify, and distribute this software for any
12purpose with or without fee is hereby granted, provided that the above
13copyright notice and this permission notice appear in all copies.
14
15THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16WITH REGARD TO THIS SOFTWARE.
17*/
18
19typedef unsigned char Uint8;
20typedef unsigned short Uint16;
21typedef unsigned int Uint32;
22
23typedef struct Ppu {
24 Uint8 *bg, *fg;
25 Uint16 hor, ver, pad, width, height;
26 Uint16 *output, colors[4];
27} Ppu;
28
29int initppu(Ppu *p, Uint8 hor, Uint8 ver, Uint8 pad);
30void putcolors(Ppu *p, Uint8 *addr);
31void putpixel(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 color);
32void puticn(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);
33void putchr(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);
34void drawppu(Ppu *p);
35void drawdebugger(Ppu *p, Uint8 *stack, Uint8 ptr);
36#endif // UXNGBA_PPU_H
diff --git a/src/uxn/roms/console.c b/src/uxn/roms/console.c
new file mode 100644
index 0000000..13d669a
--- /dev/null
+++ b/src/uxn/roms/console.c
@@ -0,0 +1,5 @@
1u16 uxn_rom[] = {
2 0x0121, 0x9411, 0x1801, 0x2117, 0x0100, 0x9438, 0xf401, 0x230d,
3 0x4800, 0x6c65, 0x6f6c, 0x5720, 0x726f, 0x646c, 0x6620, 0x6f72,
4 0x206d, 0x5855, 0x214e, 0x000d
5};
diff --git a/src/uxn/roms/dvd.c b/src/uxn/roms/dvd.c
new file mode 100644
index 0000000..2cccc84
--- /dev/null
+++ b/src/uxn/roms/dvd.c
@@ -0,0 +1,22 @@
1u16 uxn_rom[] = {
2 0x4c21, 0x01fd, 0x3708, 0x4c21, 0x01f3, 0x370a, 0xdc21, 0x01f2,
3 0x370c, 0x0121, 0x0133, 0x3720, 0x2201, 0x2136, 0x0200, 0x013b,
4 0x3100, 0x2401, 0x2136, 0x0200, 0x013b, 0x3102, 0x2101, 0x0121,
5 0x2eb2, 0x0100, 0x2120, 0xb201, 0x012e, 0x3000, 0x2201, 0x2136,
6 0x2000, 0x2839, 0x0001, 0x2130, 0x0000, 0x2128, 0x0000, 0x0128,
7 0x0d09, 0x0401, 0x0110, 0x0800, 0x0401, 0x0111, 0x3002, 0x2401,
8 0x2136, 0x1000, 0x2839, 0x0201, 0x2130, 0x0000, 0x2128, 0x0000,
9 0x0128, 0x0d09, 0x0501, 0x0110, 0x0800, 0x0501, 0x0111, 0x3000,
10 0x0021, 0x0101, 0x0100, 0x1004, 0x0001, 0x2108, 0xfeff, 0x383a,
11 0x0138, 0x3100, 0x0201, 0x2130, 0x0100, 0x0001, 0x0501, 0x0110,
12 0x0800, 0xff21, 0x3afe, 0x3838, 0x0201, 0x0131, 0x2121, 0xb201,
13 0x002e, 0x210f, 0xfd01, 0x2c01, 0x0137, 0x3002, 0x0201, 0x2130,
14 0x1000, 0x2638, 0x2a01, 0x0137, 0x3000, 0x0001, 0x2130, 0x2000,
15 0x2638, 0x2801, 0xcf37, 0x2e01, 0x0117, 0x362c, 0x0021, 0x3808,
16 0x2c01, 0x2537, 0x0021, 0x3808, 0xab25, 0xe401, 0x230d, 0x2523,
17 0x0021, 0x3808, 0xab25, 0xca01, 0x230d, 0x4323, 0x006c, 0x3f1f,
18 0x3838, 0x7838, 0x007f, 0xfefe, 0x777e, 0xe377, 0x00c3, 0x1f0f,
19 0x7b3b, 0xe777, 0x00c7, 0xfefc, 0x878f, 0x0e07, 0x7ffc, 0x0000,
20 0xff0f, 0x077f, 0x0300, 0x0001, 0xf0ff, 0xfff8, 0x8700, 0x0000,
21 0x7fff, 0xff7f, 0xf000, 0x0000, 0xfce0, 0x80fc, 0x0a00,
22};
diff --git a/src/uxn/uxn.c b/src/uxn/uxn.c
new file mode 100644
index 0000000..796a980
--- /dev/null
+++ b/src/uxn/uxn.c
@@ -0,0 +1,196 @@
1#include <stdio.h>
2#include "uxn.h"
3
4/*
5Copyright (u) 2021 Devine Lu Linvega
6
7Permission to use, copy, modify, and distribute this software for any
8purpose with or without fee is hereby granted, provided that the above
9copyright notice and this permission notice appear in all copies.
10
11THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12WITH REGARD TO THIS SOFTWARE.
13*/
14
15#pragma mark - Operations
16
17/* clang-format off */
18void push8(Stack *s, Uint8 a) { if (s->ptr == 0xff) { s->error = 2; return; } s->dat[s->ptr++] = a; }
19Uint8 pop8_keep(Stack *s) { if (s->kptr == 0) { s->error = 1; return 0; } return s->dat[--s->kptr]; }
20Uint8 pop8_nokeep(Stack *s) { if (s->ptr == 0) { s->error = 1; return 0; } return s->dat[--s->ptr]; }
21static Uint8 (*pop8)(Stack *s);
22void mempoke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; }
23Uint8 mempeek8(Uint8 *m, Uint16 a) { return m[a]; }
24void devpoke8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; d->talk(d, a & 0x0f, 1); }
25Uint8 devpeek8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf]; }
26void push16(Stack *s, Uint16 a) { push8(s, a >> 8); push8(s, a); }
27Uint16 pop16(Stack *s) { return pop8(s) + (pop8(s) << 8); }
28void mempoke16(Uint8 *m, Uint16 a, Uint16 b) { mempoke8(m, a, b >> 8); mempoke8(m, a + 1, b); }
29Uint16 mempeek16(Uint8 *m, Uint16 a) { return (mempeek8(m, a) << 8) + mempeek8(m, a + 1); }
30void devpoke16(Device *d, Uint8 a, Uint16 b) { devpoke8(d, a, b >> 8); devpoke8(d, a + 1, b); }
31Uint16 devpeek16(Device *d, Uint16 a) { return (devpeek8(d, a) << 8) + devpeek8(d, a + 1); }
32/* Stack */
33void op_brk(Uxn *u) { u->ram.ptr = 0; }
34void op_nop(Uxn *u) { (void)u; }
35void op_lit(Uxn *u) { push8(u->src, mempeek8(u->ram.dat, u->ram.ptr++)); }
36void op_pop(Uxn *u) { pop8(u->src); }
37void op_dup(Uxn *u) { Uint8 a = pop8(u->src); push8(u->src, a); push8(u->src, a); }
38void op_swp(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, a); push8(u->src, b); }
39void op_ovr(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b); push8(u->src, a); push8(u->src, b); }
40void op_rot(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src), c = pop8(u->src); push8(u->src, b); push8(u->src, a); push8(u->src, c); }
41/* Logic */
42void op_equ(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b == a); }
43void op_neq(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b != a); }
44void op_gth(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b > a); }
45void op_lth(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b < a); }
46void op_jmp(Uxn *u) { Uint8 a = pop8(u->src); u->ram.ptr += (Sint8)a; }
47void op_jnz(Uxn *u) { Uint8 a = pop8(u->src); if (pop8(u->src)) u->ram.ptr += (Sint8)a; }
48void op_jsr(Uxn *u) { Uint8 a = pop8(u->src); push16(u->dst, u->ram.ptr); u->ram.ptr += (Sint8)a; }
49void op_sth(Uxn *u) { Uint8 a = pop8(u->src); push8(u->dst, a); }
50/* Memory */
51void op_pek(Uxn *u) { Uint8 a = pop8(u->src); push8(u->src, mempeek8(u->ram.dat, a)); }
52void op_pok(Uxn *u) { Uint8 a = pop8(u->src); Uint8 b = pop8(u->src); mempoke8(u->ram.dat, a, b); }
53void op_ldr(Uxn *u) { Uint8 a = pop8(u->src); push8(u->src, mempeek8(u->ram.dat, u->ram.ptr + (Sint8)a)); }
54void op_str(Uxn *u) { Uint8 a = pop8(u->src); Uint8 b = pop8(u->src); mempoke8(u->ram.dat, u->ram.ptr + (Sint8)a, b); }
55void op_lda(Uxn *u) { Uint16 a = pop16(u->src); push8(u->src, mempeek8(u->ram.dat, a)); }
56void op_sta(Uxn *u) { Uint16 a = pop16(u->src); Uint8 b = pop8(u->src); mempoke8(u->ram.dat, a, b); }
57void op_dei(Uxn *u) { Uint8 a = pop8(u->src); push8(u->src, devpeek8(&u->dev[a >> 4], a)); }
58void op_deo(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); devpoke8(&u->dev[a >> 4], a, b); }
59/* Arithmetic */
60void op_add(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b + a); }
61void op_sub(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b - a); }
62void op_mul(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b * a); }
63void op_div(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b / a); }
64void op_and(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b & a); }
65void op_ora(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b | a); }
66void op_eor(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b ^ a); }
67void op_sft(Uxn *u) { Uint8 a = pop8(u->src), b = pop8(u->src); push8(u->src, b >> (a & 0x07) << ((a & 0x70) >> 4)); }
68/* Stack */
69void op_lit16(Uxn *u) { push16(u->src, mempeek16(u->ram.dat, u->ram.ptr++)); u->ram.ptr++; }
70void op_pop16(Uxn *u) { pop16(u->src); }
71void op_dup16(Uxn *u) { Uint16 a = pop16(u->src); push16(u->src, a); push16(u->src, a); }
72void op_swp16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, a); push16(u->src, b); }
73void op_ovr16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b); push16(u->src, a); push16(u->src, b); }
74void op_rot16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src), c = pop16(u->src); push16(u->src, b); push16(u->src, a); push16(u->src, c); }
75/* Logic(16-bits) */
76void op_equ16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push8(u->src, b == a); }
77void op_neq16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push8(u->src, b != a); }
78void op_gth16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push8(u->src, b > a); }
79void op_lth16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push8(u->src, b < a); }
80void op_jmp16(Uxn *u) { u->ram.ptr = pop16(u->src); }
81void op_jnz16(Uxn *u) { Uint16 a = pop16(u->src); if (pop8(u->src)) u->ram.ptr = a; }
82void op_jsr16(Uxn *u) { push16(u->dst, u->ram.ptr); u->ram.ptr = pop16(u->src); }
83void op_sth16(Uxn *u) { Uint16 a = pop16(u->src); push16(u->dst, a); }
84/* Memory(16-bits) */
85void op_pek16(Uxn *u) { Uint8 a = pop8(u->src); push16(u->src, mempeek16(u->ram.dat, a)); }
86void op_pok16(Uxn *u) { Uint8 a = pop8(u->src); Uint16 b = pop16(u->src); mempoke16(u->ram.dat, a, b); }
87void op_ldr16(Uxn *u) { Uint8 a = pop8(u->src); push16(u->src, mempeek16(u->ram.dat, u->ram.ptr + (Sint8)a)); }
88void op_str16(Uxn *u) { Uint8 a = pop8(u->src); Uint16 b = pop16(u->src); mempoke16(u->ram.dat, u->ram.ptr + (Sint8)a, b); }
89void op_lda16(Uxn *u) { Uint16 a = pop16(u->src); push16(u->src, mempeek16(u->ram.dat, a)); }
90void op_sta16(Uxn *u) { Uint16 a = pop16(u->src); Uint16 b = pop16(u->src); mempoke16(u->ram.dat, a, b); }
91void op_dei16(Uxn *u) { Uint8 a = pop8(u->src); push16(u->src, devpeek16(&u->dev[a >> 4], a)); }
92void op_deo16(Uxn *u) { Uint8 a = pop8(u->src); Uint16 b = pop16(u->src); devpoke16(&u->dev[a >> 4], a, b); }
93/* Arithmetic(16-bits) */
94void op_add16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b + a); }
95void op_sub16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b - a); }
96void op_mul16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b * a); }
97void op_div16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b / a); }
98void op_and16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b & a); }
99void op_ora16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b | a); }
100void op_eor16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b ^ a); }
101void op_sft16(Uxn *u) { Uint16 a = pop16(u->src), b = pop16(u->src); push16(u->src, b >> (a & 0x000f) << ((a & 0x00f0) >> 4)); }
102
103void (*ops[])(Uxn *u) = {
104 op_brk, op_lit, op_nop, op_pop, op_dup, op_swp, op_ovr, op_rot,
105 op_equ, op_neq, op_gth, op_lth, op_jmp, op_jnz, op_jsr, op_sth,
106 op_pek, op_pok, op_ldr, op_str, op_lda, op_sta, op_dei, op_deo,
107 op_add, op_sub, op_mul, op_div, op_and, op_ora, op_eor, op_sft,
108 /* 16-bit */
109 op_brk, op_lit16, op_nop, op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16,
110 op_equ16, op_neq16, op_gth16, op_lth16, op_jmp16, op_jnz16, op_jsr16, op_sth16,
111 op_pek16, op_pok16, op_ldr16, op_str16, op_lda16, op_sta16, op_dei16, op_deo16,
112 op_add16, op_sub16, op_mul16, op_div16, op_and16, op_ora16, op_eor16, op_sft16
113};
114
115/* clang-format on */
116
117#pragma mark - Core
118
119int
120haltuxn(Uxn *u, char *name, int id)
121{
122 txt_printf("Halted: %s#%04x, at 0x%04x\n", name, id, u->ram.ptr);
123 u->ram.ptr = 0;
124 return 0;
125}
126
127void
128opcuxn(Uxn *u, Uint8 instr)
129{
130 Uint8 op = instr & 0x3f, freturn = instr & 0x40, fkeep = instr & 0x80;
131 u->src = freturn ? &u->rst : &u->wst;
132 u->dst = freturn ? &u->wst : &u->rst;
133 if(fkeep) {
134 pop8 = pop8_keep;
135 u->src->kptr = u->src->ptr;
136 } else {
137 pop8 = pop8_nokeep;
138 }
139 (*ops[op])(u);
140}
141
142int
143stepuxn(Uxn *u, Uint8 instr)
144{
145 opcuxn(u, instr);
146 if(u->wst.error)
147 return haltuxn(u, u->wst.error == 1 ? "Working-stack underflow" : "Working-stack overflow", instr);
148 if(u->rst.error)
149 return haltuxn(u, u->rst.error == 1 ? "Return-stack underflow" : "Return-stack overflow", instr);
150 return 1;
151}
152
153int
154evaluxn(Uxn *u, Uint16 vec)
155{
156 u->ram.ptr = vec;
157 u->wst.error = 0;
158 u->rst.error = 0;
159 while(u->ram.ptr)
160 if(!stepuxn(u, u->ram.dat[u->ram.ptr++]))
161 return 0;
162 return 1;
163}
164
165int
166bootuxn(Uxn *u)
167{
168 size_t i;
169 char *cptr = (char *)u;
170 for(i = 0; i < sizeof(*u); i++)
171 cptr[i] = 0;
172 return 1;
173}
174
175int
176loaduxn(Uxn *u, char *filepath)
177{
178 FILE *f;
179 if(!(f = fopen(filepath, "rb")))
180 return haltuxn(u, "Missing input rom.", 0);
181 fread(u->ram.dat + PAGE_PROGRAM, sizeof(u->ram.dat) - PAGE_PROGRAM, 1, f);
182 txt_printf("Uxn loaded[%s].\n", filepath);
183 return 1;
184}
185
186Device *
187portuxn(Uxn *u, Uint8 id, char *name, void (*talkfn)(Device *d, Uint8 b0, Uint8 w))
188{
189 Device *d = &u->dev[id];
190 d->addr = id * 0x10;
191 d->u = u;
192 d->mem = u->ram.dat;
193 d->talk = talkfn;
194 txt_printf("Device added #%02x: %s, at 0x%04x \n", id, name, d->addr);
195 return d;
196}
diff --git a/src/uxn/uxn.h b/src/uxn/uxn.h
new file mode 100644
index 0000000..b2c90ac
--- /dev/null
+++ b/src/uxn/uxn.h
@@ -0,0 +1,55 @@
1#ifndef UXNGBA_UXN_H
2#define UXNGBA_UXN_H
3
4#include <stdio.h>
5
6/*
7Copyright (c) 2021 Devine Lu Linvega
8
9Permission to use, copy, modify, and distribute this software for any
10purpose with or without fee is hereby granted, provided that the above
11copyright notice and this permission notice appear in all copies.
12
13THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14WITH REGARD TO THIS SOFTWARE.
15*/
16
17typedef unsigned char Uint8;
18typedef signed char Sint8;
19typedef unsigned short Uint16;
20typedef signed short Sint16;
21
22#define PAGE_PROGRAM 0x0100
23
24typedef struct {
25 Uint8 ptr, kptr, error;
26 Uint8 dat[256];
27} Stack;
28
29typedef struct {
30 Uint16 ptr;
31 Uint8 dat[KB(16)];
32} Memory;
33
34typedef struct Device {
35 struct Uxn *u;
36 Uint8 addr, dat[16], *mem;
37 void (*talk)(struct Device *d, Uint8, Uint8);
38} Device;
39
40typedef struct Uxn {
41 Stack wst, rst, *src, *dst;
42 Memory ram;
43 Device dev[16];
44} Uxn;
45
46struct Uxn;
47
48void mempoke16(Uint8 *m, Uint16 a, Uint16 b);
49Uint16 mempeek16(Uint8 *m, Uint16 a);
50
51int loaduxn(Uxn *c, char *filepath);
52int bootuxn(Uxn *c);
53int evaluxn(Uxn *u, Uint16 vec);
54Device *portuxn(Uxn *u, Uint8 id, char *name, void (*talkfn)(Device *, Uint8, Uint8));
55#endif // UXNGBA_UXN_H