uxn

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

commit 256d72e340e01ecc2a329c81f081620dab08de11
parent 1cc7abea54148a693120e1755866b1828f7292b6
Author: neauoire <aliceffekt@gmail.com>
Date:   Sun, 14 Feb 2021 17:00:17 -0800

Added helper for LDR/STR

Diffstat:
MREADME.md | 44+++++++++++++++++++++-----------------------
Massembler.c | 18++++++++++++------
Mbuild.sh | 2+-
Memulator.c | 7+++++--
Mexamples/controller.usm | 28+++++++++++++++-------------
Mexamples/hello.usm | 4++--
Mexamples/mouse.usm | 4++--
Mexamples/pixels.usm | 25++++++++++++-------------
Mexamples/screen.usm | 14+++++++-------
Mexamples/sprite.usm | 10+++-------
Mexamples/test.usm | 54++++++++++++------------------------------------------
Muxn.c | 1-
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; }