uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

commit b3ff7af8a382c216502c140c1a77e15734773b83
parent 812148c2916e5aa177bcb91cd0cd761f48a316f9
Author: neauoire <aliceffekt@gmail.com>
Date:   Sun, 14 Feb 2021 10:22:42 -0800

Added chr/icn parser to PPU

Diffstat:
Massembler.c | 8+++++---
Mbuild.sh | 2+-
Memulator.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mexamples/test.usm | 40+++++++++++++++++++++++++++++++++-------
Muxn.c | 10+++++-----
Muxn.h | 6+++---
6 files changed, 116 insertions(+), 36 deletions(-)

diff --git a/assembler.c b/assembler.c @@ -213,8 +213,8 @@ pass1(FILE *f) else { switch(w[0]) { case '|': addr = shex(w + 1); break; - case '.': addr += 2; break; case ',': addr += 3; break; + case '.': addr += (slen(w + 1) == 2 ? 1 : 2); break; case '+': /* signed positive */ case '-': /* signed negative */ case '#': addr += (slen(w + 1) == 2 ? 2 : 3); break; @@ -242,8 +242,10 @@ pass2(FILE *f) else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); else if(w[0] == ':') fscanf(f, "%s", w); else if(w[0] == ';') fscanf(f, "%s", w); - else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w), 1); - else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w), 1); + else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 0); + else if(w[0] == '.' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 0); + else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 2) pushbyte(shex(w + 1), 1); + else if(w[0] == '#' && sihx(w + 1) && slen(w + 1) == 4) pushshort(shex(w + 1), 1); else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)shex(w + 1), 1); else if(w[0] == '+' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)shex(w + 1), 1); else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 2) pushbyte((Sint8)(shex(w + 1) * -1), 1); diff --git a/build.sh b/build.sh @@ -24,5 +24,5 @@ rm -f ./bin/emulator 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 # run -./bin/assembler examples/line.usm bin/boot.rom +./bin/assembler examples/test.usm bin/boot.rom ./bin/emulator bin/boot.rom diff --git a/emulator.c b/emulator.c @@ -37,14 +37,9 @@ SDL_Renderer *gRenderer; SDL_Texture *gTexture; Uint32 *pixels; -Device *devconsole, *devscreen, *devmouse, *devkey; +Device *devconsole, *devscreen, *devmouse, *devkey, *devsprite; -int -error(char *msg, const char *err) -{ - printf("Error %s: %s\n", msg, err); - return 0; -} +#pragma mark - Helpers void clear(Uint32 *dst) @@ -59,7 +54,41 @@ void putpixel(Uint32 *dst, int x, int y, int color) { if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8) - dst[y * WIDTH + x] = theme[color]; + dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color]; +} + +void +drawchr(Uint32 *dst, int x, int y, Uint8 *sprite) +{ + int v, h; + for(v = 0; v < 8; v++) + for(h = 0; h < 8; h++) { + int ch1 = ((sprite[v] >> h) & 0x1); + int ch2 = (((sprite[v + 8] >> h) & 0x1) << 1); + int clr = ch1 + ch2; + int guides = GUIDES && !clr && ((x + y) / 8) % 2; + putpixel(dst, x + 7 - h, y + v, guides ? 4 : clr); + } +} + +void +drawicn(Uint32 *dst, int x, int y, Uint8 *sprite, int fg, int bg) +{ + int v, h; + for(v = 0; v < 8; v++) + for(h = 0; h < 8; h++) { + int ch1 = (sprite[v] >> (7 - h)) & 0x1; + putpixel(dst, x + h, y + v, ch1 ? fg : bg); + } +} + +#pragma mark - Core + +int +error(char *msg, const char *err) +{ + printf("Error %s: %s\n", msg, err); + return 0; } void @@ -170,7 +199,7 @@ dokey(SDL_Event *event) #pragma mark - Devices Uint8 -consoler(Device *d, Uint8 b) +consoler(Device *d, Memory *m, Uint8 b) { (void)b; (void)d; @@ -178,7 +207,7 @@ consoler(Device *d, Uint8 b) } Uint8 -consolew(Device *d, Uint8 b) +consolew(Device *d, Memory *m, Uint8 b) { (void)d; if(b) @@ -188,7 +217,7 @@ consolew(Device *d, Uint8 b) } Uint8 -screenr(Device *d, Uint8 b) +ppur(Device *d, Memory *m, Uint8 b) { switch(b) { case 0: return (WIDTH >> 8) & 0xff; @@ -200,7 +229,7 @@ screenr(Device *d, Uint8 b) } Uint8 -screenw(Device *d, Uint8 b) +ppuw(Device *d, Memory *m, Uint8 b) { d->mem[d->len++] = b; if(d->len > 5) { @@ -216,13 +245,35 @@ screenw(Device *d, Uint8 b) } Uint8 -mouser(Device *d, Uint8 b) +ppusr(Device *d, Memory *m, Uint8 b) +{ + return 0; +} + +Uint8 +ppusw(Device *d, Memory *m, Uint8 b) +{ + d->mem[d->len++] = b; + if(d->len > 6) { + Uint16 x = (d->mem[2] << 8) + d->mem[3]; + Uint16 y = (d->mem[0] << 8) + d->mem[1]; + Uint8 *chr = &m->dat[(d->mem[4] << 8) + d->mem[5]]; + drawchr(pixels, x, y, chr); + if(d->mem[6]) + redraw(pixels); + d->len = 0; + } + return 0; +} + +Uint8 +mouser(Device *d, Memory *m, Uint8 b) { return d->mem[b]; } Uint8 -mousew(Device *d, Uint8 b) +mousew(Device *d, Memory *m, Uint8 b) { (void)d; (void)b; @@ -230,7 +281,7 @@ mousew(Device *d, Uint8 b) } Uint8 -keyr(Device *d, Uint8 b) +keyr(Device *d, Memory *m, Uint8 b) { (void)d; (void)b; @@ -238,7 +289,7 @@ keyr(Device *d, Uint8 b) } Uint8 -keyw(Device *d, Uint8 b) +keyw(Device *d, Memory *m, Uint8 b) { (void)d; (void)b; @@ -295,9 +346,10 @@ main(int argc, char **argv) return error("Init", "Failed"); devconsole = portuxn(&u, "console", consoler, consolew); - devscreen = portuxn(&u, "screen", screenr, screenw); + devscreen = portuxn(&u, "ppu", ppur, ppuw); devmouse = portuxn(&u, "mouse", mouser, mousew); devkey = portuxn(&u, "key", keyr, keyw); + devsprite = portuxn(&u, "ppu-sprite", ppusr, ppusw); start(&u); diff --git a/examples/test.usm b/examples/test.usm @@ -4,16 +4,42 @@ |0100 @RESET - #00 ,dev/w STR ( set dev/write to console ) - ,string ( add string pointer to stack ) - @loop - DUP2 LDR IOW ( write pointer value to console ) - #0001 ADD2 ( increment string pointer ) - DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) + #01 ,dev/w STR ( set dev/write to screen ) + + ( draw 1 pixel ) + #00 #01 #0021 #0021 ,putpixel JSR + + #04 ,dev/w STR ( set dev/write to screen ) + + #00 ,star_icn #0001 #0001 ,putsprite JSR + + #00 ,star_icn #0031 #0021 ,putsprite JSR + #00 ,cursor_icn #0021 #0016 ,putsprite JSR + #00 ,star_icn #0055 #0042 ,putsprite JSR + #01 ,cursor_icn #0067 #0031 ,putsprite JSR BRK -@string " Hello World " ( add string to memory ) +@putsprite + IOW2 ( y short ) + IOW2 ( x short ) + IOW2 ( sprite address ) + IOW ( redraw byte ) + RTS + +@putpixel + IOW2 ( y short ) + IOW2 ( x short ) + IOW ( color byte ) + IOW ( redraw byte ) + RTS + +|0200 @SPRITESHEET + +@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000 +@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000 + +BRK |c000 @FRAME BRK |d000 @ERROR BRK diff --git a/uxn.c b/uxn.c @@ -34,8 +34,8 @@ void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); } void op_lit(Uxn *u) { u->literal += 1; } void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; } void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); } -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))); } -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); } +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))); } +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); } void op_ldr(Uxn *u) { Uint16 a = pop16(&u->wst); push8(&u->wst, mempeek8(&u->ram, a)); } void op_str(Uxn *u) { Uint16 a = pop16(&u->wst); Uint8 b = pop8(&u->wst); mempoke8(&u->ram, a, b); } /* Logic */ @@ -63,8 +63,8 @@ void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, /* --- */ void op_lit16(Uxn *u) { u->literal += 2; } void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); } -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)); } -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); } } +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)); } +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); } } void op_ldr16(Uxn *u) { Uint16 a = pop16(&u->wst); push16(&u->wst, mempeek16(&u->ram, a)); } void op_str16(Uxn *u) { Uint16 a = pop16(&u->wst); Uint16 b = pop16(&u->wst); mempoke16(&u->ram, a, b); } /* Stack(16-bits) */ @@ -202,7 +202,7 @@ loaduxn(Uxn *u, char *filepath) } Device * -portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)) +portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8)) { Device *d = &u->dev[u->devices++]; d->read = rfn; diff --git a/uxn.h b/uxn.h @@ -33,8 +33,8 @@ typedef struct { typedef struct Device { Uint8 len, mem[8]; - Uint8 (*read)(struct Device *, Uint8); - Uint8 (*write)(struct Device *, Uint8); + Uint8 (*read)(struct Device *, Memory *, Uint8); + Uint8 (*write)(struct Device *, Memory *, Uint8); } Device; typedef struct { @@ -50,4 +50,4 @@ int getflag(Uint8 *status, char flag); int loaduxn(Uxn *c, char *filepath); int bootuxn(Uxn *c); int evaluxn(Uxn *u, Uint16 vec); -Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8)); +Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8));