uxn

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

commit 89952e8112880f2c4cc96f737577a2f43c03c2a2
parent a693d4ef90e2421c5e1abdfb9a74fbe0be32af04
Author: neauoire <aliceffekt@gmail.com>
Date:   Sat, 13 Feb 2021 16:37:03 -0800

Rewrote hello world to not use the stack

Diffstat:
MREADME.md | 31+++++++++++++++++--------------
Massembler.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mexamples/draw.usm | 86+++++++++++++++++++++++--------------------------------------------------------
Mexamples/hello.usm | 24++++++++++--------------
Mexamples/test.usm | 15++++++++++-----
Muxn.c | 7++++---
6 files changed, 124 insertions(+), 122 deletions(-)

diff --git a/README.md b/README.md @@ -58,40 +58,43 @@ evaluxn(u, u->vframe); /* Each frame - `+21 -03 MULS`, signed operators have the cond flag `S`. ``` -:dev/w fff9 ( const write port ) -;i 1 ( var iterator ) - -|0100 @RESET +( comment ) - #00 ,dev/w STR ( set dev/write to console ) +:dev/w fff9 ( const write port ) - @word1 "hello_world ( len: 0x0b ) +|0100 @RESET + #00 ,dev/w STR ( set dev/write to console ) + ,string ( add string pointer to stack ) @loop - IOW ( write to device#0 ) - ,i LDR #01 ADD ,i STR ( increment itr ) - ,i LDR ( a = i ) - ,word1 ,strlen JSR ( b = string length ) - NEQ ,loop ROT JSR? POP^ ( a != b ? loop ) + DUP2 LDR IOW ( write pointer value to console ) + #0001 ADD2 ( increment string pointer ) + DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) BRK -@strlen #0001 ADD2 LDR RTS +@string " Hello World " ( add string to memory ) -|c000 @FRAME BRK +|c000 @FRAME BRK |d000 @ERROR BRK + |FFFA .RESET .FRAME .ERROR ``` ## TODOs +- Li1 short mode +- 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 -- Draw a chr sprite. +- [debug]Print unused labels ## Refs diff --git a/assembler.c b/assembler.c @@ -33,7 +33,7 @@ Program p; /* clang-format off */ char ops[][4] = { - "BRK", "NOP", "LI1", "LIX", "IOR", "IOW", "LDR", "STR", + "BRK", "NOP", "LIT", "LIX", "IOR", "IOW", "LDR", "STR", "JMP", "JSR", "RTI", "RTS", "---", "---", "---", "---", "POP", "DUP", "SWP", "OVR", "ROT", "AND", "ORA", "ROL", "ADD", "SUB", "MUL", "DIV", "EQU", "NEQ", "GTH", "LTH" @@ -43,7 +43,6 @@ int scmp(char *a, char *b) { int i = 0; while(a[i] == b[i]) if(!a[i++]) return 1 int slen(char *s) { int i = 0; while(s[i] && s[++i]) ; return i; } /* string length */ int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) return 0; return 1; } /* string is hexadecimal */ int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'A' && c <= 'F') n = n * 16 + 10 + (c - 'A'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */ -int cmnt(char *w, int *skip) { if(w[0] == ')') { *skip = 0; return 1; } if(w[0] == '(') *skip = 1; if(*skip) return 1; return 0; } /* comment helper */ char *scpy(char *src, char *dst, int len) { int i = 0; while((dst[i] = src[i]) && i < len - 2) i++; dst[i + 1] = '\0'; return dst; } /* string copy */ #pragma mark - Helpers @@ -63,24 +62,12 @@ pushbyte(Uint8 b, int lit) void pushshort(Uint16 s, int lit) { - if(lit) { - pushbyte(0x03, 0); - pushbyte(0x02, 0); - } + if(lit) + pushbyte(0x22, 0); pushbyte((s >> 8) & 0xff, 0); pushbyte(s & 0xff, 0); } -void -pushtext(char *w) -{ - int i = slen(w); - pushbyte(0x03, 0); - pushbyte(slen(w), 0); - while(i > 0) - pushbyte(w[--i], 0); -} - Label * findlabel(char *s) { @@ -157,14 +144,61 @@ makevariable(char *id, Uint16 *addr, FILE *f) } int +skipcomment(char *w, int *cap) +{ + if(w[0] == ')') { + *cap = 0; + return 1; + } + if(w[0] == '(') *cap = 1; + if(*cap) return 1; + return 0; +} + +int +skipstring(char *w, int *cap, Uint16 *addr) +{ + if(w[0] == '"') { + if(*cap) + *addr += 1; + *cap = !(*cap); + return 1; + } + if(*cap) { + *addr += slen(w) + 1; + return 1; + } + return 0; +} + +int +capturestring(char *w, int *cap) +{ + if(w[0] == '"') { + if(*cap) + pushbyte(0x00, 0); + *cap = !(*cap); + return 1; + } + if(*cap) { + int i; + for(i = 0; i < slen(w); ++i) + pushbyte(w[i], 0); + pushbyte(' ', 0); + return 1; + } + return 0; +} + +int pass1(FILE *f) { - int skip = 0; + int ccmnt = 0, cstrg = 0; Uint16 addr = 0; char w[64]; while(fscanf(f, "%s", w) == 1) { - if(cmnt(w, &skip)) - continue; + if(skipcomment(w, &ccmnt)) continue; + if(skipstring(w, &cstrg, &addr)) continue; if(w[0] == '@') { if(!makelabel(w + 1, addr)) return error("Pass1 failed", w); @@ -179,12 +213,11 @@ pass1(FILE *f) else { switch(w[0]) { case '|': addr = shex(w + 1); break; - case '"': addr += slen(w + 1) + 2; break; case '.': addr += 2; break; - case ',': addr += 4; break; + case ',': addr += 3; break; case '+': /* signed positive */ case '-': /* signed negative */ - case '#': addr += (slen(w + 1) == 2 ? 2 : 4); break; + case '#': addr += (slen(w + 1) == 2 ? 2 : 3); break; default: return error("Unknown label in first pass", w); } } @@ -196,13 +229,14 @@ pass1(FILE *f) int pass2(FILE *f) { - int skip = 0; + int ccmnt = 0, cstrg = 0; char w[64]; while(fscanf(f, "%s", w) == 1) { Uint8 op = 0; Label *l; if(w[0] == '@') continue; - if(cmnt(w, &skip)) continue; + if(skipcomment(w, &ccmnt)) continue; + if(capturestring(w, &cstrg)) continue; /* clang-format off */ if(w[0] == '|') p.ptr = shex(w + 1); else if((op = findopcode(w)) || scmp(w, "BRK")) pushbyte(op, 0); @@ -214,7 +248,6 @@ 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] == '"') pushtext(w + 1); 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/examples/draw.usm b/examples/draw.usm @@ -9,51 +9,35 @@ |0100 @RESET ( set dev/write to screen ) - ,01 ,dev/w STR + #01 ,dev/w STR - ,01 ,color STR + #01 ,color STR ( fill rect x y w h ) - ,0020 ,0020 ,0060 ,0040 ,fillrect JSR + #0020 #0020 #0060 #0040 ,fillrect JSR - ,02 ,color STR + #02 ,color STR ( fill rect x y w h ) - ,0030 ,0030 ,0040 ,0060 ,fillrect JSR + #0030 #0030 #0040 #0060 ,fillrect JSR - ,03 ,color STR + #03 ,color STR ( fill rect x y w h ) - ,0040 ,0040 ,0060 ,0040 ,fillrect JSR + #0040 #0040 #0060 #0040 ,fillrect JSR - ,01 ,color STR + #01 ,color STR ( fill rect x y w h ) - ,00a0 ,0010 ,0020 ,0020 ,fillrect JSR + #00a0 #0010 #0020 #0020 ,fillrect JSR - ,02 ,color STR + #02 ,color STR ( fill rect x y w h ) - ,00b0 ,0040 ,0020 ,0020 ,linerect JSR + #00b0 #0040 #0020 #0020 ,linerect JSR - ,03 ,color STR + #03 ,color STR ( fill rect x y w h ) - ,0058 ,0028 ,0050 ,0050 ,linerect JSR + #0058 #0028 #0050 #0050 ,linerect JSR - ,01 ,color STR + #01 ,color STR ( fill rect x y w h ) - ,0028 ,0038 ,0050 ,0030 ,linerect JSR - - ( positive ) - ,01 ,color STR - +0030 ,x0 STR2 +0040 ,y0 STR2 - +0100 ,x1 STR2 +0060 ,y1 STR2 - ,line JSR - - ,02 ,color STR - +0020 ,x0 STR2 +0010 ,y0 STR2 - +0090 ,x1 STR2 +0070 ,y1 STR2 - ,line JSR - - ,03 ,color STR - +0010 ,x0 STR2 +0040 ,y0 STR2 - +0070 ,x1 STR2 +0060 ,y1 STR2 - ,line JSR + #0028 #0038 #0050 #0030 ,linerect JSR ,redraw JSR @@ -66,9 +50,9 @@ BRK ,x LDR2 ,x_ STR2 @fillrectcol ( draw ) ,x_ LDR2 ,y_ LDR2 ,putpixel JSR - ,x_ LDR2 ,0001 ADD2 ,x_ STR2 + ,x_ LDR2 #0001 ADD2 ,x_ STR2 ,x_ LDR2 ,w LDR2 ,x LDR2 ADD2 LTH2 ,fillrectcol ROT JMP? POP2 - ,y_ LDR2 ,0001 ADD2 ,y_ STR2 + ,y_ LDR2 #0001 ADD2 ,y_ STR2 ,y_ LDR2 ,h LDR2 ,y LDR2 ADD2 LTH2 ,fillrectrow ROT JMP? POP2 RTS @@ -78,33 +62,13 @@ BRK @linerectcol ( draw ) ,x LDR2 ,y_ LDR2 ,putpixel JSR ( draw ) ,x LDR2 ,w LDR2 ADD2 ,y_ LDR2 ,putpixel JSR - ,y_ LDR2 ,0001 ADD2 ,y_ STR2 + ,y_ LDR2 #0001 ADD2 ,y_ STR2 ,y_ LDR2 ,h LDR2 ,y LDR2 ADD2 LTH2 ,linerectcol ROT JMP? POP2 @linerectrow ( draw ) ,x_ LDR2 ,y LDR2 ,putpixel JSR ( draw ) ,x_ LDR2 ,y LDR2 ,h LDR2 ADD2 ,putpixel JSR - ,x_ LDR2 ,0001 ADD2 ,x_ STR2 - ,x_ LDR2 ,w LDR2 ,x LDR2 ADD2 ,0001 ADD2 LTH2 ,linerectrow ROT JMP? POP2 - RTS - -@line - ,x0 LDR2 ,x_ STR2 ,y0 LDR2 ,y_ STR2 ( start at x0,y0 ) - ,x1 LDR2 ,x0 LDR2 ,diff16sub JSR ,dx STR2 ( int dx = abs[x1 - x0] ) - ,y1 LDR2 ,y0 LDR2 ,diff16sub JSR -0001 MULS2 ,dy STR2 ( int dy = -abs[y1 - y0] ) - ,dx LDR2 ,dy LDR2 ADDS2 ,err1 STR2 ( int err1 = dx + dy, e2; ) - @lineloop - ,x_ LDR2 ,y_ LDR2 ,putpixel JSR ( draw ) - @line-x - ,err1 LDR2 +0002 MULS2 ,err2 STR2 ( e2 = 2 * err; ) - ,err2 LDR2 ,dy LDR2 LTHS2 ,line-y ROT JMP? POP2 ( e2 >= dy ) - ,err1 LDR2 ,dy LDR2 ADDS2 ,err1 STR2 ( err1 += dy; ) - ,x_ LDR2 +0001 ADDS2 ,x_ STR2 ( y0 += y0 < y1 ? 1 : -1; ) - @line-y - ,err2 LDR2 ,dx LDR2 GTHS2 ,line-end ROT JMP? POP2 ( e2 <= dx ) - ,err1 LDR2 ,dx LDR2 ADDS2 ,err1 STR2 ( err1 += dx; ) - ,y_ LDR2 +0001 ADDS2 ,y_ STR2 ( y0 += y0 < y1 ? 1 : -1; ) - @line-end - ,x_ LDR2 ,x1 LDR2 NEQS2 ,lineloop ROT JMP? POP2 ( loop ) + ,x_ LDR2 #0001 ADD2 ,x_ STR2 + ,x_ LDR2 ,w LDR2 ,x LDR2 ADD2 #0001 ADD2 LTH2 ,linerectrow ROT JMP? POP2 RTS @diff16 @@ -113,17 +77,17 @@ BRK RTS @redraw - ,0000 IOW2 - ,0000 IOW2 - ,00 IOW - ,01 IOW + #0000 IOW2 + #0000 IOW2 + #00 IOW + #01 IOW RTS @putpixel IOW2 ( y short ) IOW2 ( x short ) ,color LDR IOW ( color byte ) - ,00 IOW ( redraw byte ) + #00 IOW ( redraw byte ) RTS |c000 @FRAME BRK diff --git a/examples/hello.usm b/examples/hello.usm @@ -1,25 +1,21 @@ -( hello world, to console ) +( comment ) :dev/w fff9 ( const write port ) -;i 1 ( var iterator ) -|0100 @RESET - - #00 ,dev/w STR ( set dev/write to console ) - - @word1 "hello_world ( len: 0x0b ) +|0100 @RESET + #00 ,dev/w STR ( set dev/write to console ) + ,string ( add string pointer to stack ) @loop - IOW ( write to device#0 ) - ,i LDR #01 ADD ,i STR ( increment itr ) - ,i LDR ( a = i ) - ,word1 ,strlen JSR ( b = string length ) - NEQ ,loop ROT JSR? POP^ ( a != b ? loop ) + DUP2 LDR IOW ( write pointer value to console ) + #0001 ADD2 ( increment string pointer ) + DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) BRK -@strlen #0001 ADD2 LDR RTS +@string " Hello World " ( add string to memory ) -|c000 @FRAME BRK +|c000 @FRAME BRK |d000 @ERROR BRK + |FFFA .RESET .FRAME .ERROR diff --git a/examples/test.usm b/examples/test.usm @@ -1,16 +1,21 @@ ( comment ) -:const abcd -;byte 1 -;short 2 +:dev/w fff9 ( const write port ) |0100 @RESET - 12 34 ADD - 1234 0001 ADD2 + #00 ,dev/w STR ( set dev/write to console ) + ,string ( add string pointer to stack ) + @loop + DUP2 LDR IOW ( write pointer value to console ) + #0001 ADD2 ( increment string pointer ) + DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) BRK +@string " Hello World " ( add string to memory ) + |c000 @FRAME BRK |d000 @ERROR BRK + |FFFA .RESET .FRAME .ERROR diff --git a/uxn.c b/uxn.c @@ -31,7 +31,7 @@ Uint16 pop16(St8 *s) { return pop8(s) + (pop8(s) << 8); } Uint16 peek16(St8 *s, Uint8 a) { return peek8(s, a * 2) + (peek8(s, a * 2 + 1) << 8); } /* I/O */ void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); } -void op_li1(Uxn *u) { u->literal += 1; } +void op_lit(Uxn *u) { u->literal += 1; } void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; } void op_nop(Uxn *u) { printf("0x%02x ", pop8(&u->wst)); } void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push8(&u->wst, dev->read(dev, pop8(&u->wst))); } @@ -61,6 +61,7 @@ void op_neq(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, void op_gth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b > (Sint8)a : b > a); } void op_lth(Uxn *u) { Uint8 a = pop8(&u->wst), b = pop8(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint8)b < (Sint8)a : b < a); } /* --- */ +void op_lit16(Uxn *u) { u->literal += 2; } void op_nop16(Uxn *u) { printf("%04x\n", pop16(&u->wst)); } void op_ior16(Uxn *u) { Uint8 a = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devr)]; if(dev) push16(&u->wst, (dev->read(dev, a) << 8) + dev->read(dev, a + 1)); } void op_iow16(Uxn *u) { Uint8 a = pop8(&u->wst); Uint8 b = pop8(&u->wst); Device *dev = &u->dev[mempeek8(&u->ram, u->devw)]; if(dev) { dev->write(dev, b); dev->write(dev, a); } } @@ -86,12 +87,12 @@ void op_gth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u- void op_lth16(Uxn *u) { Uint16 a = pop16(&u->wst), b = pop16(&u->wst); push8(&u->wst, getflag(&u->status, FLAG_SIGN) ? (Sint16)b < (Sint16)a : b < a); } void (*ops[])(Uxn *u) = { - op_brk, op_nop, op_li1, op_lix, op_ior, op_iow, op_ldr, op_str, + op_brk, op_nop, op_lit, op_lix, 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_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, /* 16-bit */ - op_brk, op_nop16, op_li1, op_lix, op_ior16, op_iow16, op_ldr16, op_str16, + op_brk, op_nop16, op_lit16, op_lix, op_ior16, op_iow16, op_ldr16, op_str16, op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop, op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_and16, op_ora16, op_rol16, op_add16, op_sub16, op_mul16, op_div16, op_equ16, op_neq16, op_gth16, op_lth16