Added .chr directive to allow defining chr data
authorLukas Krickl <lukas@krickl.dev>
Fri, 22 Dec 2023 06:38:46 +0000 (07:38 +0100)
committerLukas Krickl <lukas@krickl.dev>
Fri, 22 Dec 2023 06:38:46 +0000 (07:38 +0100)
include/ulas.h
src/ulas.c
tests/t0.bin
tests/t0.s

index dd48937422c297f2d08eca2b31c500bf2309ae1e..747ddb662076c81fd6197bf337393031a8ad0037 100644 (file)
@@ -51,6 +51,7 @@
 #define ULAS_ASMSTR_SET_ENUM_DEF ".se"
 #define ULAS_ASMSTR_DEFINE_ENUM ".de"
 #define ULAS_ASMSTR_SETCHRCODE ".scc"
+#define ULAS_ASMSTR_CHR ".chr"
 
 // configurable tokens
 #define ULAS_TOK_COMMENT ';'
@@ -400,14 +401,20 @@ enum ulas_asmdir {
   // .scc '<char>'=<value>
   // allows to set custom encoding for char codes
   // when using .str
-  ULAS_ASMDIR_SETCHRCODE
+  ULAS_ASMDIR_SETCHRCODE,
+
+  // .chr 0, 1, 2, 3, 0, 1, 2, 3
+  // allows defining
+  // chr (tile) data from 0-3
+  // for each possible color
+  // it requires up to 8 integer expressions between 0 and 3
+  ULAS_ASMDIR_CHR,
 };
 
 // amount of registers
 #define ULAS_NR8 7
 #define ULAS_NR16 3
 
-
 enum ulas_asmregs {
   // r8
   ULAS_REG_B = 1,
index 2c4137850d16abc97f7cfb03905e18f24e4bbe02..5b48393e79850121402df5d17b42a5eaec0d8f4d 100644 (file)
@@ -1378,7 +1378,8 @@ int ulas_tokexpr(const char **line, unsigned long n) {
     }
 
     // check for any expression terminators here
-    if (tok.type == ',' || tok.type == ']' || tok.type == '=' || ulas_istokend(&ulas.tok)) {
+    if (tok.type == ',' || tok.type == ']' || tok.type == '=' ||
+        ulas_istokend(&ulas.tok)) {
       // on terminator we roll back line so that the terminator token
       // is not consumed now
       *line -= tokrc;
@@ -2462,8 +2463,8 @@ int ulas_asmdirstr(FILE *dst, const char **line, unsigned long n, int *rc) {
   do {
     char *s = ulas_strexpr(line, n, rc);
     long len = strlen(s);
-    
-    // apply char code map 
+
+    // apply char code map
     for (int i = 0; i < len; i++) {
       s[i] = ulas.charcodemap[(int)s[i]];
     }
@@ -2529,7 +2530,7 @@ int ulas_asmdirsetcharcode(const char **line, unsigned long n) {
     ULASERR("Expected =\n");
     return 0;
   }
-  
+
   ULAS_EVALEXPRS(setto = ulas_intexpr(line, n, &rc));
   setto = setto & 0xFF;
 
@@ -2538,6 +2539,51 @@ int ulas_asmdirsetcharcode(const char **line, unsigned long n) {
   return rc;
 }
 
+int ulas_asmdirchr(FILE *dst, const char **line, unsigned long n, int *rc) {
+  char b[2] = {0, 0};
+  struct ulas_tok t;
+  memset(&t, 0, sizeof(t));
+  int bit = 7;
+  ulas_tok(&ulas.tok, line, n);
+
+  int len = strlen(ulas.tok.buf);
+  if (len > 8) {
+    *rc = -1;
+    ULASERR("chr input exceeds 8 pixels\n");
+    return 0;
+  }
+
+  for (int i = 0; i < len; i++, bit--) {
+    switch (ulas.tok.buf[i]) {
+    case '0':
+      // 0 sets no bit
+      break;
+    case '1':
+      // 1 sets 01
+      b[1] |= (1 << bit);
+      break;
+    case '2':
+      // 2 sets 10
+      b[0] |= (1 << bit);
+      break;
+    case '3':
+      // 3 sets 11
+      b[0] |= (1 << bit);
+      b[1] |= (1 << bit);
+      break;
+    default:
+      ULASERR("Invalid chr value: '%c'. Expected 0-3.\n", ulas.tok.buf[i]);
+      break;
+    }
+  }
+
+  int written = 2;
+  ulas_asmout(dst, b, written);
+
+  // this always writes 2 bytes
+  return written;
+}
+
 int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
   // this buffer is written both to dst and to verbose output
   char outbuf[ULAS_OUTBUFMAX];
@@ -2572,13 +2618,21 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
   }
 
   if (ulas.tok.buf[0] == ULAS_TOK_ASMDIR_BEGIN) {
-    const char *dirstrs[] = {ULAS_ASMSTR_ORG,          ULAS_ASMSTR_SET,
-                             ULAS_ASMSTR_BYTE,         ULAS_ASMSTR_STR,
-                             ULAS_ASMSTR_FILL,         ULAS_ASMSTR_PAD,
-                             ULAS_ASMSTR_INCBIN,       ULAS_ASMSTR_DEF,
-                             ULAS_ASMSTR_CHKSM,        ULAS_ASMSTR_ADV,
-                             ULAS_ASMSTR_SET_ENUM_DEF, ULAS_ASMSTR_DEFINE_ENUM,
-                             ULAS_ASMSTR_SETCHRCODE,   NULL};
+    const char *dirstrs[] = {ULAS_ASMSTR_ORG,
+                             ULAS_ASMSTR_SET,
+                             ULAS_ASMSTR_BYTE,
+                             ULAS_ASMSTR_STR,
+                             ULAS_ASMSTR_FILL,
+                             ULAS_ASMSTR_PAD,
+                             ULAS_ASMSTR_INCBIN,
+                             ULAS_ASMSTR_DEF,
+                             ULAS_ASMSTR_CHKSM,
+                             ULAS_ASMSTR_ADV,
+                             ULAS_ASMSTR_SET_ENUM_DEF,
+                             ULAS_ASMSTR_DEFINE_ENUM,
+                             ULAS_ASMSTR_SETCHRCODE,
+                             ULAS_ASMSTR_CHR,
+                             NULL};
     enum ulas_asmdir dirs[] = {
         ULAS_ASMDIR_ORG,          ULAS_ASMDIR_SET,
         ULAS_ASMDIR_BYTE,         ULAS_ASMDIR_STR,
@@ -2586,7 +2640,7 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
         ULAS_ASMDIR_INCBIN,       ULAS_ASMDIR_DEF,
         ULAS_ASMDIR_CHKSM,        ULAS_ASMDIR_ADV,
         ULAS_ASMDIR_SET_ENUM_DEF, ULAS_ASMDIR_DEFINE_ENUM,
-        ULAS_ASMDIR_SETCHRCODE};
+        ULAS_ASMDIR_SETCHRCODE,   ULAS_ASMDIR_CHR};
 
     enum ulas_asmdir dir = ULAS_ASMDIR_NONE;
 
@@ -2644,6 +2698,9 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
     case ULAS_ASMDIR_SETCHRCODE:
       rc = ulas_asmdirsetcharcode(&line, n);
       break;
+    case ULAS_ASMDIR_CHR:
+      other_writes += ulas_asmdirchr(dst, &line, n, &rc);
+      break;
     case ULAS_ASMDIR_PAD:
       // TODO: pad is the same as .fill n, $ - n
     case ULAS_ASMDIR_NONE:
index 47a8d977a1f8092faff96b165ee6cacc332788e1..612d93adb5f4783ef8949eff6d2bbfa8334aaae0 100644 (file)
Binary files a/tests/t0.bin and b/tests/t0.bin differ
index 261dc9f16fa84bf46087634d4fabc83fc7920ed6..93ad7b80f889faeb5a76656da4893a4f7f199565 100644 (file)
@@ -128,3 +128,5 @@ l3: .db 1
 .str "abc"
 .scc 'a' = 'f'
 .str "abc"
+.db 1, 2, 3
+.chr 01233213