Added basic mlb support.
authorLukas Krickl <lukas@krickl.dev>
Wed, 13 Mar 2024 05:46:07 +0000 (06:46 +0100)
committerLukas Krickl <lukas@krickl.dev>
Wed, 13 Mar 2024 05:46:07 +0000 (06:46 +0100)
TODO: Allow user-defined sections for better label support

src/main.c
src/ulas.c
src/ulas.h

index fff1c6e785700ee54be9cf0c8688d7446872c2ee..d2a0212c88bc1357f86ce92b30e22e09522754c9 100644 (file)
@@ -23,7 +23,7 @@
 #define ULAS_OPTS "hvVpdA"
 
 // args with value
-#define ULAS_OPTS_ARG "o:l:s:i:w:a:"
+#define ULAS_OPTS_ARG "o:l:s:i:w:a:S:"
 
 #define ULAS_HELP(a, desc) printf("\t-%s\t%s\n", (a), desc);
 
@@ -34,7 +34,7 @@ unsigned long incpathslen = 0;
 
 void ulas_help(void) {
   printf("%s\n", ULAS_NAME);
-  printf("Usage %s [-%s] [-o=path] [-i=path] [-l=path] [-a=initial-address] "
+  printf("Usage %s [-%s] [-o=path] [-i=path] [-l=path] [-a=initial-address] [-S=ulas|mlb] "
          "[input]\n\n",
          ULAS_NAME, ULAS_OPTS);
   ULAS_HELP("h", "display this help and exit");
@@ -48,6 +48,7 @@ void ulas_help(void) {
   ULAS_HELP("a=initial-address", "Initial starting address");
   ULAS_HELP("A", "Print addresses in disassembler mode");
   ULAS_HELP("d", "Disassemble a file");
+  ULAS_HELP("S", "Set the symbol format");
   ULAS_HELP("w=warning", "Toggle warnings: a=all, o=overflow");
 }
 
@@ -101,6 +102,16 @@ void ulas_getopt(int argc, char **argv, struct ulas_config *cfg) {
     case 'A':
       cfg->print_addrs = 1;
       break;
+    case 'S':
+      if (strcmp("ulas", optarg) == 0) {
+        cfg->sym_fmt = ULAS_SYM_FMT_DEFAULT; 
+      } else if (strcmp("mlb", optarg) == 0) {
+        cfg->sym_fmt = ULAS_SYM_FMT_MLB; 
+      } else {
+        printf("Invalid symbol format: %s\n", optarg);
+        exit(-1);
+      }
+      break;
     case '?':
       break;
     default:
index ca7da5ad5c3f4eee581171301114ae8cf9c21c51..07c671717b5ccca7b55533e70e53e8fcd216e1ef 100644 (file)
@@ -334,29 +334,85 @@ int ulas_symbolset(const char *cname, int scope, struct ulas_tok tok,
   return rc;
 }
 
+int ulas_symbolout_mlbloc(FILE *dst, long addr) {
+  if (addr == -1) {
+    fprintf(dst, "Unknown:");
+    return 0;
+  }
+  
+  // TODO: maybe allow the user to define this by using 
+  // .section and just trust the label location in the source
+  // is correct
+  switch (ulas.arch.type) {
+  case ULAS_ARCH_SM83:
+    if (addr >= 0x0000 && addr <= 0x7FFF) {
+      fprintf(dst, "GbPrgRom:");
+      return 0;
+    } else if (addr >= 0xC000 && addr <= 0xDFFF) {
+      fprintf(dst, "GbWorkRam:");
+      return 0xC000;
+    } else {
+      fprintf(dst, "Unknown:");
+      return 0;
+    }
+    break;
+  }
+  return 0;
+}
+
 int ulas_symbolout(FILE *dst, struct ulas_sym *s) {
   if (!dst || ulas.pass != ULAS_PASS_FINAL) {
     return 0;
   }
 
   int rc = 0;
-  if (!s->name || s->name[0] == '\0') {
-    fprintf(dst, "<unnamed> = ");
-  } else {
-    fprintf(dst, "%s = ", s->name);
-  }
-  switch (s->tok.type) {
-  case ULAS_INT:
-    fprintf(dst, "0x%x", ulas_valint(&s->tok, &rc));
-    break;
-  case ULAS_STR:
-    fprintf(dst, "%s", ulas_valstr(&s->tok, &rc));
+
+  switch (ulascfg.sym_fmt) {
+  case ULAS_SYM_FMT_DEFAULT:
+    if (!s->name || s->name[0] == '\0') {
+      fprintf(dst, "<unnamed> = ");
+    } else {
+      fprintf(dst, "%s = ", s->name);
+    }
+    switch (s->tok.type) {
+    case ULAS_INT:
+      fprintf(dst, "0x%x", ulas_valint(&s->tok, &rc));
+      break;
+    case ULAS_STR:
+      fprintf(dst, "%s", ulas_valstr(&s->tok, &rc));
+      break;
+    default:
+      fprintf(dst, "<Unknown type>");
+      break;
+    }
+    fprintf(dst, "\n");
     break;
-  default:
-    fprintf(dst, "<Unknown type>");
+  case ULAS_SYM_FMT_MLB:
+    switch (s->tok.type) {
+    case ULAS_INT: {
+      int valint = ulas_valint(&s->tok, &rc);
+      valint -= ulas_symbolout_mlbloc(dst, valint);
+      fprintf(dst, "%x:", valint);
+      break;
+    }
+    case ULAS_STR:
+      ulas_symbolout_mlbloc(dst, -1);
+      fprintf(dst, "%s:", ulas_valstr(&s->tok, &rc));
+      break;
+    default:
+      ulas_symbolout_mlbloc(dst, -1);
+      fprintf(dst, "<Unknown type>:");
+      break;
+    }
+    if (!s->name || s->name[0] == '\0') {
+      fprintf(dst, "<unnamed>:<unnamed>");
+    } else {
+      fprintf(dst, "%s:%s", s->name, s->name);
+    }
+
+    fprintf(dst, "\n");
     break;
   }
-  fprintf(dst, "\n");
 
   return rc;
 }
@@ -376,7 +432,8 @@ int ulas_tok(struct ulas_str *dst, const char **out_line, unsigned long n) {
     i++;
   }
 
-  // string token
+  // s
+  // tring token
   if (line[i] == '"') {
     dst->buf[write++] = line[i++];
     int last_escape = 0;
index 8c58880d709473687d5282e56c0aa0aa1566f901..e124ba9c9a80458cfdfc46d9e2cdda260cd0a2af 100644 (file)
@@ -119,6 +119,8 @@ struct ulas_tok;
 
 enum ulas_warm { ULAS_WARN_OVERFLOW = 1, ULAS_WARN_ALL = 0x7FFFFFFF };
 
+enum ulas_symfmt { ULAS_SYM_FMT_DEFAULT, ULAS_SYM_FMT_MLB };
+
 struct ulas_config {
   // argv represents file names
   char **argv;
@@ -128,6 +130,8 @@ struct ulas_config {
   char *lst_path;
   char *sym_path;
 
+  enum ulas_symfmt sym_fmt;
+
   int verbose;
   int preproc_only;
   int disas;