]> git.sur5r.net Git - cc65/blob - src/sp65/c.c
Changed most "backticks" (grave accents) into apostrophes.
[cc65] / src / sp65 / c.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                    c.c                                    */
4 /*                                                                           */
5 /*              C output for the sp65 sprite and bitmap utility              */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2012,      Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <errno.h>
37 #include <stdio.h>
38 #include <string.h>
39
40 /* common */
41 #include "chartype.h"
42 #include "check.h"
43 #include "cmdline.h"
44 #include "version.h"
45
46 /* sp65 */
47 #include "attr.h"
48 #include "c.h"
49 #include "error.h"
50
51
52
53 /*****************************************************************************/
54 /*                                   Code                                    */
55 /*****************************************************************************/
56
57
58
59 static int ValidIdentifier (const char* L)
60 /* Check a C identifier for validity */
61 {
62     /* Must begin with underscore or alphabetic character */
63     if (*L != '_' && !IsAlpha (*L)) {
64         return 0;
65     }
66     ++L;
67
68     /* Remainder must be as above plus digits */
69     while (*L) {
70         if (*L != '_' && !IsAlNum (*L)) {
71             return 0;
72         }
73         ++L;
74     }
75
76     /* Ok */
77     return 1;
78 }
79
80
81
82 static unsigned GetBytesPerLine (const Collection* A)
83 /* Return the number of bytes per line from the attribute collection A */
84 {
85     char        C;
86     unsigned    BytesPerLine = 16;
87
88     /* Check for a bytesperline attribute */
89     const char* V = GetAttrVal (A, "bytesperline");
90     if ((V && sscanf (V, "%u%c", &BytesPerLine, &C) != 1) ||
91         (BytesPerLine < 1 || BytesPerLine > 64)) {
92         Error ("Invalid value for attribute 'bytesperline'");
93     }
94     return BytesPerLine;
95 }
96
97
98
99 static unsigned GetBase (const Collection* A)
100 /* Return the number base from the attribute collection A */
101 {
102     char        C;
103     unsigned    Base = 16;
104
105     /* Check for a base attribute */
106     const char* V = GetAttrVal (A, "base");
107     if ((V && sscanf (V, "%u%c", &Base, &C) != 1) || (Base != 10 && Base != 16)) {
108         Error ("Invalid value for attribute 'base'");
109     }
110     return Base;
111 }
112
113
114
115 static const char* GetIdentifier (const Collection* A)
116 /* Return the variable identifier from the attribute collection A */
117 {
118     /* Check for a ident attribute */
119     const char* Ident = GetAttrVal (A, "ident");
120     if (Ident && !ValidIdentifier (Ident)) {
121         Error ("Invalid value for attribute 'ident'");
122     }
123     return Ident;
124 }
125
126
127
128 void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B)
129 /* Write the contents of Data to a file in C format */
130 {
131     FILE*       F;
132     const char* D;
133     unsigned    Size;
134
135
136     /* Get the name of the image */
137     const StrBuf* S = GetBitmapName (B);
138
139     /* Get the file name */
140     const char* Name = NeedAttrVal (A, "name", "write");
141
142     /* Check the number of bytes per line */
143     unsigned BytesPerLine = GetBytesPerLine (A);
144
145     /* Get the number base */
146     unsigned Base = GetBase (A);
147
148     /* Get the identifier */
149     const char* Ident = GetIdentifier (A);
150
151     /* Open the output file */
152     F = fopen (Name, "w");
153     if (F == 0) {
154         Error ("Cannot open output file '%s': %s", Name, strerror (errno));
155     }
156
157     /* Write a readable header */
158     fprintf (F,
159              "/*\n"
160              "** This file was generated by %s %s from\n"
161              "** %.*s (%ux%u, %u colors%s)\n"
162              "*/\n"
163              "\n",
164              ProgName,
165              GetVersionAsString (),
166              SB_GetLen (S), SB_GetConstBuf (S),
167              GetBitmapWidth (B), GetBitmapHeight (B),
168              GetBitmapColors (B),
169              BitmapIsIndexed (B)? ", indexed" : "");
170
171     /* If an identifier was given, output #defines for width, height, the
172     ** number of colors and declare a variable for the data.
173     */
174     if (Ident) {
175         fprintf (F,
176                  "#define %s_COLORS       %u\n"
177                  "#define %s_WIDTH        %u\n"
178                  "#define %s_HEIGHT       %u\n"
179                  "const unsigned char %s[] = {\n",
180                  Ident, GetBitmapColors (B),
181                  Ident, GetBitmapWidth (B),
182                  Ident, GetBitmapHeight (B),
183                  Ident);
184     }
185
186     /* Write the data */
187     D    = SB_GetConstBuf (Data);
188     Size = SB_GetLen (Data);
189     while (Size) {
190
191         unsigned I;
192
193         /* Output one line */
194         unsigned Chunk = Size;
195         if (Chunk > BytesPerLine) {
196             Chunk = BytesPerLine;
197         }
198         fputs ("    ", F);
199         for (I = 0; I < Chunk; ++I) {
200             switch (Base) {
201                 case 10:
202                     fprintf (F, "%u,", *D++ & 0xFF);
203                     break;
204                 case 16:
205                     fprintf (F, "0x%02X,", *D++ & 0xFF);
206                     break;
207
208             }
209         }
210         fputc ('\n', F);
211
212         /* Bump the counters */
213         Size -= Chunk;
214     }
215
216     /* Terminate the array if we had an identifier */
217     if (Ident) {
218         fputs ("};\n", F);
219     }
220
221     /* Close the file */
222     if (fclose (F) != 0) {
223         Error ("Error closing output file '%s': %s", Name, strerror (errno));
224     }
225 }