Added helper for LDR/STR
This commit is contained in:
parent
1cc7abea54
commit
256d72e340
44
README.md
44
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
|
||||
|
||||
|
|
18
assembler.c
18
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 */
|
||||
|
|
2
build.sh
2
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
#ef =test
|
||||
|
||||
BRK
|
||||
|
||||
|0200 @SPRITESHEET
|
||||
|
||||
@cursor_icn .80c0 .e0f0 .f8e0 .1000 .0000 .0000 .0000 .0000
|
||||
@star_icn .1054 .28c6 .2854 .1000 .0000 .0000 .0000 .0000
|
||||
|
||||
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
|
||||
|
|
1
uxn.c
1
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; }
|
||||
|
|
Loading…
Reference in New Issue