| ... | ... |
@@ -213,8 +213,8 @@ pass1(FILE *f) |
| 213 | 213 |
else {
|
| 214 | 214 |
switch(w[0]) {
|
| 215 | 215 |
case '|': addr = shex(w + 1); break; |
| 216 |
- case '.': addr += 2; break; |
|
| 217 | 216 |
case ',': addr += 3; break; |
| 217 |
+ case '.': addr += (slen(w + 1) == 2 ? 1 : 2); break; |
|
| 218 | 218 |
case '+': /* signed positive */ |
| 219 | 219 |
case '-': /* signed negative */ |
| 220 | 220 |
case '#': addr += (slen(w + 1) == 2 ? 2 : 3); break; |
| ... | ... |
@@ -242,8 +242,10 @@ pass2(FILE *f) |
| 242 | 242 |
else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); |
| 243 | 243 |
else if(w[0] == ':') fscanf(f, "%s", w); |
| 244 | 244 |
else if(w[0] == ';') fscanf(f, "%s", w); |
| 245 |
- else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w), 1); |
|
| 246 |
- else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w), 1); |
|
| 245 |
+ else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 0); |
|
| 246 |
+ else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 0); |
|
| 247 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 1); |
|
| 248 |
+ else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 1); |
|
| 247 | 249 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); |
| 248 | 250 |
else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); |
| 249 | 251 |
else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); |
| ... | ... |
@@ -24,5 +24,5 @@ rm -f ./bin/emulator |
| 24 | 24 |
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c emulator.c -L/usr/local/lib -lSDL2 -o bin/emulator |
| 25 | 25 |
|
| 26 | 26 |
# run |
| 27 |
-./bin/assembler examples/line.usm bin/boot.rom |
|
| 27 |
+./bin/assembler examples/test.usm bin/boot.rom |
|
| 28 | 28 |
./bin/emulator bin/boot.rom |
| ... | ... |
@@ -37,14 +37,9 @@ SDL_Renderer *gRenderer; |
| 37 | 37 |
SDL_Texture *gTexture; |
| 38 | 38 |
Uint32 *pixels; |
| 39 | 39 |
|
| 40 |
-Device *devconsole, *devscreen, *devmouse, *devkey; |
|
| 40 |
+Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite; |
|
| 41 | 41 |
|
| 42 |
-int |
|
| 43 |
-error(char *msg, const char *err) |
|
| 44 |
-{
|
|
| 45 |
- printf("Error %s: %s\n", msg, err);
|
|
| 46 |
- return 0; |
|
| 47 |
-} |
|
| 42 |
+#pragma mark - Helpers |
|
| 48 | 43 |
|
| 49 | 44 |
void |
| 50 | 45 |
clear(Uint32 *dst) |
| ... | ... |
@@ -59,7 +54,41 @@ void |
| 59 | 54 |
putpixel(Uint32 *dst, int x, int y, int color) |
| 60 | 55 |
{
|
| 61 | 56 |
if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8) |
| 62 |
- dst[y * WIDTH + x] = theme[color]; |
|
| 57 |
+ dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color]; |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+void |
|
| 61 |
+drawchr(Uint32 *dst, int x, int y, Uint8 *sprite) |
|
| 62 |
+{
|
|
| 63 |
+ int v, h; |
|
| 64 |
+ for(v = 0; v < 8; v++) |
|
| 65 |
+ for(h = 0; h < 8; h++) {
|
|
| 66 |
+ int ch1 = ((sprite[v] >> h) & 0x1); |
|
| 67 |
+ int ch2 = (((sprite[v + 8] >> h) & 0x1) << 1); |
|
| 68 |
+ int clr = ch1 + ch2; |
|
| 69 |
+ int guides = GUIDES && !clr && ((x + y) / 8) % 2; |
|
| 70 |
+ putpixel(dst, x + 7 - h, y + v, guides ? 4 : clr); |
|
| 71 |
+ } |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 74 |
+void |
|
| 75 |
+drawicn(Uint32 *dst, int x, int y, Uint8 *sprite, int fg, int bg) |
|
| 76 |
+{
|
|
| 77 |
+ int v, h; |
|
| 78 |
+ for(v = 0; v < 8; v++) |
|
| 79 |
+ for(h = 0; h < 8; h++) {
|
|
| 80 |
+ int ch1 = (sprite[v] >> (7 - h)) & 0x1; |
|
| 81 |
+ putpixel(dst, x + h, y + v, ch1 ? fg : bg); |
|
| 82 |
+ } |
|
| 83 |
+} |
|
| 84 |
+ |
|
| 85 |
+#pragma mark - Core |
|
| 86 |
+ |
|
| 87 |
+int |
|
| 88 |
+error(char *msg, const char *err) |
|
| 89 |
+{
|
|
| 90 |
+ printf("Error %s: %s\n", msg, err);
|
|
| 91 |
+ return 0; |
|
| 63 | 92 |
} |
| 64 | 93 |
|
| 65 | 94 |
void |
| ... | ... |
@@ -170,7 +199,7 @@ dokey(SDL_Event *event) |
| 170 | 199 |
#pragma mark - Devices |
| 171 | 200 |
|
| 172 | 201 |
Uint8 |
| 173 |
-consoler(Device *d, Uint8 b) |
|
| 202 |
+consoler(Device *d, Memory *m, Uint8 b) |
|
| 174 | 203 |
{
|
| 175 | 204 |
(void)b; |
| 176 | 205 |
(void)d; |
| ... | ... |
@@ -178,7 +207,7 @@ consoler(Device *d, Uint8 b) |
| 178 | 207 |
} |
| 179 | 208 |
|
| 180 | 209 |
Uint8 |
| 181 |
-consolew(Device *d, Uint8 b) |
|
| 210 |
+consolew(Device *d, Memory *m, Uint8 b) |
|
| 182 | 211 |
{
|
| 183 | 212 |
(void)d; |
| 184 | 213 |
if(b) |
| ... | ... |
@@ -188,7 +217,7 @@ consolew(Device *d, Uint8 b) |
| 188 | 217 |
} |
| 189 | 218 |
|
| 190 | 219 |
Uint8 |
| 191 |
-screenr(Device *d, Uint8 b) |
|
| 220 |
+ppur(Device *d, Memory *m, Uint8 b) |
|
| 192 | 221 |
{
|
| 193 | 222 |
switch(b) {
|
| 194 | 223 |
case 0: return (WIDTH >> 8) & 0xff; |
| ... | ... |
@@ -200,7 +229,7 @@ screenr(Device *d, Uint8 b) |
| 200 | 229 |
} |
| 201 | 230 |
|
| 202 | 231 |
Uint8 |
| 203 |
-screenw(Device *d, Uint8 b) |
|
| 232 |
+ppuw(Device *d, Memory *m, Uint8 b) |
|
| 204 | 233 |
{
|
| 205 | 234 |
d->mem[d->len++] = b; |
| 206 | 235 |
if(d->len > 5) {
|
| ... | ... |
@@ -216,13 +245,35 @@ screenw(Device *d, Uint8 b) |
| 216 | 245 |
} |
| 217 | 246 |
|
| 218 | 247 |
Uint8 |
| 219 |
-mouser(Device *d, Uint8 b) |
|
| 248 |
+ppusr(Device *d, Memory *m, Uint8 b) |
|
| 249 |
+{
|
|
| 250 |
+ return 0; |
|
| 251 |
+} |
|
| 252 |
+ |
|
| 253 |
+Uint8 |
|
| 254 |
+ppusw(Device *d, Memory *m, Uint8 b) |
|
| 255 |
+{
|
|
| 256 |
+ d->mem[d->len++] = b; |
|
| 257 |
+ if(d->len > 6) {
|
|
| 258 |
+ Uint16 x = (d->mem[2] << 8) + d->mem[3]; |
|
| 259 |
+ Uint16 y = (d->mem[0] << 8) + d->mem[1]; |
|
| 260 |
+ Uint8 *chr = &m->dat[(d->mem[4] << 8) + d->mem[5]]; |
|
| 261 |
+ drawchr(pixels, x, y, chr); |
|
| 262 |
+ if(d->mem[6]) |
|
| 263 |
+ redraw(pixels); |
|
| 264 |
+ d->len = 0; |
|
| 265 |
+ } |
|
| 266 |
+ return 0; |
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+Uint8 |
|
| 270 |
+mouser(Device *d, Memory *m, Uint8 b) |
|
| 220 | 271 |
{
|
| 221 | 272 |
return d->mem[b]; |
| 222 | 273 |
} |
| 223 | 274 |
|
| 224 | 275 |
Uint8 |
| 225 |
-mousew(Device *d, Uint8 b) |
|
| 276 |
+mousew(Device *d, Memory *m, Uint8 b) |
|
| 226 | 277 |
{
|
| 227 | 278 |
(void)d; |
| 228 | 279 |
(void)b; |
| ... | ... |
@@ -230,7 +281,7 @@ mousew(Device *d, Uint8 b) |
| 230 | 281 |
} |
| 231 | 282 |
|
| 232 | 283 |
Uint8 |
| 233 |
-keyr(Device *d, Uint8 b) |
|
| 284 |
+keyr(Device *d, Memory *m, Uint8 b) |
|
| 234 | 285 |
{
|
| 235 | 286 |
(void)d; |
| 236 | 287 |
(void)b; |
| ... | ... |
@@ -238,7 +289,7 @@ keyr(Device *d, Uint8 b) |
| 238 | 289 |
} |
| 239 | 290 |
|
| 240 | 291 |
Uint8 |
| 241 |
-keyw(Device *d, Uint8 b) |
|
| 292 |
+keyw(Device *d, Memory *m, Uint8 b) |
|
| 242 | 293 |
{
|
| 243 | 294 |
(void)d; |
| 244 | 295 |
(void)b; |
| ... | ... |
@@ -295,9 +346,10 @@ main(int argc, char **argv) |
| 295 | 346 |
return error("Init", "Failed");
|
| 296 | 347 |
|
| 297 | 348 |
devconsole = portuxn(&u, "console", consoler, consolew); |
| 298 |
- devscreen = portuxn(&u, "screen", screenr, screenw); |
|
| 349 |
+ devscreen = portuxn(&u, "ppu", ppur, ppuw); |
|
| 299 | 350 |
devmouse = portuxn(&u, "mouse", mouser, mousew); |
| 300 | 351 |
devkey = portuxn(&u, "key", keyr, keyw); |
| 352 |
+ devsprite = portuxn(&u, "ppu-sprite", ppusr, ppusw); |
|
| 301 | 353 |
|
| 302 | 354 |
start(&u); |
| 303 | 355 |
|
| ... | ... |
@@ -4,16 +4,42 @@ |
| 4 | 4 |
|
| 5 | 5 |
|0100 @RESET |
| 6 | 6 |
|
| 7 |
- #00 ,dev/w STR ( set dev/write to console ) |
|
| 8 |
- ,string ( add string pointer to stack ) |
|
| 9 |
- @loop |
|
| 10 |
- DUP2 LDR IOW ( write pointer value to console ) |
|
| 11 |
- #0001 ADD2 ( increment string pointer ) |
|
| 12 |
- DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) |
|
| 7 |
+ #01 ,dev/w STR ( set dev/write to screen ) |
|
| 8 |
+ |
|
| 9 |
+ ( draw 1 pixel ) |
|
| 10 |
+ #00 #01 #0021 #0021 ,putpixel JSR |
|
| 11 |
+ |
|
| 12 |
+ #04 ,dev/w STR ( set dev/write to screen ) |
|
| 13 |
+ |
|
| 14 |
+ #00 ,star_icn #0001 #0001 ,putsprite JSR |
|
| 15 |
+ |
|
| 16 |
+ #00 ,star_icn #0031 #0021 ,putsprite JSR |
|
| 17 |
+ #00 ,cursor_icn #0021 #0016 ,putsprite JSR |
|
| 18 |
+ #00 ,star_icn #0055 #0042 ,putsprite JSR |
|
| 19 |
+ #01 ,cursor_icn #0067 #0031 ,putsprite JSR |
|
| 13 | 20 |
|
| 14 | 21 |
BRK |
| 15 | 22 |
|
| 16 |
-@string " Hello World " ( add string to memory ) |
|
| 23 |
+@putsprite |
|
| 24 |
+ IOW2 ( y short ) |
|
| 25 |
+ IOW2 ( x short ) |
|
| 26 |
+ IOW2 ( sprite address ) |
|
| 27 |
+ IOW ( redraw byte ) |
|
| 28 |
+ RTS |
|
| 29 |
+ |
|
| 30 |
+@putpixel |
|
| 31 |
+ IOW2 ( y short ) |
|
| 32 |
+ IOW2 ( x short ) |
|
| 33 |
+ IOW ( color byte ) |
|
| 34 |
+ IOW ( redraw byte ) |
|
| 35 |
+ RTS |
|
| 36 |
+ |
|
| 37 |
+|0200 @SPRITESHEET |
|
| 38 |
+ |
|
| 39 |
+@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 |
|
| 40 |
+@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 |
|
| 41 |
+ |
|
| 42 |
+BRK |
|
| 17 | 43 |
|
| 18 | 44 |
|c000 @FRAME BRK |
| 19 | 45 |
|d000 @ERROR BRK |
| ... | ... |
@@ -34,8 +34,8 @@ void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
|
| 34 | 34 |
void op_lit(Uxn *u) { u->literal += 1; }
|
| 35 | 35 |
void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
|
| 36 | 36 |
void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); }
|
| 37 |
-void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, pop8(&u->wst))); }
|
|
| 38 |
-void op_iow(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) dev->write(dev, a); }
|
|
| 37 |
+void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, &u->ram, pop8(&u->wst))); }
|
|
| 38 |
+void op_iow(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) dev->write(dev, &u->ram, a); }
|
|
| 39 | 39 |
void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(&u->ram, a)); }
|
| 40 | 40 |
void op_str(Uxn *u) { Uint16 a = pop16(&u->wst); Uint8 b = pop8(&u->wst); mempoke8(&u->ram, a, b); }
|
| 41 | 41 |
/* Logic */ |
| ... | ... |
@@ -63,8 +63,8 @@ void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst,
|
| 63 | 63 |
/* --- */ |
| 64 | 64 |
void op_lit16(Uxn *u) { u->literal += 2; }
|
| 65 | 65 |
void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); }
|
| 66 |
-void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, a) << 8) + dev->read(dev, a + 1)); }
|
|
| 67 |
-void op_iow16(Uxn *u) { Uint8 a = pop8(&u->wst); Uint8 b = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) { dev->write(dev, b); dev->write(dev, a); } }
|
|
| 66 |
+void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, &u->ram, a) << 8) + dev->read(dev, &u->ram, a + 1)); }
|
|
| 67 |
+void op_iow16(Uxn *u) { Uint8 a = pop8(&u->wst); Uint8 b = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) { dev->write(dev, &u->ram, b); dev->write(dev, &u->ram, a); } }
|
|
| 68 | 68 |
void op_ldr16(Uxn *u) { Uint16 a = pop16(&u->wst); push16(&u->wst, mempeek16(&u->ram, a)); }
|
| 69 | 69 |
void op_str16(Uxn *u) { Uint16 a = pop16(&u->wst); Uint16 b = pop16(&u->wst); mempoke16(&u->ram, a, b); }
|
| 70 | 70 |
/* Stack(16-bits) */ |
| ... | ... |
@@ -202,7 +202,7 @@ loaduxn(Uxn *u, char *filepath) |
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
Device * |
| 205 |
-portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)) |
|
| 205 |
+portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8)) |
|
| 206 | 206 |
{
|
| 207 | 207 |
Device *d = &u->dev[u->devices++]; |
| 208 | 208 |
d->read = rfn; |
| ... | ... |
@@ -33,8 +33,8 @@ typedef struct {
|
| 33 | 33 |
|
| 34 | 34 |
typedef struct Device {
|
| 35 | 35 |
Uint8 len, mem[8]; |
| 36 |
- Uint8 (*read)(struct Device *, Uint8); |
|
| 37 |
- Uint8 (*write)(struct Device *, Uint8); |
|
| 36 |
+ Uint8 (*read)(struct Device *, Memory *, Uint8); |
|
| 37 |
+ Uint8 (*write)(struct Device *, Memory *, Uint8); |
|
| 38 | 38 |
} Device; |
| 39 | 39 |
|
| 40 | 40 |
typedef struct {
|
| ... | ... |
@@ -50,4 +50,4 @@ int getflag(Uint8 *status, char flag); |
| 50 | 50 |
int loaduxn(Uxn *c, char *filepath); |
| 51 | 51 |
int bootuxn(Uxn *c); |
| 52 | 52 |
int evaluxn(Uxn *u, Uint16 vec); |
| 53 |
-Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)); |
|
| 53 |
+Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8)); |