mirror of https://git.sr.ht/~rabbits/uxn
Redesigned devices
This commit is contained in:
parent
1dbe552f77
commit
56ca1091b4
|
@ -31,7 +31,7 @@ Program p;
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
char ops[][4] = {
|
char ops[][4] = {
|
||||||
"BRK", "LIT", "---", "---", "PEK", "POK", "LDR", "STR",
|
"BRK", "LIT", "---", "---", "IOR", "IOW", "LDR", "STR",
|
||||||
"JMP", "JSR", "RTI", "RTS", "---", "---", "---", "---",
|
"JMP", "JSR", "RTI", "RTS", "---", "---", "---", "---",
|
||||||
"POP", "DUP", "SWP", "OVR", "ROT", "AND", "ORA", "ROL",
|
"POP", "DUP", "SWP", "OVR", "ROT", "AND", "ORA", "ROL",
|
||||||
"ADD", "SUB", "MUL", "DIV", "EQU", "NEQ", "GTH", "LTH"
|
"ADD", "SUB", "MUL", "DIV", "EQU", "NEQ", "GTH", "LTH"
|
||||||
|
|
10
build.sh
10
build.sh
|
@ -8,19 +8,21 @@ clang-format -i assembler.c
|
||||||
rm -f ./bin/assembler
|
rm -f ./bin/assembler
|
||||||
rm -f ./bin/boot.rom
|
rm -f ./bin/boot.rom
|
||||||
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 assembler.c -o bin/assembler
|
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 assembler.c -o bin/assembler
|
||||||
./bin/assembler examples/hello.usm bin/boot.rom
|
|
||||||
|
# Core
|
||||||
|
clang-format -i uxn.h
|
||||||
|
clang-format -i uxn.c
|
||||||
|
|
||||||
# Cli
|
# Cli
|
||||||
clang-format -i cli.c
|
clang-format -i cli.c
|
||||||
clang-format -i uxn.h
|
|
||||||
clang-format -i uxn.c
|
|
||||||
rm -f ./bin/cli
|
rm -f ./bin/cli
|
||||||
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 cli.c -o bin/cli
|
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 cli.c -o bin/cli
|
||||||
|
|
||||||
# Emulator
|
# Emulator
|
||||||
# clang-format -i emulator.c
|
clang-format -i emulator.c
|
||||||
# rm -f ./bin/emulator
|
# 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
|
# 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
|
# run
|
||||||
|
./bin/assembler examples/hello.usm bin/boot.rom
|
||||||
./bin/cli bin/boot.rom
|
./bin/cli bin/boot.rom
|
||||||
|
|
26
cli.c
26
cli.c
|
@ -20,19 +20,19 @@ error(char *msg, const char *err)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Uint8
|
||||||
console_onread(Uint8 *b)
|
console_onread(Uint8 b)
|
||||||
{
|
{
|
||||||
(void)b;
|
(void)b;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Uint8
|
||||||
console_onwrite(Uint8 *b)
|
console_onwrite(Uint8 b)
|
||||||
{
|
{
|
||||||
if(b) {
|
if(b)
|
||||||
printf("%c", *b);
|
printf("%c", b);
|
||||||
*b = 0x00;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -64,7 +64,7 @@ echom(Memory *m, Uint16 len, char *name)
|
||||||
void
|
void
|
||||||
echof(Uxn *c)
|
echof(Uxn *c)
|
||||||
{
|
{
|
||||||
printf("ended @ %d steps | hf: %x sf: %x sf: %x cf: %x\n",
|
printf("\nEnded @ %d steps | hf: %x sf: %x sf: %x cf: %x\n",
|
||||||
c->counter,
|
c->counter,
|
||||||
getflag(&c->status, FLAG_HALT) != 0,
|
getflag(&c->status, FLAG_HALT) != 0,
|
||||||
getflag(&c->status, FLAG_SHORT) != 0,
|
getflag(&c->status, FLAG_SHORT) != 0,
|
||||||
|
@ -82,14 +82,14 @@ main(int argc, char **argv)
|
||||||
return error("Boot", "Failed");
|
return error("Boot", "Failed");
|
||||||
if(!loaduxn(&u, argv[1]))
|
if(!loaduxn(&u, argv[1]))
|
||||||
return error("Load", "Failed");
|
return error("Load", "Failed");
|
||||||
portuxn(&u, 0xfff0, 0xfff1, console_onread, console_onwrite);
|
portuxn(&u, "console", console_onread, console_onwrite);
|
||||||
evaluxn(&u, u.vreset);
|
evaluxn(&u, u.vreset);
|
||||||
evaluxn(&u, u.vframe);
|
evaluxn(&u, u.vframe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
echos(&u.wst, 0x40, "stack");
|
echos(&u.wst, 0x40, "stack");
|
||||||
echom(&u.ram, 0x40, "ram");
|
echom(&u.ram, 0x40, "ram");
|
||||||
echof(&u);
|
|
||||||
*/
|
*/
|
||||||
|
echof(&u);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
27
emulator.c
27
emulator.c
|
@ -150,13 +150,33 @@ dokey(SDL_Event *event)
|
||||||
#pragma mark - Devices
|
#pragma mark - Devices
|
||||||
|
|
||||||
void
|
void
|
||||||
console_onread(void)
|
console_onread(Uint8 *b)
|
||||||
|
{
|
||||||
|
(void)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_onwrite(Uint8 *b)
|
||||||
|
{
|
||||||
|
if(b) {
|
||||||
|
printf("%c", *b);
|
||||||
|
fflush(stdout);
|
||||||
|
*b = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8 ppumem[5];
|
||||||
|
|
||||||
|
void
|
||||||
|
ppur(Uint8 *b)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
console_onwrite(void)
|
ppuw(Uint8 *b)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
printf("%02x\n", *b);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -201,7 +221,8 @@ main(int argc, char **argv)
|
||||||
if(!init())
|
if(!init())
|
||||||
return error("Init", "Failed");
|
return error("Init", "Failed");
|
||||||
|
|
||||||
portuxn(&u, 0xfff0, 0xfff1, console_onread, console_onwrite);
|
portuxn(&u, 0xfff0, console_onread, console_onwrite);
|
||||||
|
portuxn(&u, 0xfff2, ppur, ppuw);
|
||||||
|
|
||||||
start(&u);
|
start(&u);
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
( hello world )
|
( hello world )
|
||||||
|
|
||||||
;iterator
|
;iterator
|
||||||
:dev1r FFF0
|
|
||||||
:dev1w FFF1
|
|
||||||
|
|
||||||
|0100 @RESET
|
|0100 @RESET
|
||||||
|
|
||||||
@word1 "hello_word ( len: 0x0b )
|
@word1 "hello_word ( len: 0x0b )
|
||||||
|
|
||||||
@loop
|
@loop
|
||||||
,dev1w STR ( write to stdout )
|
,00 IOW ( write to device#0 )
|
||||||
,incr JSR ( increment itr )
|
,incr JSR ( increment itr )
|
||||||
,word1 ,strlen JSR ( get strlen )
|
,word1 ,strlen JSR ( get strlen )
|
||||||
NEQ ,loop ROT JSR? ( loop != strlen )
|
NEQ ,loop ROT JSR? ( loop != strlen )
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
( hello world )
|
||||||
|
|
||||||
|
:stdr FFF0
|
||||||
|
:stdw FFF1
|
||||||
|
:ppur FFF2
|
||||||
|
:ppuw FFF3
|
||||||
|
|
||||||
|
|0100 @RESET
|
||||||
|
|
||||||
|
,11 ,ppuw STR ( x0 )
|
||||||
|
,23 ,ppuw STR ( x1 )
|
||||||
|
,12 ,ppuw STR ( y0 )
|
||||||
|
,34 ,ppuw STR ( y1 )
|
||||||
|
,01 ,ppuw STR ( clr )
|
||||||
|
|
||||||
|
BRK
|
||||||
|
|
||||||
|
|c000 @FRAME BRK
|
||||||
|
|d000 @ERROR BRK
|
||||||
|
|FFFA .RESET .FRAME .ERROR
|
|
@ -1,11 +1,15 @@
|
||||||
( my default test file )
|
( my default test file )
|
||||||
|
|
||||||
;iterator
|
;iterator
|
||||||
:dev1r FFF0
|
|
||||||
:dev1w FFF1
|
|
||||||
|
|
||||||
|0100 @RESET
|
|0100 @RESET
|
||||||
,01 ,02 ,03
|
|
||||||
|
,01 ,00 IOW
|
||||||
|
,02 ,00 IOW
|
||||||
|
,03 ,00 IOW
|
||||||
|
,04 ,00 IOW
|
||||||
|
,05 ,00 IOW
|
||||||
|
|
||||||
BRK
|
BRK
|
||||||
|
|
||||||
|c000 @FRAME BRK
|
|c000 @FRAME BRK
|
||||||
|
|
28
uxn.c
28
uxn.c
|
@ -33,8 +33,10 @@ Uint16 mempeek16(Uxn *u, Uint16 s) { return (u->ram.dat[s] << 8) + (u->ram.dat[s
|
||||||
void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
|
void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
|
||||||
void op_lit(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
|
void op_lit(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
|
||||||
void op_nop(Uxn *u) { printf("NOP"); (void)u; }
|
void op_nop(Uxn *u) { printf("NOP"); (void)u; }
|
||||||
void op_ldr(Uxn *u) { wspush8(u, u->ram.dat[wspop16(u)]); }
|
void op_ior(Uxn *u) { Uint8 devid = wspop8(u); Uint8 devop = wspop8(u); Device *dev = &u->dev[devid]; if(dev) wspush8(u, dev->rfn(devop)); }
|
||||||
void op_str(Uxn *u) { u->ram.dat[wspop16(u)] = wspop8(u); }
|
void op_iow(Uxn *u) { Uint8 devid = wspop8(u); Uint8 devop = wspop8(u); Device *dev = &u->dev[devid]; if(dev) dev->wfn(devop); }
|
||||||
|
void op_ldr(Uxn *u) { Uint16 a = wspop16(u); wspush8(u, u->ram.dat[a]); }
|
||||||
|
void op_str(Uxn *u) { Uint16 a = wspop16(u); Uint8 b = wspop8(u); u->ram.dat[a] = b; }
|
||||||
/* Logic */
|
/* Logic */
|
||||||
void op_jmp(Uxn *u) { u->ram.ptr = wspop16(u); }
|
void op_jmp(Uxn *u) { u->ram.ptr = wspop16(u); }
|
||||||
void op_jsr(Uxn *u) { u->rst.dat[u->rst.ptr++] = u->ram.ptr; u->ram.ptr = wspop16(u); }
|
void op_jsr(Uxn *u) { u->rst.dat[u->rst.ptr++] = u->ram.ptr; u->ram.ptr = wspop16(u); }
|
||||||
|
@ -77,7 +79,7 @@ void op_gth16(Uxn *u) { Uint16 a = wspop16(u), b = wspop16(u); wspush8(u, b > a)
|
||||||
void op_lth16(Uxn *u) { Uint16 a = wspop16(u), b = wspop16(u); wspush8(u, b < a); }
|
void op_lth16(Uxn *u) { Uint16 a = wspop16(u), b = wspop16(u); wspush8(u, b < a); }
|
||||||
|
|
||||||
void (*ops[])(Uxn *u) = {
|
void (*ops[])(Uxn *u) = {
|
||||||
op_brk, op_lit, op_nop, op_nop, op_nop, op_nop, op_ldr, op_str,
|
op_brk, op_lit, op_nop, op_nop, op_ior, op_iow, op_ldr, op_str,
|
||||||
op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop,
|
op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop,
|
||||||
op_pop, op_dup, op_swp, op_ovr, op_rot, op_and, op_ora, op_rol,
|
op_pop, op_dup, op_swp, op_ovr, op_rot, op_and, op_ora, op_rol,
|
||||||
op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth,
|
op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth,
|
||||||
|
@ -86,7 +88,7 @@ void (*ops[])(Uxn *u) = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Uint8 opr[][2] = {
|
Uint8 opr[][2] = {
|
||||||
{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {3,0},
|
{0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {2,0}, {2,1}, {3,0},
|
||||||
{2,0}, {2,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
|
{2,0}, {2,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
|
||||||
{1,0}, {1,2}, {2,2}, {3,3}, {3,3}, {2,1}, {2,1}, {2,1},
|
{1,0}, {1,2}, {2,2}, {3,3}, {3,3}, {2,1}, {2,1}, {2,1},
|
||||||
{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1},
|
{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1},
|
||||||
|
@ -113,17 +115,6 @@ lituxn(Uxn *u, Uint8 instr)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
devuxn(Uxn *u)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < u->devices; ++i) {
|
|
||||||
u->dev[i].wfn(&u->ram.dat[u->dev[i].w]);
|
|
||||||
u->dev[i].rfn(&u->ram.dat[u->dev[i].r]);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
opcuxn(Uxn *u, Uint8 instr)
|
opcuxn(Uxn *u, Uint8 instr)
|
||||||
{
|
{
|
||||||
|
@ -139,7 +130,6 @@ opcuxn(Uxn *u, Uint8 instr)
|
||||||
return haltuxn(u, "Stack overflow", instr);
|
return haltuxn(u, "Stack overflow", instr);
|
||||||
if(!getflag(&u->status, FLAG_COND) || (getflag(&u->status, FLAG_COND) && wspop8(u)))
|
if(!getflag(&u->status, FLAG_COND) || (getflag(&u->status, FLAG_COND) && wspop8(u)))
|
||||||
(*ops[op])(u);
|
(*ops[op])(u);
|
||||||
devuxn(u);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,13 +187,11 @@ loaduxn(Uxn *u, char *filepath)
|
||||||
/* to start: evaluxn(u, u->vreset); */
|
/* to start: evaluxn(u, u->vreset); */
|
||||||
|
|
||||||
int
|
int
|
||||||
portuxn(Uxn *u, Uint16 r, Uint16 w, void (*onread)(Uint8 *), void (*onwrite)(Uint8 *))
|
portuxn(Uxn *u, char *name, Uint8 (*onread)(Uint8), Uint8 (*onwrite)(Uint8))
|
||||||
{
|
{
|
||||||
Device *d = &u->dev[u->devices++];
|
Device *d = &u->dev[u->devices++];
|
||||||
d->r = r;
|
|
||||||
d->w = w;
|
|
||||||
d->rfn = onread;
|
d->rfn = onread;
|
||||||
d->wfn = onwrite;
|
d->wfn = onwrite;
|
||||||
printf("Created device: #%d, at r:%04x w:%04x\n", u->devices, r, w);
|
printf("Device#%d: %s \n", u->devices, name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
10
uxn.h
10
uxn.h
|
@ -35,9 +35,9 @@ typedef struct {
|
||||||
} Memory;
|
} Memory;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Uint16 r, w;
|
Uint16 index;
|
||||||
void (*rfn)(Uint8 *);
|
Uint8 (*rfn)(Uint8);
|
||||||
void (*wfn)(Uint8 *);
|
Uint8 (*wfn)(Uint8);
|
||||||
} Device;
|
} Device;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -46,7 +46,7 @@ typedef struct {
|
||||||
Stack8 wst;
|
Stack8 wst;
|
||||||
Stack16 rst;
|
Stack16 rst;
|
||||||
Memory ram;
|
Memory ram;
|
||||||
Device dev[64];
|
Device dev[256];
|
||||||
} Uxn;
|
} Uxn;
|
||||||
|
|
||||||
void setflag(Uint8 *status, char flag, int b);
|
void setflag(Uint8 *status, char flag, int b);
|
||||||
|
@ -54,4 +54,4 @@ int getflag(Uint8 *status, char flag);
|
||||||
int loaduxn(Uxn *c, char *filepath);
|
int loaduxn(Uxn *c, char *filepath);
|
||||||
int bootuxn(Uxn *c);
|
int bootuxn(Uxn *c);
|
||||||
int evaluxn(Uxn *u, Uint16 vec);
|
int evaluxn(Uxn *u, Uint16 vec);
|
||||||
int portuxn(Uxn *u, Uint16 r, Uint16 w, void (*onread)(Uint8 *), void (*onwrite)(Uint8 *));
|
int portuxn(Uxn *u, char *name, Uint8 (*onread)(Uint8), Uint8 (*onwrite)(Uint8));
|
||||||
|
|
Loading…
Reference in New Issue