diff --git a/build.sh b/build.sh index 54028c9..a7b2e56 100755 --- a/build.sh +++ b/build.sh @@ -20,5 +20,5 @@ cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werr # cc uxn.c emulator.c -std=c89 -Os -DNDEBUG -g0 -s -Wall -Wno-unknown-pragmas -L/usr/local/lib -lSDL2 -o bin/emulator # run -./bin/assembler examples/gui.shapes.usm bin/boot.rom +./bin/assembler examples/dev.mouse.usm bin/boot.rom ./bin/emulator bin/boot.rom diff --git a/emulator.c b/emulator.c index c8e858b..8dc56fe 100644 --- a/emulator.c +++ b/emulator.c @@ -253,30 +253,31 @@ init(void) } void -domouse(SDL_Event *event) +domouse(Uxn *u, SDL_Event *event) { Uint8 flag = 0x00; + Uint16 addr = 0xff50; /* TODO: get dynamically */ Uint16 x = clamp(event->motion.x / ZOOM - PAD * 8, 0, HOR * 8 - 1); Uint16 y = clamp(event->motion.y / ZOOM - PAD * 8, 0, VER * 8 - 1); - devmouse->mem[0] = (x >> 8) & 0xff; - devmouse->mem[1] = x & 0xff; - devmouse->mem[2] = (y >> 8) & 0xff; - devmouse->mem[3] = y & 0xff; - devmouse->mem[5] = 0x00; + u->ram.dat[addr + 0] = (x >> 8) & 0xff; + u->ram.dat[addr + 1] = x & 0xff; + u->ram.dat[addr + 2] = (y >> 8) & 0xff; + u->ram.dat[addr + 3] = y & 0xff; + u->ram.dat[addr + 5] = 0x00; switch(event->button.button) { case SDL_BUTTON_LEFT: flag = 0x01; break; case SDL_BUTTON_RIGHT: flag = 0x10; break; } switch(event->type) { case SDL_MOUSEBUTTONUP: - setflag(&devmouse->mem[4], flag, 0); + setflag(&u->ram.dat[addr + 4], flag, 0); break; case SDL_MOUSEBUTTONDOWN: - setflag(&devmouse->mem[4], flag, 1); - if(flag == 0x01 && getflag(&devmouse->mem[4], 0x10)) - devmouse->mem[5] = 0x01; - if(flag == 0x10 && getflag(&devmouse->mem[4], 0x01)) - devmouse->mem[5] = 0x10; + setflag(&u->ram.dat[addr + 4], flag, 1); + if(flag == 0x01 && getflag(&u->ram.dat[addr + 4], 0x10)) + u->ram.dat[addr + 5] = 0x01; + if(flag == 0x10 && getflag(&u->ram.dat[addr + 4], 0x01)) + u->ram.dat[addr + 5] = 0x10; break; } } @@ -325,19 +326,23 @@ doctrl(SDL_Event *event, int z) #pragma mark - Devices Uint8 -console_poke(Uint8 *m, Uint8 b0, Uint8 b1) +console_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1) { printf("%c", b1); fflush(stdout); + (void)m; + (void)ptr; + (void)b0; return b1; } Uint8 -screen_poke(Uint8 *m, Uint8 b0, Uint8 b1) +screen_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1) { - if(b0 == 0x04) { - Uint16 x = (*(m + 2) << 8) + *(m + 3); - Uint16 y = (*m << 8) + *(m + 1); + ptr += 8; + if(b0 == 0x0c) { + Uint16 x = (m[ptr] << 8) + m[ptr + 1]; + Uint16 y = (m[ptr + 2] << 8) + m[ptr + 3]; paintpixel(b1 >> 4 & 0xf ? screen.fg : screen.bg, x, y, b1 & 0xf); screen.reqdraw = 1; } @@ -345,16 +350,30 @@ screen_poke(Uint8 *m, Uint8 b0, Uint8 b1) } Uint8 -peek1(Uint8 *m, Uint8 b0, Uint8 b1) +sprite_poke(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1) { - printf("PEEK! %02x\n", b1); + ptr += 8; + if(b0 == 0x0e) { + Uint16 x = (m[ptr] << 8) + m[ptr + 1]; + Uint16 y = (m[ptr + 2] << 8) + m[ptr + 3]; + Uint16 a = (m[ptr + 4] << 8) + m[ptr + 5]; + Uint8 source = (b1 >> 4) & 0xf; + Uint8 *layer = source % 2 ? screen.fg : screen.bg; + if(source / 2) + paintchr(layer, x, y, &m[a]); + else + painticn(layer, x, y, &m[a], b1 & 0xf); + screen.reqdraw = 1; + } return b1; } Uint8 -poke1(Uint8 *m, Uint8 b0, Uint8 b1) +ppnil(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1) { - printf("POKE! %02x\n", b1); + (void)m; + (void)ptr; + (void)b0; return b1; } @@ -376,37 +395,6 @@ consolew(Device *d, Memory *m, Uint8 b) return 0; } -Uint8 -screenr(Device *d, Memory *m, Uint8 b) -{ - loadtheme(m->dat + 0xfff0); - switch(b) { - case 0: return (HOR * 8 >> 8) & 0xff; - case 1: return HOR * 8 & 0xff; - case 2: return (VER * 8 >> 8) & 0xff; - case 3: return VER * 8 & 0xff; - } - (void)m; - return d->mem[b]; -} - -Uint8 -screenw(Device *d, Memory *m, Uint8 b) -{ - d->mem[d->ptr++] = b; - if(d->ptr > 4) { - Uint16 x = (d->mem[2] << 8) + d->mem[3]; - Uint16 y = (d->mem[0] << 8) + d->mem[1]; - Uint8 clr = d->mem[4] & 0xf; - Uint8 layer = d->mem[4] >> 4 & 0xf; - paintpixel(layer ? screen.fg : screen.bg, x, y, clr); - screen.reqdraw = 1; - d->ptr = 0; - } - (void)m; - return 0; -} - Uint8 spritew(Device *d, Memory *m, Uint8 b) { @@ -449,7 +437,7 @@ start(Uxn *u) case SDL_QUIT: quit(); break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEMOTION: domouse(&event); break; + case SDL_MOUSEMOTION: domouse(u, &event); break; case SDL_TEXTINPUT: dotext(&event); break; case SDL_KEYDOWN: doctrl(&event, 1); break; case SDL_KEYUP: doctrl(&event, 0); break; @@ -479,12 +467,17 @@ main(int argc, char **argv) if(!init()) return error("Init", "Failed"); - devconsole = portuxn(&u, "console", defaultrw, consolew, peek1, console_poke); - devscreen = portuxn(&u, "screen", screenr, screenw, peek1, screen_poke); - devsprite = portuxn(&u, "sprite", screenr, spritew, peek1, poke1); - devcontroller = portuxn(&u, "controller", defaultrw, defaultrw, peek1, poke1); - devkey = portuxn(&u, "key", defaultrw, consolew, peek1, poke1); - devmouse = portuxn(&u, "mouse", defaultrw, defaultrw, peek1, poke1); + devconsole = portuxn(&u, "console", defaultrw, consolew, ppnil, console_poke); + devscreen = portuxn(&u, "screen", defaultrw, defaultrw, ppnil, screen_poke); + devsprite = portuxn(&u, "sprite", defaultrw, spritew, ppnil, sprite_poke); + devcontroller = portuxn(&u, "controller", defaultrw, defaultrw, ppnil, ppnil); + devkey = portuxn(&u, "key", defaultrw, consolew, ppnil, ppnil); + devmouse = portuxn(&u, "mouse", defaultrw, defaultrw, ppnil, ppnil); + + u.ram.dat[0xff10] = (HOR * 8 >> 8) & 0xff; + u.ram.dat[0xff11] = HOR * 8 & 0xff; + u.ram.dat[0xff12] = (VER * 8 >> 8) & 0xff; + u.ram.dat[0xff13] = VER * 8 & 0xff; start(&u); quit(); diff --git a/examples/blank.usm b/examples/blank.usm index 7d679c2..98d5540 100644 --- a/examples/blank.usm +++ b/examples/blank.usm @@ -1,11 +1,18 @@ ( blank ) -:dev/r fff8 ( std read port ) -:dev/w fff9 ( std write port ) +&Console { pad 8 stdio 1 } +&Screen { width 2 height 2 pad 4 y 2 x 2 color 1 } +&Sprite { pad 8 y 2 x 2 addr 2 color 1 } +&Mouse { x 2 y 2 state 1 chord 1 } |0100 @RESET BRK |c000 @FRAME BRK |d000 @ERROR BRK +|FF00 ;dev/console Console +|FF10 ;dev/screen Screen +|FF20 ;dev/sprite Sprite +|FF50 ;dev/mouse Mouse + |FFF0 [ f2ac 35bb 2b53 ] ( palette ) |FFFA .RESET .FRAME .ERROR diff --git a/examples/devchord.usm b/examples/dev.chord.usm similarity index 100% rename from examples/devchord.usm rename to examples/dev.chord.usm diff --git a/examples/devconsole.usm b/examples/dev.console.usm similarity index 91% rename from examples/devconsole.usm rename to examples/dev.console.usm index 675c1ce..cc057b7 100644 --- a/examples/devconsole.usm +++ b/examples/dev.console.usm @@ -1,6 +1,6 @@ ( hello world ) -&Console { stdio 1 } +&Console { pad 8 stdio 1 } |0100 @RESET diff --git a/examples/devmouse.usm b/examples/dev.mouse.usm similarity index 83% rename from examples/devmouse.usm rename to examples/dev.mouse.usm index ed77f3b..ded4cad 100644 --- a/examples/devmouse.usm +++ b/examples/dev.mouse.usm @@ -1,45 +1,37 @@ ( mouse ) -:dev/r fff8 ( std read port ) -:dev/w fff9 ( std write port ) +&Screen { width 2 height 2 pad 4 y 2 x 2 color 1 } +&Sprite { pad 8 y 2 x 2 addr 2 color 1 } +&Mouse { x 2 y 2 state 1 chord 1 } &Point2d { x 2 y 2 } -;mouse Point2d -;cat Point2d +;cat Point2d ;mouse Point2d -;state 1 ;timer 1 +;timer 1 |0100 @RESET - - #01 =dev/r ( set dev/read screen ) ( position cat ) - #00 IOR2 #0002 DIV2 =cat.x - #02 IOR2 #0038 SUB2 =cat.y - - #05 =dev/r ( set dev/read mouse ) - #02 =dev/w ( set dev/write to sprite ) - + ~dev/screen.width #0002 DIV2 =cat.x + ~dev/screen.height #0038 SUB2 =cat.y ( draw polycat ) ,draw-polycat JSR BRK |c000 @FRAME - + ( clear last cursor ) #10 ,clear_icn ~mouse.x ~mouse.y ,draw-sprite JSR ( record mouse positions ) - #00 IOR2 =mouse.x #02 IOR2 =mouse.y - ( record mouse state ) - #04 IOR #11 ADD =state + ~dev/mouse.x =mouse.x ~dev/mouse.y =mouse.y ( detect click ) - #04 IOR #01 NEQ ,no-click ROT JMP? POP2 + ~dev/mouse.state #01 NEQ ,no-click ROT JMP? POP2 #50 =timer @no-click ( draw mouse ) - ~state ,cursor_icn ~mouse.x ~mouse.y ,draw-sprite JSR + ~dev/mouse.state #11 ADD ,cursor_icn ~mouse.x ~mouse.y ,draw-sprite JSR ( animate ) ,animate-polycat JSR ( update last pos ) @@ -99,17 +91,17 @@ RTS RTS @draw-sprite - IOW2 ( y byte ) - IOW2 ( x byte ) - IOW2 ( sprite address ) - IOW ( layer-color ) + =dev/sprite.x + =dev/sprite.y + =dev/sprite.addr + =dev/sprite.color RTS @draw-sprite-chr - IOW2 ( y byte ) - IOW2 ( x byte ) - IOW2 ( sprite address ) - #20 IOW ( layer-color ) + =dev/sprite.x + =dev/sprite.y + =dev/sprite.addr + #20 =dev/sprite.color RTS @clear_icn [ 0000 0000 0000 0000 ] @@ -132,6 +124,10 @@ RTS c0f0 f0e0 e080 8000 c0f1 faf9 fef8 b000 ] +|FF10 ;dev/screen Screen +|FF20 ;dev/sprite Sprite +|FF50 ;dev/mouse Mouse + |d000 @ERROR BRK |FFF0 [ 0f85 0fd5 0fb5 ] ( palette ) |FFFA .RESET .FRAME .ERROR diff --git a/examples/dev.screen.usm b/examples/dev.screen.usm new file mode 100644 index 0000000..14fe7b1 --- /dev/null +++ b/examples/dev.screen.usm @@ -0,0 +1,40 @@ +( screen ) + +&Screen { width 2 height 2 pad 4 x 2 y 2 color 1 } + +;centerx 2 ;centery 2 ;i 2 + +|0100 @RESET + + ( find screen center ) + ~dev/screen.width #0002 DIV2 =centerx + ~dev/screen.height #0002 DIV2 =centery + + ( draw hor line ) + #0000 =i + ~centery =dev/screen.y + @draw-hor + #03 ~i =dev/screen.x =dev/screen.color + ~i #0002 ADD2 =i ( increment ) + ~i ~dev/screen.width LTH2 ,draw-hor ROT JMP? POP2 + + ( draw ver line ) + #0000 =i + ~centerx =dev/screen.x + @draw-ver + #03 ~i =dev/screen.y =dev/screen.color + ~i #0002 ADD2 =i ( increment ) + ~i ~dev/screen.width LTH2 ,draw-ver ROT JMP? POP2 + + ( draw pixel in the middle ) + #01 ~centerx ~centery =dev/screen.y =dev/screen.x =dev/screen.color + +BRK + +|c000 @FRAME BRK +|d000 @ERROR BRK + +|FF10 ;dev/screen Screen + +|FFF0 [ f0ac f0bb f053 ] ( palette ) +|FFFA .RESET .FRAME .ERROR ( vectors ) diff --git a/examples/devscreen.usm b/examples/devscreen.usm deleted file mode 100644 index 97505d6..0000000 --- a/examples/devscreen.usm +++ /dev/null @@ -1,45 +0,0 @@ -( screen ) - -:dev/r fff8 ( std read port ) -:dev/w fff9 ( std write port ) - -;centerx 2 ;centery 2 ;i 2 - -|0100 @RESET - - ( set read/write to dev/screen ) - #01 DUP =dev/r =dev/w - - ( find screen center ) - #00 IOR2 #0002 DIV2 =centerx - #02 IOR2 #0002 DIV2 =centery - - ( draw hor line ) - #0000 =i - @draw-hor - #03 ~i ~centery ,draw-pixel JSR - ~i #0002 ADD2 =i ( increment ) - ~i #00 IOR2 LTH2 ,draw-hor ROT JMP? POP2 - - ( draw ver line ) - #0000 =i - @draw-ver - #03 ~centerx ~i ,draw-pixel JSR - ~i #0002 ADD2 =i ( increment ) - ~i #02 IOR2 LTH2 ,draw-ver ROT JMP? POP2 - - ( draw pixel in the middle ) - #01 ~centerx ~centery ,draw-pixel JSR - -BRK - -@draw-pixel - IOW2 ( y short ) - IOW2 ( x short ) - IOW ( color byte ) - RTS - -|c000 @FRAME BRK -|d000 @ERROR BRK -|FFF0 [ f0ac f0bb f053 ] ( palette ) -|FFFA .RESET .FRAME .ERROR ( vectors ) diff --git a/examples/blending.usm b/examples/gui.blending.usm similarity index 100% rename from examples/blending.usm rename to examples/gui.blending.usm diff --git a/examples/gui.shapes.usm b/examples/gui.shapes.usm index 881ffd8..15cfd19 100644 --- a/examples/gui.shapes.usm +++ b/examples/gui.shapes.usm @@ -1,6 +1,6 @@ ( draw routines ) -&Screen { y 2 x 2 color 1 } +&Screen { width 2 height 2 pad 4 y 2 x 2 color 1 red 1 green 1 blue 1 } ;color 1 ;x1 2 ;x2 2 ;y1 2 ;y2 2 @@ -53,7 +53,7 @@ RTS |c000 @FRAME BRK |d000 @ERROR BRK -|FF08 ;dev/screen Screen +|FF10 ;dev/screen Screen |FFF0 [ 0f0f 0fff 0ff0 ] ( palette ) |FFFA .RESET .FRAME .ERROR ( vectors ) \ No newline at end of file diff --git a/uxn.c b/uxn.c index d407af5..7690ea3 100644 --- a/uxn.c +++ b/uxn.c @@ -18,9 +18,9 @@ WITH REGARD TO THIS SOFTWARE. /* clang-format off */ void setflag(Uint8 *a, char flag, int b) { if(b) *a |= flag; else *a &= (~flag); } int getflag(Uint8 *a, char flag) { return *a & flag; } -Uint8 devpoke8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].poke(&u->ram.dat[0xff00 + id * 8], b0, b1) : b1; } -Uint8 devpeek8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].peek(&u->ram.dat[0xff00 + id * 8], b0, b1) : b1; } -void mempoke8(Uxn *u, Uint16 a, Uint8 b) { u->ram.dat[a] = a >= 0xff00 ? devpoke8(u, (a & 0xff) >> 3, (a & 0xf) % 8, b) : b; } +Uint8 devpoke8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].poke(u->ram.dat, 0xff00 + id * 0x10, b0, b1) : b1; } +Uint8 devpeek8(Uxn *u, Uint8 id, Uint8 b0, Uint8 b1){ return id < u->devices ? u->dev[id].peek(u->ram.dat, 0xff00 + id * 0x10, b0, b1) : b1; } +void mempoke8(Uxn *u, Uint16 a, Uint8 b) { u->ram.dat[a] = a >= 0xff00 ? devpoke8(u, (a & 0xff) >> 4, a & 0xf, b) : b; } Uint8 mempeek8(Uxn *u, Uint16 a) { return a >= 0xff00 ? devpeek8(u, (a & 0xff) >> 4, a & 0xf, u->ram.dat[a]) : u->ram.dat[a]; } void mempoke16(Uxn *u, Uint16 a, Uint16 b) { mempoke8(u, a, b >> 8); mempoke8(u, a + 1, b); } Uint16 mempeek16(Uxn *u, Uint16 a) { return (mempeek8(u, a) << 8) + mempeek8(u, a + 1); } @@ -211,7 +211,7 @@ loaduxn(Uxn *u, char *filepath) } Device * -portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *m, Uint8 b0, Uint8 b1), Uint8 (*pofn)(Uint8 *m, Uint8 b0, Uint8 b1)) +portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1), Uint8 (*pofn)(Uint8 *m, Uint16 ptr, Uint8 b0, Uint8 b1)) { Device *d = &u->dev[u->devices++]; d->read = rfn; diff --git a/uxn.h b/uxn.h index 1c783f7..e670e38 100644 --- a/uxn.h +++ b/uxn.h @@ -35,8 +35,8 @@ typedef struct Device { Uint8 ptr, mem[8]; Uint8 (*read)(struct Device *, Memory *, Uint8); Uint8 (*write)(struct Device *, Memory *, Uint8); - Uint8 (*peek)(Uint8 *, Uint8, Uint8); - Uint8 (*poke)(Uint8 *, Uint8, Uint8); + Uint8 (*peek)(Uint8 *, Uint16, Uint8, Uint8); + Uint8 (*poke)(Uint8 *, Uint16, Uint8, Uint8); } Device; typedef struct { @@ -52,4 +52,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 *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *, Uint8, Uint8), Uint8 (*pofn)(Uint8 *, Uint8, Uint8)); +Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Memory *, Uint8), Uint8 (*wfn)(Device *, Memory *, Uint8), Uint8 (*pefn)(Uint8 *, Uint16, Uint8, Uint8), Uint8 (*pofn)(Uint8 *, Uint16, Uint8, Uint8));