commit 256d72e340e01ecc2a329c81f081620dab08de11
parent 1cc7abea54148a693120e1755866b1828f7292b6
Author: neauoire <aliceffekt@gmail.com>
Date: Sun, 14 Feb 2021 17:00:17 -0800
Added helper for LDR/STR
Diffstat:
12 files changed, 92 insertions(+), 119 deletions(-)
diff --git a/README.md b/README.md
@@ -30,11 +30,6 @@ evaluxn(u, u->vframe); /* Each frame
- `;variable 2`, assign an address to a label automatically.
- `:const 1a2b`, assign an address to a label manually.
-### Read
-
-- `,literal`, push label value to stack, prefixed with `LIT LEN`.
-- `.pointer`, push label value to stack.
-
### Write
- `ADD`, an opcode.
@@ -46,18 +41,22 @@ evaluxn(u, u->vframe); /* Each frame
- `-12ef`, a literal signed short(negative).
- `.ab`, a raw byte in memory.
- `.abcd`, a raw short in memory.
+- `,literal`, push label address to stack, prefixed with `LIT LEN`.
### Special
- `( comment )`, toggle parsing on/off.
- `|0010`, move to position in the program.
- `"hello`, push literal bytes for word "hello".
+- `=label`, helper to STR, equivalent to `,label STR`, or `label STR2`.
+- `~label`, helper to LDR, equivalent to `,label LDR2`, or `,label LDR2`.
### Operator modes
- `#1234 #0001 ADD2`, 16-bits operators have the short flag `2`.
- `#12 #11 GTH JMP?`, conditional operators have the cond flag `?`.
- `+21 -03 MULS`, signed operators have the cond flag `S`.
+- `ADDS2?`, modes can be combined.
```
( comment )
@@ -66,8 +65,7 @@ evaluxn(u, u->vframe); /* Each frame
|0100 @RESET
- #00 ,dev/w STR ( set dev/write to console )
- ,string ( add string pointer to stack )
+ ,string ( add string pointer to stack )
@loop
DUP2 LDR IOW ( write pointer value to console )
#0001 ADD2 ( increment string pointer )
@@ -75,7 +73,7 @@ evaluxn(u, u->vframe); /* Each frame
BRK
-@string " Hello World " ( add string to memory )
+@string " Hello World " ( add string to memory )
|c000 @FRAME BRK
|d000 @ERROR BRK
@@ -89,28 +87,28 @@ BRK
A device that works like a NES controller, each button is a bit from a single byte.
-- Ctrl
-- Alt
-- Escape
-- Return
-- Up
-- Down
-- Left
-- Right
+- `0x01` Ctrl
+- `0x02` Alt
+- `0x04` Escape
+- `0x08` Return
+- `0x10` Up
+- `0x20` Down
+- `0x40` Left
+- `0x80` Right
## TODOs
-- Defines?
- LDR/STR helpers
-- Keyboard example
-- PPU chr device
- Line routine
- On-screen debugger.
-- Auto-advance ldr?
- Getting rid of IOR/IOW would be nice..
-- Sending from the wst to the rst, balance mode/flag?
-- Device that works like an extra memory bank
-- [debug]Print unused labels
+- Sending from the wst to the rst, balance counter?
+
+### Misc TODOs
+
+- Includes
+- Defines
+- Lint, print unused labels
## Refs
diff --git a/assembler.c b/assembler.c
@@ -22,6 +22,7 @@ typedef struct {
} Program;
typedef struct {
+ Uint8 len;
Uint16 addr;
char name[64];
} Label;
@@ -33,7 +34,7 @@ Program p;
/* clang-format off */
char ops[][4] = {
- "BRK", "NOP", "LIT", "LIX", "IOR", "IOW", "LDR", "STR",
+ "BRK", "NOP", "LIT", "---", "IOR", "IOW", "LDR", "STR",
"JMP", "JSR", "RTI", "RTS", "---", "---", "---", "---",
"POP", "DUP", "SWP", "OVR", "ROT", "AND", "ORA", "ROL",
"ADD", "SUB", "MUL", "DIV", "EQU", "NEQ", "GTH", "LTH"
@@ -108,7 +109,7 @@ error(char *name, char *id)
}
int
-makelabel(char *name, Uint16 addr)
+makelabel(char *name, Uint16 addr, Uint8 len)
{
Label *l;
if(findlabel(name))
@@ -119,8 +120,9 @@ makelabel(char *name, Uint16 addr)
return error("Label name is invalid", name);
l = &labels[labelslen++];
l->addr = addr;
+ l->len = len;
scpy(name, l->name, 64);
- printf("New label: %s[0x%02x]\n", l->name, l->addr);
+ printf("New label: %s, at 0x%02x[%d]\n", l->name, l->addr, l->len);
return 1;
}
@@ -129,7 +131,7 @@ makeconst(char *id, FILE *f)
{
char wv[64];
fscanf(f, "%s", wv);
- return makelabel(id, shex(wv));
+ return makelabel(id, shex(wv), 1);
}
int
@@ -140,7 +142,7 @@ makevariable(char *id, Uint16 *addr, FILE *f)
fscanf(f, "%s", wv);
origin = *addr;
*addr += shex(wv);
- return makelabel(id, origin);
+ return makelabel(id, origin, shex(wv));
}
int
@@ -200,7 +202,7 @@ pass1(FILE *f)
if(skipcomment(w, &ccmnt)) continue;
if(skipstring(w, &cstrg, &addr)) continue;
if(w[0] == '@') {
- if(!makelabel(w + 1, addr))
+ if(!makelabel(w + 1, addr, 0))
return error("Pass1 failed", w);
} else if(w[0] == ';') {
if(!makevariable(w + 1, &addr, f))
@@ -213,6 +215,8 @@ pass1(FILE *f)
else {
switch(w[0]) {
case '|': addr = shex(w + 1); break;
+ case '=': addr += 4; break; /* STR helper */
+ case '~': addr += 4; break; /* LDR helper */
case ',': addr += 3; break;
case '.': addr += (slen(w + 1) == 2 ? 1 : 2); break;
case '+': /* signed positive */
@@ -250,6 +254,8 @@ pass2(FILE *f)
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);
else if(w[0] == '-' && sihx(w + 1) && slen(w + 1) == 4) pushshort((Sint16)(shex(w + 1) * -1), 1);
+ else if(w[0] == '=' && (l = findlabel(w + 1)) && l->len){ pushshort(l->addr, 1); pushbyte(findopcode(l->len == 2 ? "STR2" : "STR"),0); }
+ else if(w[0] == '~' && (l = findlabel(w + 1)) && l->len){ pushshort(l->addr, 1); pushbyte(findopcode(l->len == 2 ? "LDR2" : "LDR"),0); }
else if((l = findlabel(w + 1))) pushshort(l->addr, w[0] == ',');
else return error("Unknown label in second pass", w);
/* clang-format on */
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/controller.usm bin/boot.rom
+./bin/assembler examples/sprite.usm bin/boot.rom
./bin/emulator bin/boot.rom
diff --git a/emulator.c b/emulator.c
@@ -54,7 +54,7 @@ void
putpixel(Uint32 *dst, int x, int y, int color)
{
if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8)
- dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color];
+ dst[y * WIDTH + x] = theme[color];
}
void
@@ -190,6 +190,7 @@ domouse(SDL_Event *event)
void
dokey(SDL_Event *event)
{
+ (void)event;
}
void
@@ -218,16 +219,18 @@ consoler(Device *d, Memory *m, Uint8 b)
{
(void)b;
(void)d;
+ (void)m;
return 0;
}
Uint8
consolew(Device *d, Memory *m, Uint8 b)
{
- (void)d;
if(b)
printf("%c", b);
fflush(stdout);
+ (void)d;
+ (void)m;
return 0;
}
diff --git a/examples/controller.usm b/examples/controller.usm
@@ -7,12 +7,10 @@
|0100 @RESET
- #05 ,dev/r STR ( set dev/read to ctrl )
- #04 ,dev/w STR ( set dev/write to ppu-sprite )
-
- #0080 ,x STR2
- #0040 ,y STR2
- #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR
+ #05 =dev/r ( set dev/read to ctrl )
+ #04 =dev/w ( set dev/write to ppu-sprite )
+ #0080 =x #0040 =y ( origin )
+ #01 ,cursor_icn ~x ~y ,putsprite JSR ( draw sprite )
BRK
@@ -26,19 +24,23 @@ BRK
|c000 @FRAME
#00 IOR #10 NEQ ,next0 ROT JMP? POP2
- ,y LDR2 #0001 SUB2 ,y STR2
+ ~y #0001 SUB2 =y
@next0
+
#00 IOR #20 NEQ ,next1 ROT JMP? POP2
- ,y LDR2 #0001 ADD2 ,y STR2
+ ~y #0001 ADD2 =y
+
@next1
#00 IOR #40 NEQ ,next2 ROT JMP? POP2
- ,x LDR2 #0001 SUB2 ,x STR2
+ ~x #0001 SUB2 =x
+
@next2
- #00 IOR #80 NEQ ,next3 ROT JMP? POP2
- ,x LDR2 #0001 ADD2 ,x STR2
- @next3
+ #00 IOR #80 NEQ ,end ROT JMP? POP2
+ ~x #0001 ADD2 =x
+
+ @end
( redraw )
- #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR
+ #01 ,cursor_icn ~x ~y ,putsprite JSR
BRK
diff --git a/examples/hello.usm b/examples/hello.usm
@@ -4,7 +4,6 @@
|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 )
@@ -18,4 +17,4 @@ BRK
|c000 @FRAME BRK
|d000 @ERROR BRK
-|FFFA .RESET .FRAME .ERROR
+|FFFA .RESET .FRAME .ERROR
+\ No newline at end of file
diff --git a/examples/mouse.usm b/examples/mouse.usm
@@ -5,8 +5,8 @@
|0100 @RESET
- #02 ,dev/r STR ( set dev/read mouse#02 )
- #01 ,dev/w STR ( set dev/write screen#01 )
+ #02 =dev/r ( set dev/read mouse#02 )
+ #01 =dev/w ( set dev/write screen#01 )
BRK
diff --git a/examples/pixels.usm b/examples/pixels.usm
@@ -7,29 +7,28 @@
|0100 @RESET
- #01 ,dev/w STR ( set dev/write to screen )
- #01 ,color STR ( set color )
- #0020 ,x STR2 ( set x-pos )
- #0030 ,y STR2 ( set y-pos )
- #01 ,alive STR ( set alive = true )
+ #01 =dev/w ( set dev/write to screen )
+ #01 =color ( set color )
+ #0020 =x #0030 =y ( set origin )
+ #01 =alive ( set alive = true )
BRK
|c000 @FRAME
- ,alive LDR #00 EQU BRK?
- #01 ,color LDR ,x LDR2 ,y LDR2 ,putpixel JSR
+ ~alive #00 EQU BRK?
+ #01 ~color ~x ~y ,putpixel JSR
,move JSR
BRK
@move
- ,x LDR2 #0001 ADD2 ,x STR2 ( incr x )
- ,x LDR2 #0040 LTH2 RTS? ( if x > 60 )
- #0020 ,x STR2 ( x = 0x0020 )
- ,y LDR2 #0001 ADD2 ,y STR2 ( incr y )
- ,y LDR2 #0050 LTH2 RTS? ( y > 50 )
- #00 ,alive STR ( alive = 0 )
+ ~x #0001 ADD2 =x ( incr x )
+ ~x #0040 LTH2 RTS? ( if x > 60 )
+ #0020 =x ( x = 0x0020 )
+ ~y #0001 ADD2 =y ( incr y )
+ ~y #0050 LTH2 RTS? ( y > 50 )
+ #00 ,alive STR ( alive = 0 )
RTS
@putpixel
diff --git a/examples/screen.usm b/examples/screen.usm
@@ -2,22 +2,22 @@
:dev/r fff8 ( std read port )
:dev/w fff9 ( std write port )
-;width 2
-;height 2
+
+;width 2 ;height 2
|0100 @RESET
( set read/write to dev/screen )
- #01 DUP ,dev/r STR ,dev/w STR
+ #01 DUP =dev/r =dev/w
( load screen size )
- #00 IOR2 ,width STR2
- #02 IOR2 ,height STR2
+ #00 IOR2 =width
+ #02 IOR2 =height
( draw pixel at screen center )
#0101
- ,width LDR2 #0002 DIV2
- ,height LDR2 #0002 DIV2
+ ~width #0002 DIV2
+ ~height #0002 DIV2
,putpixel JSR
BRK
diff --git a/examples/sprite.usm b/examples/sprite.usm
@@ -4,14 +4,10 @@
|0100 @RESET
- #01 ,dev/w STR ( set dev/write to screen )
+ #01 =dev/w ( set dev/write to screen )
+ #04 =dev/w ( set dev/write to ppu-sprite )
- ( 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 #0041 #0041 ,putsprite JSR
#00 ,star_icn #0031 #0021 ,putsprite JSR
#00 ,cursor_icn #0021 #0016 ,putsprite JSR
#00 ,star_icn #0055 #0042 ,putsprite JSR
diff --git a/examples/test.usm b/examples/test.usm
@@ -1,54 +1,24 @@
-( comment )
+( blank )
-:dev/r fff8 ( const read port )
-:dev/w fff9 ( const write port )
+:dev/r fff8 ( std read port )
+:dev/w fff9 ( std write port )
-;x 2 ;y 2
+:test 0010
-|0100 @RESET
+;x 1 ;y 2
- #05 ,dev/r STR ( set dev/read to ctrl )
- #04 ,dev/w STR ( set dev/write to ppu-sprite )
+|0100 @RESET
- #0080 ,x STR2
- #0040 ,y STR2
- #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR
+ #12 =x
+ #1234 =y
+ ~x
+ ~y
-BRK
-
-|0200 @SPRITESHEET
-
-@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000
-@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000
+ #ef =test
BRK
-|c000 @FRAME
-
- #00 IOR #10 NEQ ,next0 ROT JMP? POP2
- ,y LDR2 #0001 SUB2 ,y STR2
- @next0
- #00 IOR #20 NEQ ,next1 ROT JMP? POP2
- ,y LDR2 #0001 ADD2 ,y STR2
- @next1
- #00 IOR #40 NEQ ,next2 ROT JMP? POP2
- ,x LDR2 #0001 SUB2 ,x STR2
- @next2
- #00 IOR #80 NEQ ,next3 ROT JMP? POP2
- ,x LDR2 #0001 ADD2 ,x STR2
- @next3
- ( redraw )
- #01 ,cursor_icn ,x LDR2 ,y LDR2 ,putsprite JSR
-
-BRK
-
-@putsprite
- IOW2 ( y short )
- IOW2 ( x short )
- IOW2 ( sprite address )
- IOW ( redraw byte )
- RTS
-
+|c000 @FRAME BRK
|d000 @ERROR BRK
|FFFA .RESET .FRAME .ERROR
diff --git a/uxn.c b/uxn.c
@@ -16,7 +16,6 @@ WITH REGARD TO THIS SOFTWARE.
#pragma mark - Operations
/* 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; }
void mempoke8(Memory *m, Uint16 a, Uint8 b) { m->dat[a] = b; }