]> git.sur5r.net Git - cc65/blobdiff - src/chrcvt/main.c
Removed (pretty inconsistently used) tab chars from source code base.
[cc65] / src / chrcvt / main.c
index 846a8d892cc14f3085a0909d41b0a3358e3e5981..bec905142cf75ca154d4d7283687f8190bd13664 100644 (file)
@@ -1,12 +1,12 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                 main.c                                   */
+/*                                  main.c                                   */
 /*                                                                           */
 /*             Main program of the chrcvt vector font converter              */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/* (C) 2000-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -40,6 +40,7 @@
 
 /* common */
 #include "cmdline.h"
+#include "fname.h"
 #include "print.h"
 #include "strbuf.h"
 #include "xmalloc.h"
  *
  * Header portion:
  *      .byte   $54, $43, $48, $00              ; "TCH" version
- *      .word   <size of char definitions>
+ *      .word   <size of data portion>
  * Data portion:
- *      .byte   <top>                           ; Value from $88
- *      .byte   <baseline>                      ; Value from $89
- *      .byte   <bottom>                        ; Negative value from $8A
+ *      .byte   <top>                           ; Baseline to top
+ *      .byte   <bottom>                        ; Baseline to bottom
+ *      .byte   <height>                        ; Maximum char height
  *      .byte   <width>, ...                    ; $5F width bytes
  *      .word   <char definition offset>, ...   ; $5F char def offsets
  * Character definitions:
  *      .word   <converted opcode>, ...
  *      .byte   $80
  *
+ * The baseline of the character is assume to be at position zero. top and
+ * bottom are both positive values. The former extends in positive, the other
+ * in negative direction of the baseline. height contains the sum of top and
+ * bottom and is stored here just for easier handling.
+ *
  * The opcodes get converted for easier handling: END is marked by bit 7
  * set in the first byte. The second byte of this opcode is not needed.
  * Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1).
  * is stored in the header.
  *
  * Above structure allows a program to read the header portion of the file,
- * validate it, read the width and offset tables into static storage, allocate
- * memory for the character definitions read them into memory in one chunk.
+ * validate it, then read the remainder of the file into memory in one chunk.
  * The character definition offsets will then be converted into pointers by
  * adding the character definition base pointer to each.
  */
 
 
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
@@ -166,7 +171,7 @@ static unsigned FilesProcessed = 0;
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -175,21 +180,23 @@ static void Usage (void)
 /* Print usage information and exit */
 {
     fprintf (stderr,
-            "Usage: %s [options] file [options] [file]\n"
-            "Short options:\n"
-                    "  -h\t\t\tHelp (this text)\n"
-                    "  -V\t\t\tPrint the version number and exit\n"
-            "\n"
-            "Long options:\n"
-            "  --help\t\tHelp (this text)\n"
-                    "  --version\t\tPrint the version number and exit\n",
-            ProgName);
+             "Usage: %s [options] file [options] [file]\n"
+             "Short options:\n"
+             "  -h\t\t\tHelp (this text)\n"
+             "  -v\t\t\tBe more verbose\n"
+             "  -V\t\t\tPrint the version number and exit\n"
+             "\n"
+             "Long options:\n"
+             "  --help\t\tHelp (this text)\n"
+             "  --verbose\t\tBe more verbose\n"
+             "  --version\t\tPrint the version number and exit\n",
+             ProgName);
 }
 
 
 
 static void OptHelp (const char* Opt attribute ((unused)),
-                    const char* Arg attribute ((unused)))
+                     const char* Arg attribute ((unused)))
 /* Print usage information and exit */
 {
     Usage ();
@@ -199,7 +206,7 @@ static void OptHelp (const char* Opt attribute ((unused)),
 
 
 static void OptVerbose (const char* Opt attribute ((unused)),
-                       const char* Arg attribute ((unused)))
+                        const char* Arg attribute ((unused)))
 /* Increase verbosity */
 {
     ++Verbosity;
@@ -208,35 +215,46 @@ static void OptVerbose (const char* Opt attribute ((unused)),
 
 
 static void OptVersion (const char* Opt attribute ((unused)),
-                       const char* Arg attribute ((unused)))
+                        const char* Arg attribute ((unused)))
 /* Print the assembler version */
 {
     fprintf (stderr,
-                    "%s V%s - (C) Copyright 2009, Ullrich von Bassewitz\n",
-                    ProgName, GetVersionAsString ());
+             "%s V%s - (C) Copyright 2009, Ullrich von Bassewitz\n",
+             ProgName, GetVersionAsString ());
 }
 
 
 
-static void ConvertChar (StrBuf* Data, const unsigned char* Buf)
+static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining)
 /* Convert data for one character. Original data is in Buf, converted data
  * will be placed in Data.
  */
 {
-    /* We should check here for reading past the end of the buffer in case the
-     * input data is not sane.
-     */
+    /* Convert all drawing vectors for this character */
     while (1) {
 
+        unsigned Op;
+
+        /* Check if we have enough data left */
+        if (Remaining < 2) {
+            Error ("End of file while parsing character definitions");
+        }
+
         /* Get the next op word */
-        unsigned Op = (Buf[0] + (Buf[1] << 8)) & 0x8080;
+        Op = (Buf[0] + (Buf[1] << 8)) & 0x8080;
 
         /* Check the opcode */
         switch (Op) {
 
             case 0x0000:
                 /* End */
-                SB_AppendChar (Data, 0x80);
+                if (SB_IsEmpty (Data)) {
+                    /* No ops. We need to add an empty one */
+                    SB_AppendChar (Data, 0x00);
+                    SB_AppendChar (Data, 0x00);
+                }
+                /* Add an end marker to the last op in the buffer */
+                SB_GetBuf (Data)[SB_GetLen (Data) - 2] |= 0x80;
                 return;
 
             case 0x0080:
@@ -259,6 +277,7 @@ static void ConvertChar (StrBuf* Data, const unsigned char* Buf)
 
         /* Next Op */
         Buf += 2;
+        Remaining -= 2;
     }
 }
 
@@ -269,7 +288,13 @@ static void ConvertFile (const char* Input, const char* Output)
 {
     /* The header of a BGI vector font file */
     static const unsigned char ChrHeader[] = {
-        0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20
+        /* According to the Borland docs, the following should work, but it
+         * doesn't. Seems like there are fonts that work, but don't have the
+         * "BGI" string in the header. So we use just the PK\b\b mark as
+         * a header.
+         *
+         * 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20 */
+        0x50, 0x4B, 0x08, 0x08
     };
 
     /* The header of a TGI vector font file */
@@ -299,7 +324,7 @@ static void ConvertFile (const char* Input, const char* Output)
     /* Try to open the file for reading */
     FILE* F = fopen (Input, "rb");
     if (F == 0) {
-       Error ("Cannot open input file `%s': %s", Input, strerror (errno));
+        Error ("Cannot open input file `%s': %s", Input, strerror (errno));
     }
 
     /* Seek to the end and determine the size */
@@ -343,7 +368,9 @@ static void ConvertFile (const char* Input, const char* Output)
     FirstChar = Buf[0x84];
     CharCount = Buf[0x81] + (Buf[0x82] << 8);
     LastChar  = FirstChar + CharCount - 1;
-    if (FirstChar < 0x20 || LastChar < 0x7E) {
+    if (FirstChar > 0x20 || LastChar < 0x7E) {
+        Print (stderr, 1, "FirstChar = $%04X, CharCount = %u\n",
+               FirstChar, CharCount);
         Error ("File `%s' doesn't contain the chars we need", Input);
     } else if (LastChar >= 0x100) {
         Error ("File `%s' contains too many character definitions", Input);
@@ -362,6 +389,8 @@ static void ConvertFile (const char* Input, const char* Output)
     /* Convert the characters */
     for (Char = 0x20; Char <= 0x7E; ++Char, OffsetBuf += 2) {
 
+        int Remaining;
+
         /* Add the offset to the offset table */
         Offs = SB_GetLen (&VectorData);
         SB_AppendChar (&Offsets, Offs & 0xFF);
@@ -370,27 +399,42 @@ static void ConvertFile (const char* Input, const char* Output)
         /* Get the offset of the vector data in the BGI data buffer */
         Offs = OffsetBuf[0] + (OffsetBuf[1] << 8);
 
+        /* Calculate the remaining data in the buffer for this character */
+        Remaining = Size - (Offs + (VectorBuf - Buf));
+
         /* Check if the offset is valid */
-        if (Offs + (VectorBuf - Buf) > Size) {
+        if (Remaining <= 0) {
             Error ("Invalid data offset in input file `%s'", Input);
         }
 
         /* Convert the vector data and place it into the buffer */
-        ConvertChar (&VectorData, VectorBuf + Offs);
+        ConvertChar (&VectorData, VectorBuf + Offs, Remaining);
     }
 
     /* Complete the TCH header */
-    Offs = SB_GetLen (&VectorData);
+    Offs = 3 + 0x5F + 2*0x5F + SB_GetLen (&VectorData);
     TchHeader[4] = Offs & 0xFF;
     TchHeader[5] = (Offs >> 8) & 0xFF;
     TchHeader[6] = Buf[0x88];
-    TchHeader[7] = Buf[0x89];
-    TchHeader[8] = (unsigned char) -(signed char)(Buf[0x8A]);
+    TchHeader[7] = (unsigned char) -(signed char)(Buf[0x8A]);
+    TchHeader[8] = TchHeader[6] + TchHeader[7];
+
+    /* The baseline must be zero, otherwise we cannot convert */
+    if (Buf[0x89] != 0) {
+        Error ("Baseline of font in `%s' is not zero", Input);
+    }
+
+    /* If the output file is NULL, use the name of the input file with ".tch"
+     * appended.
+     */
+    if (Output == 0) {
+        Output = MakeFilename (Input, ".tch");
+    }
 
     /* Open the output file */
     F = fopen (Output, "wb");
     if (F == 0) {
-               Error ("Cannot open output file `%s': %s", Output, strerror (errno));
+        Error ("Cannot open output file `%s': %s", Output, strerror (errno));
     }
 
     /* Write the header to the output file */
@@ -409,6 +453,7 @@ static void ConvertFile (const char* Input, const char* Output)
     }
 
     /* Write the data to the output file */
+    Offs = SB_GetLen (&VectorData);
     if (fwrite (SB_GetConstBuf (&VectorData), 1, Offs, F) != Offs) {
         Error ("Error writing to `%s' (disk full?)", Output);
     }
@@ -428,9 +473,9 @@ int main (int argc, char* argv [])
 {
     /* Program long options */
     static const LongOpt OptTab[] = {
-       { "--help",             0,      OptHelp                 },
-               { "--verbose",          0,      OptVerbose              },
-       { "--version",          0,      OptVersion              },
+        { "--help",             0,      OptHelp                 },
+        { "--verbose",          0,      OptVerbose              },
+        { "--version",          0,      OptVersion              },
     };
 
     unsigned I;
@@ -442,43 +487,47 @@ int main (int argc, char* argv [])
     I = 1;
     while (I < ArgCount) {
 
-               /* Get the argument */
-               const char* Arg = ArgVec[I];
+        /* Get the argument */
+        const char* Arg = ArgVec[I];
 
-               /* Check for an option */
-               if (Arg [0] == '-') {
-                   switch (Arg [1]) {
+        /* Check for an option */
+        if (Arg [0] == '-') {
+            switch (Arg [1]) {
 
-               case '-':
-                   LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
-                   break;
+                case '-':
+                    LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
+                    break;
 
-               case 'h':
-                   OptHelp (Arg, 0);
-                   break;
+                case 'h':
+                    OptHelp (Arg, 0);
+                    break;
 
-                       case 'V':
-                   OptVersion (Arg, 0);
-                           break;
+                case 'v':
+                    OptVerbose (Arg, 0);
+                    break;
 
-                       default:
-                           UnknownOption (Arg);
-                   break;
+                case 'V':
+                    OptVersion (Arg, 0);
+                    break;
 
-           }
-               } else {
-           /* Filename. Dump it. */
-           ConvertFile (Arg, "out.tch"); 
-           ++FilesProcessed;
-       }
+                default:
+                    UnknownOption (Arg);
+                    break;
+
+            }
+        } else {
+            /* Filename. Dump it. */
+            ConvertFile (Arg, 0);
+            ++FilesProcessed;
+        }
 
-       /* Next argument */
-       ++I;
+        /* Next argument */
+        ++I;
     }
 
     /* Print a message if we did not process any files */
     if (FilesProcessed == 0) {
-       fprintf (stderr, "%s: No input files\n", ProgName);
+        fprintf (stderr, "%s: No input files\n", ProgName);
     }
 
     /* Success */