]> git.sur5r.net Git - cc65/blobdiff - src/sp65/asm.c
Merge remote-tracking branch 'upstream/master' into a5200
[cc65] / src / sp65 / asm.c
index e95bfc664715a8e87d26dc745378e2e4f3b36200..8f520cb9ecdca7f301a09062c6922791660e621a 100644 (file)
 #include <string.h>
 
 /* common */
+#include "chartype.h"
+#include "check.h"
 #include "cmdline.h"
 #include "version.h"
 
 /* sp65 */
 #include "attr.h"
-#include "bin.h"
+#include "asm.h"
 #include "error.h"
 
 
 
 
 
-void WriteAsmFile (const StrBuf* Data, const Collection* A)
+static int ValidIdentifier (const char* L)
+/* Check an assembler label for validity */
+{
+    /* Must begin with underscore or alphabetic character */
+    if (*L != '_' && !IsAlpha (*L)) {
+        return 0;
+    }
+    ++L;
+
+    /* Remainder must be as above plus digits */
+    while (*L) {
+        if (*L != '_' && !IsAlNum (*L)) {
+            return 0;
+        }
+        ++L;
+    }
+
+    /* Ok */
+    return 1;
+}
+
+
+
+static unsigned GetBytesPerLine (const Collection* A)
+/* Return the number of bytes per line from the attribute collection A */
+{
+    char        C;
+    unsigned    BytesPerLine = 16;
+
+    /* Check for a bytesperline attribute */
+    const char* V = GetAttrVal (A, "bytesperline");
+    if ((V && sscanf (V, "%u%c", &BytesPerLine, &C) != 1) ||
+        (BytesPerLine < 1 || BytesPerLine > 64)) {
+        Error ("Invalid value for attribute `bytesperline'");
+    }
+    return BytesPerLine;
+}
+
+
+
+static unsigned GetBase (const Collection* A)
+/* Return the number base from the attribute collection A */
+{
+    char        C;
+    unsigned    Base = 16;
+
+    /* Check for a base attribute */
+    const char* V = GetAttrVal (A, "base");
+    if ((V && sscanf (V, "%u%c", &Base, &C) != 1) ||
+        (Base != 2 && Base != 10 && Base != 16)) {
+        Error ("Invalid value for attribute `base'");
+    }
+    return Base;
+}
+
+
+
+static const char* GetIdentifier (const Collection* A)
+/* Return the label identifier from the attribute collection A */
+{
+    /* Check for a ident attribute */
+    const char* Ident = GetAttrVal (A, "ident");
+    if (Ident && !ValidIdentifier (Ident)) {
+        Error ("Invalid value for attribute `ident'");
+    }
+    return Ident;
+}
+
+
+
+void WriteAsmFile (const StrBuf* Data, const Collection* A, const Bitmap* B)
 /* Write the contents of Data to the given file in assembler (ca65) format */
 {
     FILE*       F;
     const char* D;
     unsigned    Size;
-    unsigned    BytesPerLine = 16;
-    char        C;
 
 
+    /* Get the name of the image */
+    const StrBuf* S = GetBitmapName (B);
+
     /* Get the file name */
     const char* Name = NeedAttrVal (A, "name", "write");
 
-    /* Check for a bytesperline attribute */
-    const char* V = GetAttrVal (A, "bytesperline");
-    if ((V && sscanf (V, "%u%c", &BytesPerLine, &C) != 1) || 
-        (BytesPerLine < 1 || BytesPerLine > 64)) {
-        Error ("Invalid value for attribute `bytesperline'");
-    }
+    /* Check the number of bytes per line */
+    unsigned BytesPerLine = GetBytesPerLine (A);
+
+    /* Get the number base */
+    unsigned Base = GetBase (A);
+
+    /* Get the identifier */
+    const char* Ident = GetIdentifier (A);
 
     /* Open the output file */
     F = fopen (Name, "w");
@@ -83,11 +158,29 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A)
     /* Write a readable header */
     fprintf (F,
              ";\n"
-             "; This file was generated by %s %s\n"
+             "; This file was generated by %s %s from\n"
+             "; %.*s (%ux%u, %u colors%s)\n"
              ";\n"
              "\n",
              ProgName,
-             GetVersionAsString ());
+             GetVersionAsString (),
+             SB_GetLen (S), SB_GetConstBuf (S),
+             GetBitmapWidth (B), GetBitmapHeight (B),
+             GetBitmapColors (B),
+             BitmapIsIndexed (B)? ", indexed" : "");
+
+    /* If we have an assembler label, output that */
+    if (Ident) {
+        fprintf (F,
+                 ".proc   %s\n"
+                 "        COLORS = %u\n"
+                 "        WIDTH  = %u\n"
+                 "        HEIGHT = %u\n",
+                 Ident,
+                 GetBitmapColors (B),
+                 GetBitmapWidth (B),
+                 GetBitmapHeight (B));
+    }
 
     /* Write the data */
     D    = SB_GetConstBuf (Data);
@@ -99,11 +192,32 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A)
         /* Output one line */
         unsigned Chunk = Size;
         if (Chunk > BytesPerLine) {
-            Chunk = BytesPerLine;         
+            Chunk = BytesPerLine;
         }
-        fprintf (F, "        .byte   $%02X", (*D++ & 0xFF));
-        for (I = 1; I < Chunk; ++I) {
-            fprintf (F, ",%02X", (*D++ & 0xFF));
+        fputs ("        .byte   ", F);
+        for (I = 0; I < Chunk; ++I) {
+            unsigned char V = *D++;
+            if (I > 0) {
+                fputc (',', F);
+            }
+            switch (Base) {
+                case 2:
+                    fprintf (F, "%%%u%u%u%u%u%u%u%u",
+                             (V >> 7) & 0x01, (V >> 6) & 0x01,
+                             (V >> 5) & 0x01, (V >> 4) & 0x01,
+                             (V >> 3) & 0x01, (V >> 2) & 0x01,
+                             (V >> 1) & 0x01, (V >> 0) & 0x01);
+                    break;
+
+                case 10:
+                    fprintf (F, "%u", V);
+                    break;
+
+                case 16:
+                    fprintf (F, "$%02X", V);
+                    break;
+
+            }
         }
         fputc ('\n', F);
 
@@ -111,6 +225,11 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A)
         Size -= Chunk;
     }
 
+    /* Terminate the .proc if we had an identifier */
+    if (Ident) {
+        fputs (".endproc\n", F);
+    }
+
     /* Add an empty line at the end */
     fputc ('\n', F);
 
@@ -119,6 +238,3 @@ void WriteAsmFile (const StrBuf* Data, const Collection* A)
         Error ("Error closing output file `%s': %s", Name, strerror (errno));
     }
 }
-
-
-