1 /* Object file conversion utility for Challenger 1P
\r
3 by Stephan Muehlstrasser
\r
16 #include "cmdline.h"
\r
18 #include "chartype.h"
\r
20 #include "version.h"
\r
21 #include "xmalloc.h"
\r
23 static void Usage (void)
\r
26 "Usage: %s [options] file\n"
\r
28 " -V\t\t\tPrint the version number\n"
\r
29 " -h\t\t\tHelp (this text)\n"
\r
30 " -o name\t\tName the C1P output file (default: <input.c1p>)\n"
\r
31 " -S addr\t\tLoad address (default 0x400)\n"
\r
34 " --help\t\tHelp (this text)\n"
\r
35 " --version\t\tPrint the version number\n",
\r
39 static void OptHelp (const char* Opt attribute ((unused)),
\r
40 const char* Arg attribute ((unused)))
\r
41 /* Print usage information and exit */
\r
44 exit (EXIT_SUCCESS);
\r
48 static void OptVersion (const char* Opt attribute ((unused)),
\r
49 const char* Arg attribute ((unused)))
\r
50 /* Print the program version */
\r
52 fprintf (stderr, "grc65 V%s\n", GetVersionAsString ());
\r
56 static unsigned long CvtNumber (const char* Arg, const char* Number)
\r
57 /* Convert a number from a string. Allow '$' and '0x' prefixes for hex
\r
58 * numbers. Duplicated from ld65's main.c.
\r
65 if (*Number == '$') {
\r
67 Converted = sscanf (Number, "%lx", &Val);
\r
69 Converted = sscanf (Number, "%li", (long*)&Val);
\r
72 /* Check if we do really have a number */
\r
73 if (Converted != 1) {
\r
74 AbEnd ("Invalid number given in argument: %s\n", Arg);
\r
77 /* Return the result */
\r
81 /* Commands of C1P PROM monitor */
\r
82 #define ADDRESS_MODE_CMD '.'
\r
83 #define DATA_MODE_CMD '/'
\r
84 #define EXECUTE_CMD 'G'
\r
85 #define DATA_MODE_ADDRESS 0x00FB
\r
87 /* Transform the cc65 executable binary into a series of
\r
88 commands that make the C1P PROM monitor load the bytes
\r
91 static void Transform (unsigned long StartAddress, FILE *In, FILE *Out)
\r
95 /* Position to the start address */
\r
96 fprintf(Out, "%c%04.4X%c", ADDRESS_MODE_CMD,
\r
97 StartAddress & 0xFFFF, DATA_MODE_CMD);
\r
99 /* Loop over all input bytes and enter them one by one */
\r
100 for (c = getc(In); c != EOF; c = getc(In)) {
\r
101 fprintf(Out, "%02.2X\n", (unsigned int) c & 0xFF);
\r
104 /* Store 00 to 0x00FB to enable keyboard input at the end */
\r
105 fprintf(Out, "%c%04.4X%c%02.2X\n", ADDRESS_MODE_CMD,
\r
106 0x00FB, DATA_MODE_CMD, 0x00);
\r
109 fprintf (Out, "%c%04.4x%c",
\r
110 ADDRESS_MODE_CMD, (unsigned int) StartAddress & 0xFFFF,
\r
115 /* Default suffix for C1P object file */
\r
116 #define C1P_SUFFIX ".c1p"
\r
118 int main (int argc, char *argv[])
\r
120 /* Program long options */
\r
121 static const LongOpt OptTab[] = {
\r
122 { "--help", 0, OptHelp},
\r
123 { "--version", 0, OptVersion},
\r
126 /* Initialize input and output file name */
\r
127 const char* InputFile = 0;
\r
128 const char* OutputFile = 0;
\r
129 char *GeneratedOutputFile = 0;
\r
131 /* Initialize file pointers */
\r
132 FILE *InputFileFp = 0;
\r
133 FILE *OutputFileFp = 0;
\r
135 /* Initialize with default start address defined in c1p.cfg */
\r
136 unsigned long StartAddr = 0x400;
\r
140 /* Initialize the cmdline module */
\r
141 InitCmdLine (&argc, &argv, "c1p65");
\r
143 /* Check the parameters */
\r
145 while (I < ArgCount) {
\r
147 /* Get the argument */
\r
148 const char* Arg = ArgVec [I];
\r
150 /* Check for an option */
\r
151 if (Arg[0] == '-') {
\r
155 LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
\r
159 OutputFile = GetArg (&I, 2);
\r
163 StartAddr = CvtNumber (Arg, GetArg (&I, 2));
\r
172 OptVersion (Arg, 0);
\r
176 UnknownOption (Arg);
\r
181 fprintf (stderr, "additional file specs ignored\n");
\r
187 /* Next argument */
\r
191 if (!InputFile) AbEnd ("No input file");
\r
194 const size_t len = strlen(InputFile) + sizeof(C1P_SUFFIX);
\r
196 GeneratedOutputFile = (char *) xmalloc(len);
\r
197 sprintf(GeneratedOutputFile, "%s%s", InputFile, C1P_SUFFIX);
\r
198 OutputFile = GeneratedOutputFile;
\r
201 /* Open input and output files */
\r
202 InputFileFp = fopen(InputFile, "rb");
\r
203 if (!InputFileFp) AbEnd ("Unable to open input file");
\r
205 OutputFileFp = fopen(OutputFile, "wb");
\r
206 if (!OutputFileFp) AbEnd ("Unable to open output file");
\r
208 /* Generate object file */
\r
209 Transform (StartAddr, InputFileFp, OutputFileFp);
\r
212 if (fclose(InputFileFp) == EOF) AbEnd ("Error closing input file");
\r
214 if (fclose(OutputFileFp) == EOF) AbEnd ("Error closing output file");
\r
216 if (GeneratedOutputFile) {
\r
217 xfree(GeneratedOutputFile);
\r
220 return EXIT_SUCCESS;
\r