Started migrating examples to new devices setup

This commit is contained in:
neauoire 2021-02-26 16:38:20 -08:00
parent 3c04e1ece1
commit b014a73bcd
12 changed files with 135 additions and 144 deletions

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -1,6 +1,6 @@
( hello world )
&Console { stdio 1 }
&Console { pad 8 stdio 1 }
|0100 @RESET

View File

@ -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

40
examples/dev.screen.usm Normal file
View File

@ -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 )

View File

@ -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 )

View File

@ -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 )

8
uxn.c
View File

@ -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;

6
uxn.h
View File

@ -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));