]> git.sur5r.net Git - cc65/commitdiff
File reading, verification and comments.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 30 Oct 2009 22:34:08 +0000 (22:34 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 30 Oct 2009 22:34:08 +0000 (22:34 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4408 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/chrcvt/main.c

index 759c23385ef6346f20833c07b3fe15fe961f4870..100807899ef4744159ac716f94e889d347b98662 100644 (file)
@@ -40,6 +40,8 @@
 
 /* common */
 #include "cmdline.h"
+#include "print.h"
+#include "xmalloc.h"
 #include "version.h"
 
 /* chrcvt */
 
 
 
+/*
+ * The following is a corrected doc from the BGI font editor toolkit:
+ *
+ *                      BGI Stroke File Format
+ *
+ * The structure of Borland .CHR (stroke) files is as follows:
+ *
+ * ;  offset 0h is a Borland header:
+ * ;
+ *         HeaderSize      equ     080h
+ *         DataSize        equ     (size of font file)
+ *         descr           equ     "Triplex font"
+ *         fname           equ     "TRIP"
+ *         MajorVersion    equ     1
+ *         MinorVersion    equ     0
+ *
+ *         db      'PK',8,8
+ *         db      'BGI ',descr,'  V'
+ *         db      MajorVersion+'0'
+ *         db      (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0'
+ *         db      ' - 19 October 1987',0DH,0AH
+ *         db      'Copyright (c) 1987 Borland International', 0dh,0ah
+ *         db      0,1ah                           ; null & ctrl-Z = end
+ *
+ *         dw      HeaderSize                      ; size of header
+ *         db      fname                           ; font name
+ *         dw      DataSize                        ; font file size
+ *         db      MajorVersion,MinorVersion       ; version #'s
+ *         db      1,0                             ; minimal version #'s
+ *
+ *         db      (HeaderSize - $) DUP (0)        ; pad out to header size
+ *
+ * At offset 80h starts data for the file:
+ *
+ * ;               80h     '+'  flags stroke file type
+ * ;               81h-82h  number chars in font file (n)
+ * ;               83h      undefined
+ * ;               84h      ASCII value of first char in file
+ * ;               85h-86h  offset to stroke definitions (8+3n)
+ * ;               87h      scan flag (normally 0)
+ * ;               88h      distance from origin to top of capital
+ * ;               89h      distance from origin to baseline
+ * ;               8Ah      distance from origin to bottom descender
+ * ;               8Bh-8Fh  undefined
+ * ;               90h      offsets to individual character definitions
+ * ;               90h+2n   width table (one word per character)
+ * ;               90h+3n   start of character definitions
+ * ;
+ * The individual character definitions consist of a variable number of words
+ * describing the operations required to render a character. Each word
+ * consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown
+ * here:
+ *
+ * Byte 1          7   6   5   4   3   2   1   0     bit #
+ *                op1  <seven bit signed X coord>
+ *
+ * Byte 2          7   6   5   4   3   2   1   0     bit #
+ *                op2  <seven bit signed Y coord>
+ *
+ *
+ *           Opcodes
+ *
+ *         op1=0  op2=0  End of character definition.
+ *         op1=1  op2=0  Move the pointer to (x,y)
+ *         op1=1  op2=1  Draw from current pointer to (x,y)
+ */
+
+
+
+/* The target file format is designed to be read by a cc65 compiled program
+ * more easily. It should not be necessary to load the whole file into a
+ * buffer to parse it, or seek within the file. Also using less memory if
+ * possible would be fine. Therefore we use the following structure:
+ *
+ * Header portion:
+ *      .byte   $54, $43, $48, $00              ; "TCH" version
+ *      .word   <size of following data>
+ * Data portion:
+ *      .byte   <number of chars in font>       ; Value from $81
+ *      .byte   <ascii value of first char>     ; Value from $84
+ *      .byte   <top>                           ; Value from $88
+ *      .byte   <baseline>                      ; Value from $89
+ *      .byte   <bottom>                        ; Negative value from $8A
+ *      .word   <char definition offsets>, ...  ; Relative to data portion
+ * Character definitions:
+ *      .byte   <width>
+ *      .word   <converted opcode>, ...         
+ *      .byte   $80
+ *
+ * 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).
+ *
+ * The parsing code does not expect the file to contain more than $7D
+ * characters (most will contain $5E or similar), therefore the character
+ * definition offset will be accessed using the pointer to the data portion
+ * plus an offset in an 8 bit index register.
+ *
+ * Above structure allows a program to read the header portion of the file,
+ * validate it, allocate memory for the data portion and read the data portion
+ * in one chunk into memory. The character definition offsets will then be
+ * converted into pointers by adding the data portion pointer to each.
+ */
+
+
+
 /*****************************************************************************/
-/*                                          Data                                    */
+/*                                          Data                                    */
 /*****************************************************************************/
 
 
@@ -58,7 +166,7 @@ static unsigned FilesProcessed = 0;
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
@@ -70,21 +178,9 @@ static void Usage (void)
             "Usage: %s [options] file [options] [file]\n"
             "Short options:\n"
                     "  -h\t\t\tHelp (this text)\n"
-                    "  -H\t\t\tDump the object file header\n"
-                    "  -S\t\t\tDump segments sizes\n"
                     "  -V\t\t\tPrint the version number and exit\n"
             "\n"
             "Long options:\n"
-            "  --dump-all\t\tDump all object file information\n"
-            "  --dump-dbgsyms\tDump debug symbols\n"
-                    "  --dump-exports\tDump exported symbols\n"
-            "  --dump-files\t\tDump the source files\n"
-            "  --dump-header\t\tDump the object file header\n"
-            "  --dump-imports\tDump imported symbols\n"
-            "  --dump-lineinfo\tDump line information\n"
-            "  --dump-options\tDump object file options\n"
-            "  --dump-segments\tDump the segments in the file\n"
-                    "  --dump-segsize\tDump segments sizes\n"
             "  --help\t\tHelp (this text)\n"
                     "  --version\t\tPrint the version number and exit\n",
             ProgName);
@@ -102,6 +198,15 @@ static void OptHelp (const char* Opt attribute ((unused)),
 
 
 
+static void OptVerbose (const char* Opt attribute ((unused)),
+                       const char* Arg attribute ((unused)))
+/* Increase verbosity */
+{
+    ++Verbosity;
+}
+
+
+
 static void OptVersion (const char* Opt attribute ((unused)),
                        const char* Arg attribute ((unused)))
 /* Print the assembler version */
@@ -116,14 +221,63 @@ static void OptVersion (const char* Opt attribute ((unused)),
 static void ConvertFile (const char* Name)
 /* Convert one vector font file */
 {
-    /* Try to open the file */
+    static const unsigned char ChrHeader[] = {
+        0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20
+    };
+
+    long           Size;
+    unsigned char* Buf;
+    unsigned char* MsgEnd;
+
+    /* Try to open the file for reading */
     FILE* F = fopen (Name, "rb");
     if (F == 0) {
-       Error ("Cannot open `%s': %s", Name, strerror (errno));
+       Error ("Cannot open `%s': %s", Name, strerror (errno));
+    }
+
+    /* Seek to the end and determine the size */
+    fseek (F, 0, SEEK_END);
+    Size = ftell (F);
+
+    /* Seek back to the start of the file */
+    fseek (F, 0, SEEK_SET);
+
+    /* Check if the size is reasonable */
+    if (Size > 32*1024) {
+        Error ("File `%s' is too large (max = 32k)", Name);
+    } else if (Size < 0x100) {
+        Error ("File `%s' is too small to be a vector font file", Name);
+    }
+
+    /* Allocate memory for the file */
+    Buf = xmalloc ((size_t) Size);
+
+    /* Read the file contents into the buffer */
+    if (fread (Buf, 1, (size_t) Size, F) != (size_t) Size) {
+        Error ("Error reading from `%s'", Name);
     }
 
     /* Close the file */
     fclose (F);
+
+    /* Verify the header */
+    if (memcmp (Buf, ChrHeader, sizeof (ChrHeader)) != 0) {
+        Error ("Invalid format for `%s': invalid header", Name);
+    }
+    MsgEnd = memchr (Buf + sizeof (ChrHeader), 0x1A, 0x80);
+    if (MsgEnd == 0) {
+        Error ("Invalid format for `%s': description not found", Name);
+    }
+    if (MsgEnd[1] != 0x80 || MsgEnd[2] != 0x00) {
+        Error ("Invalid format for `%s': wrong header size", Name);
+    }
+
+    /* Print the copyright from the header */
+    Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4);
+
+    /* Convert the buffer into a strokefont structure */
+
+
 }
 
 
@@ -134,6 +288,7 @@ int main (int argc, char* argv [])
     /* Program long options */
     static const LongOpt OptTab[] = {
        { "--help",             0,      OptHelp                 },
+               { "--verbose",          0,      OptVerbose              },
        { "--version",          0,      OptVersion              },
     };