| ... | ... |
@@ -24,33 +24,24 @@ evaluxn(u, u->vframe); /* Each frame |
| 24 | 24 |
|
| 25 | 25 |
## Assembly Syntax |
| 26 | 26 |
|
| 27 |
-### Assign |
|
| 28 |
- |
|
| 27 |
+- `ADD`, an opcode. |
|
| 29 | 28 |
- `@label`, assign the current address to a label. |
| 30 | 29 |
- `;variable 2`, assign an address to a label automatically. |
| 31 | 30 |
- `:const 1a2b`, assign an address to a label manually. |
| 32 | 31 |
- `¯o { x 2 y 2 }`, define a macro named `macro`.
|
| 33 |
- |
|
| 34 |
-### Write |
|
| 35 |
- |
|
| 36 |
-- `ADD`, an opcode. |
|
| 37 |
-- `#1a`, a literal byte. |
|
| 38 |
-- `#12ef`, a literal short. |
|
| 39 |
-- `+1a`, a literal signed byte. |
|
| 40 |
-- `+12ef`, a literal signed short. |
|
| 41 |
-- `-1a`, a literal signed byte(negative). |
|
| 42 |
-- `-12ef`, a literal signed short(negative). |
|
| 43 |
-- `.ab`, a raw byte in memory. |
|
| 44 |
-- `.abcd`, a raw short in memory. |
|
| 32 |
+- `#1a`, a literal byte/short. |
|
| 33 |
+- `+1a`, a literal signed byte/short. |
|
| 34 |
+- `-1a`, a literal signed byte/short(negative). |
|
| 35 |
+- `.ab`, a raw byte/short in memory. |
|
| 45 | 36 |
- `,literal`, push label address to stack, prefixed with `LIT LEN`. |
| 46 |
- |
|
| 47 |
-### Special |
|
| 48 |
- |
|
| 49 |
-- `( comment )`, toggle parsing on/off. |
|
| 50 |
-- `|0010`, move to position in the program. |
|
| 51 |
-- `"hello`, push literal bytes for word "hello". |
|
| 52 | 37 |
- `=label`, helper to STR, equivalent to `,label STR`, or `label STR2`. |
| 53 | 38 |
- `~label`, helper to LDR, equivalent to `,label LDR2`, or `,label LDR2`. |
| 39 |
+- `|0010`, move to position in the program. |
|
| 40 |
+- `<23`, move the program position `23` bytes backward. |
|
| 41 |
+- `>12`, move the program position `12` bytes forward. |
|
| 42 |
+- `( comment )`, toggle parsing on/off. |
|
| 43 |
+- `[ 0123 abcd ]`, write shorts to memory. |
|
| 44 |
+- `[ Hello World ]`, write text to memory. |
|
| 54 | 45 |
|
| 55 | 46 |
### Operator modes |
| 56 | 47 |
|
| ... | ... |
@@ -60,25 +51,33 @@ evaluxn(u, u->vframe); /* Each frame |
| 60 | 51 |
- `ADDS2?`, modes can be combined. |
| 61 | 52 |
|
| 62 | 53 |
``` |
| 63 |
-( comment ) |
|
| 54 |
+( hello world ) |
|
| 64 | 55 |
|
| 65 | 56 |
:dev/w fff9 ( const write port ) |
| 66 | 57 |
|
| 67 | 58 |
|0100 @RESET |
| 68 |
- |
|
| 69 |
- ,string ( add string pointer to stack ) |
|
| 70 |
- @loop |
|
| 71 |
- DUP2 LDR IOW ( write pointer value to console ) |
|
| 72 |
- #0001 ADD2 ( increment string pointer ) |
|
| 73 |
- DUP2 LDR #00 NEQ ,loop ROT JMP? POP2 ( while *ptr!=0 goto loop ) |
|
| 59 |
+ |
|
| 60 |
+ #00 =dev/w ( set dev/write to console ) |
|
| 61 |
+ ,text1 ,print-label JSR ( print to console ) |
|
| 74 | 62 |
|
| 75 | 63 |
BRK |
| 76 | 64 |
|
| 77 |
-@string " Hello World " ( add string to memory ) |
|
| 65 |
+@print-label ( text ) |
|
| 66 |
+ |
|
| 67 |
+ @cliloop |
|
| 68 |
+ DUP2 LDR IOW ( write pointer value to console ) |
|
| 69 |
+ #0001 ADD2 ( increment string pointer ) |
|
| 70 |
+ DUP2 LDR #00 NEQ ,cliloop ROT JMP? POP2 ( while *ptr!=0 goto loop ) |
|
| 71 |
+ POP2 |
|
| 72 |
+ |
|
| 73 |
+RTS |
|
| 74 |
+ |
|
| 75 |
+@text1 [ Hello World ] <1 .00 ( add text to memory, return 1 byte, add null byte ) |
|
| 78 | 76 |
|
| 79 |
-|c000 @FRAME BRK |
|
| 80 |
-|d000 @ERROR BRK |
|
| 77 |
+|c000 @FRAME |
|
| 78 |
+|d000 @ERROR |
|
| 81 | 79 |
|
| 80 |
+|FFF0 [ f3f0 f30b f30a ] ( palette ) |
|
| 82 | 81 |
|FFFA .RESET .FRAME .ERROR |
| 83 | 82 |
``` |
| 84 | 83 |
|
| ... | ... |
@@ -80,6 +80,18 @@ pushshort(Uint16 s, int lit) |
| 80 | 80 |
pushbyte(s & 0xff, 0); |
| 81 | 81 |
} |
| 82 | 82 |
|
| 83 |
+void |
|
| 84 |
+pushtext(char *s, int lit) |
|
| 85 |
+{
|
|
| 86 |
+ int i = 0; |
|
| 87 |
+ char c; |
|
| 88 |
+ if(lit) |
|
| 89 |
+ pushbyte(0x22, 0); |
|
| 90 |
+ while((c = s[i++])) |
|
| 91 |
+ pushbyte(c, 0); |
|
| 92 |
+ pushbyte(' ', 0);
|
|
| 93 |
+} |
|
| 94 |
+ |
|
| 83 | 95 |
Macro * |
| 84 | 96 |
findmacro(char *s) |
| 85 | 97 |
{
|
| ... | ... |
@@ -253,54 +265,20 @@ skipblock(char *w, int *cap, char a, char b) |
| 253 | 265 |
return 0; |
| 254 | 266 |
} |
| 255 | 267 |
|
| 256 |
-int |
|
| 257 |
-skipstring(char *w, int *cap, Uint16 *addr) |
|
| 258 |
-{
|
|
| 259 |
- if(w[0] == '"') {
|
|
| 260 |
- if(*cap) |
|
| 261 |
- *addr += 1; |
|
| 262 |
- *cap = !(*cap); |
|
| 263 |
- return 1; |
|
| 264 |
- } |
|
| 265 |
- if(*cap) {
|
|
| 266 |
- *addr += slen(w) + 1; |
|
| 267 |
- return 1; |
|
| 268 |
- } |
|
| 269 |
- return 0; |
|
| 270 |
-} |
|
| 271 |
- |
|
| 272 |
-int |
|
| 273 |
-capturestring(char *w, int *cap) |
|
| 274 |
-{
|
|
| 275 |
- if(w[0] == '"') {
|
|
| 276 |
- if(*cap) |
|
| 277 |
- pushbyte(0x00, 0); |
|
| 278 |
- *cap = !(*cap); |
|
| 279 |
- return 1; |
|
| 280 |
- } |
|
| 281 |
- if(*cap) {
|
|
| 282 |
- int i; |
|
| 283 |
- for(i = 0; i < slen(w); ++i) |
|
| 284 |
- pushbyte(w[i], 0); |
|
| 285 |
- pushbyte(' ', 0);
|
|
| 286 |
- return 1; |
|
| 287 |
- } |
|
| 288 |
- return 0; |
|
| 289 |
-} |
|
| 290 |
- |
|
| 291 | 268 |
int |
| 292 | 269 |
pass1(FILE *f) |
| 293 | 270 |
{
|
| 294 |
- int ccmnt = 0, cstrg = 0, cbits = 0; |
|
| 271 |
+ int ccmnt = 0, cbits = 0; |
|
| 295 | 272 |
Uint16 addr = 0; |
| 296 | 273 |
char w[64]; |
| 297 | 274 |
printf("Pass 1\n");
|
| 298 | 275 |
while(fscanf(f, "%s", w) == 1) {
|
| 299 | 276 |
if(skipblock(w, &ccmnt, '(', ')')) continue;
|
| 300 |
- if(skipstring(w, &cstrg, &addr)) continue; |
|
| 301 |
- if(skipblock(w, &cbits, '[', ']')) |
|
| 302 |
- addr += w[0] != '[' && w[0] != ']' ? 2 : 0; |
|
| 303 |
- else if(w[0] == '@') {
|
|
| 277 |
+ if(skipblock(w, &cbits, '[', ']')) {
|
|
| 278 |
+ if(w[0] == '[' || w[0] == ']') |
|
| 279 |
+ continue; |
|
| 280 |
+ addr += sihx(w) ? 2 : slen(w) + 1; |
|
| 281 |
+ } else if(w[0] == '@') {
|
|
| 304 | 282 |
if(!makelabel(w + 1, addr, 0, NULL)) |
| 305 | 283 |
return error("Pass1 failed", w);
|
| 306 | 284 |
} else if(w[0] == ';') {
|
| ... | ... |
@@ -317,6 +295,8 @@ pass1(FILE *f) |
| 317 | 295 |
else {
|
| 318 | 296 |
switch(w[0]) {
|
| 319 | 297 |
case '|': addr = shex(w + 1); break; |
| 298 |
+ case '<': addr -= shex(w + 1); break; |
|
| 299 |
+ case '>': addr += shex(w + 1); break; |
|
| 320 | 300 |
case '=': addr += 4; break; /* STR helper */ |
| 321 | 301 |
case '~': addr += 4; break; /* LDR helper */ |
| 322 | 302 |
case ',': addr += 3; break; |
| ... | ... |
@@ -335,7 +315,7 @@ pass1(FILE *f) |
| 335 | 315 |
int |
| 336 | 316 |
pass2(FILE *f) |
| 337 | 317 |
{
|
| 338 |
- int ccmnt = 0, cstrg = 0, cbits = 0, cmacro = 0; |
|
| 318 |
+ int ccmnt = 0, cbits = 0, cmacro = 0; |
|
| 339 | 319 |
char w[64]; |
| 340 | 320 |
printf("Pass 2\n");
|
| 341 | 321 |
while(fscanf(f, "%s", w) == 1) {
|
| ... | ... |
@@ -345,10 +325,14 @@ pass2(FILE *f) |
| 345 | 325 |
if(w[0] == '&') continue; |
| 346 | 326 |
if(skipblock(w, &ccmnt, '(', ')')) continue;
|
| 347 | 327 |
if(skipblock(w, &cmacro, '{', '}')) continue;
|
| 348 |
- if(capturestring(w, &cstrg)) continue; |
|
| 349 | 328 |
/* clang-format off */ |
| 350 |
- if(skipblock(w, &cbits, '[', ']')) { if(w[0] != '[' && w[0] != ']') { pushshort(shex(w), 0); } }
|
|
| 329 |
+ if(skipblock(w, &cbits, '[', ']')) {
|
|
| 330 |
+ if(w[0] == '[' || w[0] == ']') { continue; }
|
|
| 331 |
+ if(slen(w) == 4 && sihx(w)) pushshort(shex(w), 0); else pushtext(w, 0); |
|
| 332 |
+ } |
|
| 351 | 333 |
else if(w[0] == '|') p.ptr = shex(w + 1); |
| 334 |
+ else if(w[0] == '<') p.ptr -= shex(w + 1); |
|
| 335 |
+ else if(w[0] == '>') p.ptr += shex(w + 1); |
|
| 352 | 336 |
else if((op = findopcode(w)) || scmp(w, "BRK", 4)) pushbyte(op, 0); |
| 353 | 337 |
else if(w[0] == ':') fscanf(f, "%s", w); |
| 354 | 338 |
else if(w[0] == ';') fscanf(f, "%s", w); |
| ... | ... |
@@ -2,15 +2,9 @@ |
| 2 | 2 |
|
| 3 | 3 |
:dev/w fff9 ( const write port ) |
| 4 | 4 |
|
| 5 |
-;x1 2 ;y1 2 |
|
| 6 |
- |
|
| 7 |
-;x 2 ;y 2 ;color 1 |
|
| 8 |
- |
|
| 9 | 5 |
|0100 @RESET |
| 10 | 6 |
|
| 11 | 7 |
#02 =dev/w |
| 12 |
- |
|
| 13 |
- #01 =color |
|
| 14 | 8 |
#00 ,icon #0040 #0040 ,draw-sprite JSR |
| 15 | 9 |
#01 ,icon #0048 #0040 ,draw-sprite JSR |
| 16 | 10 |
#02 ,icon #0050 #0040 ,draw-sprite JSR |
| ... | ... |
@@ -2,27 +2,24 @@ |
| 2 | 2 |
|
| 3 | 3 |
:dev/w fff9 ( const write port ) |
| 4 | 4 |
|
| 5 |
-;x 2 ;y 2 ;color 1 |
|
| 6 |
- |
|
| 7 | 5 |
|0100 @RESET |
| 8 | 6 |
|
| 9 |
- ( set dev/write to console ) |
|
| 10 |
- #00 =dev/w |
|
| 11 |
- ( print to console ) |
|
| 12 |
- ,text ,displaycli JSR |
|
| 7 |
+ #00 =dev/w ( set dev/write to console ) |
|
| 8 |
+ ,text1 ,print-label JSR ( print to console ) |
|
| 13 | 9 |
|
| 14 | 10 |
BRK |
| 15 | 11 |
|
| 16 |
-@displaycli |
|
| 12 |
+@print-label ( text ) |
|
| 17 | 13 |
|
| 18 | 14 |
@cliloop |
| 19 | 15 |
DUP2 LDR IOW ( write pointer value to console ) |
| 20 | 16 |
#0001 ADD2 ( increment string pointer ) |
| 21 | 17 |
DUP2 LDR #00 NEQ ,cliloop ROT JMP? POP2 ( while *ptr!=0 goto loop ) |
| 18 |
+ POP2 |
|
| 22 | 19 |
|
| 23 |
-RTS |
|
| 20 |
+RTS |
|
| 24 | 21 |
|
| 25 |
-@text " Hello World " ( add characters to memory ) |
|
| 22 |
+@text1 [ Hello World ] <1 .00 ( add text to memory, return 1 byte, add null byte ) |
|
| 26 | 23 |
|
| 27 | 24 |
|c000 @FRAME |
| 28 | 25 |
|d000 @ERROR |
| ... | ... |
@@ -3,15 +3,18 @@ |
| 3 | 3 |
:dev/r fff8 ( const read port ) |
| 4 | 4 |
:dev/w fff9 ( const write port ) |
| 5 | 5 |
|
| 6 |
-;x 2 ;y 2 ;sprite 2 |
|
| 6 |
+&Point2d { x 2 y 2 }
|
|
| 7 |
+ |
|
| 8 |
+;pos Point2d |
|
| 9 |
+;sprite 2 |
|
| 7 | 10 |
|
| 8 | 11 |
|0100 @RESET |
| 9 | 12 |
|
| 10 | 13 |
#03 =dev/r ( set dev/read to controller ) |
| 11 | 14 |
#02 =dev/w ( set dev/write to sprite ) |
| 12 |
- #0080 =x #0040 =y ( origin ) |
|
| 15 |
+ #0080 =pos.x #0040 =pos.y ( origin ) |
|
| 13 | 16 |
|
| 14 |
- #12 ,up_icn ~x ~y ,draw-sprite JSR |
|
| 17 |
+ #12 ,up_icn ~pos.x ~pos.y ,draw-sprite JSR |
|
| 15 | 18 |
|
| 16 | 19 |
BRK |
| 17 | 20 |
|
| ... | ... |
@@ -23,22 +26,22 @@ BRK |
| 23 | 26 |
|
| 24 | 27 |
#00 IOR #10 NEQ ,next1 ROT JMP? POP2 |
| 25 | 28 |
,up_icn =sprite |
| 26 |
- ~y #0001 SUB2 =y |
|
| 29 |
+ ~pos.y #0001 SUB2 =pos.y |
|
| 27 | 30 |
@next1 |
| 28 | 31 |
#00 IOR #20 NEQ ,next2 ROT JMP? POP2 |
| 29 | 32 |
,down_icn =sprite |
| 30 |
- ~y #0001 ADD2 =y |
|
| 33 |
+ ~pos.y #0001 ADD2 =pos.y |
|
| 31 | 34 |
@next2 |
| 32 | 35 |
#00 IOR #40 NEQ ,next3 ROT JMP? POP2 |
| 33 | 36 |
,left_icn =sprite |
| 34 |
- ~x #0001 SUB2 =x |
|
| 37 |
+ ~pos.x #0001 SUB2 =pos.x |
|
| 35 | 38 |
@next3 |
| 36 | 39 |
#00 IOR #80 NEQ ,end ROT JMP? POP2 |
| 37 | 40 |
,right_icn =sprite |
| 38 |
- ~x #0001 ADD2 =x |
|
| 41 |
+ ~pos.x #0001 ADD2 =pos.x |
|
| 39 | 42 |
@end |
| 40 | 43 |
( redraw ) |
| 41 |
- #13 ~sprite ~x ~y ,draw-sprite JSR |
|
| 44 |
+ #13 ~sprite ~pos.x ~pos.y ,draw-sprite JSR |
|
| 42 | 45 |
|
| 43 | 46 |
BRK |
| 44 | 47 |
|
| ... | ... |
@@ -134,11 +134,11 @@ RTS |
| 134 | 134 |
@checkoff_icn [ 7e81 8181 8181 817e ] |
| 135 | 135 |
@checkon_icn [ 7e81 99bd bd99 817e ] |
| 136 | 136 |
|
| 137 |
-@text1 " Planet " ( add string to memory ) |
|
| 138 |
-@text2 " To Jupiter " |
|
| 139 |
-@text3 " To Neptune " |
|
| 140 |
-@text4 " To Nereid " |
|
| 141 |
-@text5 " Theme " |
|
| 137 |
+@text1 [ Planet ] <1 .00 ( add string to memory ) |
|
| 138 |
+@text2 [ To Jupiter ] <1 .00 |
|
| 139 |
+@text3 [ To Neptune ] <1 .00 |
|
| 140 |
+@text4 [ To Nereid ] <1 .00 |
|
| 141 |
+@text5 [ Theme ] <1 .00 |
|
| 142 | 142 |
|
| 143 | 143 |
@font ( spectrum-zx font ) |
| 144 | 144 |
[ |