-/* Object file conversion utility for Challenger 1P
-
- by Stephan Muehlstrasser
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-
-/* common stuff */
-#include "abend.h"
-#include "cmdline.h"
-#include "fname.h"
-#include "chartype.h"
-#include "target.h"
-#include "version.h"
-#include "xmalloc.h"
-
-static void Usage (void)
-{
- printf (
- "Usage: %s [options] file\n"
- "Short options:\n"
- " -V\t\t\tPrint the version number\n"
- " -h\t\t\tHelp (this text)\n"
- " -o name\t\tName the C1P output file (default: <input.c1p>)\n"
- " -S addr\t\tLoad address (default 0x400)\n"
- "\n"
- "Long options:\n"
- " --help\t\tHelp (this text)\n"
- " --version\t\tPrint the version number\n",
- ProgName);
-}
-
-static void OptHelp (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Print usage information and exit */
-{
- Usage ();
- exit (EXIT_SUCCESS);
-}
-
-
-static void OptVersion (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
-/* Print the program version */
-{
- fprintf (stderr, "grc65 V%s\n", GetVersionAsString ());
-}
-
-
-static unsigned long CvtNumber (const char* Arg, const char* Number)
-/* Convert a number from a string. Allow '$' and '0x' prefixes for hex
- * numbers. Duplicated from ld65's main.c.
- */
-{
- unsigned long Val;
- int Converted;
-
- /* Convert */
- if (*Number == '$') {
- ++Number;
- Converted = sscanf (Number, "%lx", &Val);
- } else {
- Converted = sscanf (Number, "%li", (long*)&Val);
- }
-
- /* Check if we do really have a number */
- if (Converted != 1) {
- AbEnd ("Invalid number given in argument: %s\n", Arg);
- }
-
- /* Return the result */
- return Val;
-}
-
-/* Commands of C1P PROM monitor */
-#define ADDRESS_MODE_CMD '.'
-#define DATA_MODE_CMD '/'
-#define EXECUTE_CMD 'G'
-
-/* Transform the cc65 executable binary into a series of
- commands that make the C1P PROM monitor load the bytes
- into memory.
-*/
-static void Transform (unsigned long StartAddress, FILE *In, FILE *Out)
-{
- int c;
- unsigned long CurrentAddress;
-
- /* Loop over all input bytes, position to current address,
- switch to data mod, output input byte
- */
- for (CurrentAddress = StartAddress, c = getc(In);
- c != EOF;
- c = getc(In), CurrentAddress += 1) {
- fprintf (Out, "%c%04.4X%c%02.2X",
- ADDRESS_MODE_CMD, (unsigned int) CurrentAddress & 0xFFFF,
- DATA_MODE_CMD, (unsigned int) c & 0xFF);
- }
-
- /* And execute
- fprintf (Out, "%c%04.4x%c",
- ADDRESS_MODE_CMD, (unsigned int) StartAddress & 0xFFFF,
- EXECUTE_CMD);
- */
-}
-
-/* Default suffix for C1P object file */
-#define C1P_SUFFIX ".c1p"
-
-int main (int argc, char *argv[])
-{
- /* Program long options */
- static const LongOpt OptTab[] = {
- { "--help", 0, OptHelp},
- { "--version", 0, OptVersion},
- };
-
- /* Initialize input and output file name */
- const char* InputFile = 0;
- const char* OutputFile = 0;
- char *GeneratedOutputFile = 0;
-
- /* Initialize file pointers */
- FILE *InputFileFp = 0;
- FILE *OutputFileFp = 0;
-
- /* Initialize with default start address defined in c1p.cfg */
- unsigned long StartAddr = 0x400;
-
- unsigned int I;
-
- /* Initialize the cmdline module */
- InitCmdLine (&argc, &argv, "c1p65");
-
- /* Check the parameters */
- I = 1;
- while (I < ArgCount) {
-
- /* Get the argument */
- const char* Arg = ArgVec [I];
-
- /* Check for an option */
- if (Arg[0] == '-') {
- switch (Arg[1]) {
-
- case '-':
- LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
- break;
-
- case 'o':
- OutputFile = GetArg (&I, 2);
- break;
-
- case 'S':
- StartAddr = CvtNumber (Arg, GetArg (&I, 2));
- break;
-
- case 'h':
- case '?':
- OptHelp (Arg, 0);
- break;
-
- case 'V':
- OptVersion (Arg, 0);
- break;
-
- default:
- UnknownOption (Arg);
- }
-
- } else {
- if (InputFile) {
- fprintf (stderr, "additional file specs ignored\n");
- } else {
- InputFile = Arg;
- }
- }
-
- /* Next argument */
- ++I;
- }
-
- if (!InputFile) AbEnd ("No input file");
-
- if (!OutputFile) {
- const size_t len = strlen(InputFile) + sizeof(C1P_SUFFIX);
-
- GeneratedOutputFile = (char *) xmalloc(len);
- sprintf(GeneratedOutputFile, "%s%s", InputFile, C1P_SUFFIX);
- OutputFile = GeneratedOutputFile;
- }
-
- /* Open input and output files */
- InputFileFp = fopen(InputFile, "rb");
- if (!InputFileFp) AbEnd ("Unable to open input file");
-
- OutputFileFp = fopen(OutputFile, "wb");
- if (!OutputFileFp) AbEnd ("Unable to open output file");
-
- /* Generate object file */
- Transform (StartAddr, InputFileFp, OutputFileFp);
-
- /* Cleanup */
- if (fclose(InputFileFp) == EOF) AbEnd ("Error closing input file");
-
- if (fclose(OutputFileFp) == EOF) AbEnd ("Error closing output file");
-
- if (GeneratedOutputFile) {
- xfree(GeneratedOutputFile);
- }
-
- return EXIT_SUCCESS;
-}
+/* Object file conversion utility for Challenger 1P\r
+\r
+ by Stephan Muehlstrasser\r
+*/\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+#include <time.h>\r
+\r
+/* common stuff */\r
+#include "abend.h"\r
+#include "cmdline.h"\r
+#include "fname.h"\r
+#include "chartype.h"\r
+#include "target.h"\r
+#include "version.h"\r
+#include "xmalloc.h"\r
+\r
+static void Usage (void)\r
+{\r
+ printf (\r
+ "Usage: %s [options] file\n"\r
+ "Short options:\n"\r
+ " -V\t\t\tPrint the version number\n"\r
+ " -h\t\t\tHelp (this text)\n"\r
+ " -o name\t\tName the C1P output file (default: <input.c1p>)\n"\r
+ " -S addr\t\tLoad address (default 0x400)\n"\r
+ "\n"\r
+ "Long options:\n"\r
+ " --help\t\tHelp (this text)\n"\r
+ " --version\t\tPrint the version number\n",\r
+ ProgName);\r
+}\r
+\r
+static void OptHelp (const char* Opt attribute ((unused)),\r
+ const char* Arg attribute ((unused)))\r
+/* Print usage information and exit */\r
+{\r
+ Usage ();\r
+ exit (EXIT_SUCCESS);\r
+}\r
+\r
+\r
+static void OptVersion (const char* Opt attribute ((unused)),\r
+ const char* Arg attribute ((unused)))\r
+/* Print the program version */\r
+{\r
+ fprintf (stderr, "grc65 V%s\n", GetVersionAsString ());\r
+}\r
+\r
+\r
+static unsigned long CvtNumber (const char* Arg, const char* Number)\r
+/* Convert a number from a string. Allow '$' and '0x' prefixes for hex\r
+ * numbers. Duplicated from ld65's main.c.\r
+ */\r
+{\r
+ unsigned long Val;\r
+ int Converted;\r
+\r
+ /* Convert */\r
+ if (*Number == '$') {\r
+ ++Number;\r
+ Converted = sscanf (Number, "%lx", &Val);\r
+ } else {\r
+ Converted = sscanf (Number, "%li", (long*)&Val);\r
+ }\r
+\r
+ /* Check if we do really have a number */\r
+ if (Converted != 1) {\r
+ AbEnd ("Invalid number given in argument: %s\n", Arg);\r
+ }\r
+\r
+ /* Return the result */\r
+ return Val;\r
+}\r
+\r
+/* Commands of C1P PROM monitor */\r
+#define ADDRESS_MODE_CMD '.'\r
+#define DATA_MODE_CMD '/'\r
+#define EXECUTE_CMD 'G'\r
+#define DATA_MODE_ADDRESS 0x00FB\r
+\r
+/* Transform the cc65 executable binary into a series of\r
+ commands that make the C1P PROM monitor load the bytes\r
+ into memory.\r
+*/\r
+static void Transform (unsigned long StartAddress, FILE *In, FILE *Out)\r
+{\r
+ int c;\r
+\r
+ /* Position to the start address */\r
+ fprintf(Out, "%c%04.4X%c", ADDRESS_MODE_CMD,\r
+ StartAddress & 0xFFFF, DATA_MODE_CMD);\r
+\r
+ /* Loop over all input bytes and enter them one by one */\r
+ for (c = getc(In); c != EOF; c = getc(In)) {\r
+ fprintf(Out, "%02.2X\n", (unsigned int) c & 0xFF);\r
+ }\r
+\r
+ /* Store 00 to 0x00FB to enable keyboard input at the end */\r
+ fprintf(Out, "%c%04.4X%c%02.2X\n", ADDRESS_MODE_CMD,\r
+ 0x00FB, DATA_MODE_CMD, 0x00);\r
+\r
+ /* And execute\r
+ fprintf (Out, "%c%04.4x%c",\r
+ ADDRESS_MODE_CMD, (unsigned int) StartAddress & 0xFFFF,\r
+ EXECUTE_CMD);\r
+ */\r
+} \r
+\r
+/* Default suffix for C1P object file */\r
+#define C1P_SUFFIX ".c1p"\r
+\r
+int main (int argc, char *argv[])\r
+{\r
+ /* Program long options */\r
+ static const LongOpt OptTab[] = {\r
+ { "--help", 0, OptHelp},\r
+ { "--version", 0, OptVersion},\r
+ };\r
+\r
+ /* Initialize input and output file name */\r
+ const char* InputFile = 0;\r
+ const char* OutputFile = 0;\r
+ char *GeneratedOutputFile = 0;\r
+\r
+ /* Initialize file pointers */\r
+ FILE *InputFileFp = 0;\r
+ FILE *OutputFileFp = 0;\r
+\r
+ /* Initialize with default start address defined in c1p.cfg */\r
+ unsigned long StartAddr = 0x400;\r
+\r
+ unsigned int I;\r
+\r
+ /* Initialize the cmdline module */\r
+ InitCmdLine (&argc, &argv, "c1p65");\r
+\r
+ /* Check the parameters */\r
+ I = 1;\r
+ while (I < ArgCount) {\r
+\r
+ /* Get the argument */\r
+ const char* Arg = ArgVec [I];\r
+\r
+ /* Check for an option */\r
+ if (Arg[0] == '-') {\r
+ switch (Arg[1]) {\r
+\r
+ case '-':\r
+ LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));\r
+ break;\r
+\r
+ case 'o':\r
+ OutputFile = GetArg (&I, 2);\r
+ break;\r
+\r
+ case 'S':\r
+ StartAddr = CvtNumber (Arg, GetArg (&I, 2));\r
+ break;\r
+\r
+ case 'h':\r
+ case '?':\r
+ OptHelp (Arg, 0);\r
+ break;\r
+\r
+ case 'V':\r
+ OptVersion (Arg, 0);\r
+ break;\r
+\r
+ default:\r
+ UnknownOption (Arg);\r
+ }\r
+\r
+ } else {\r
+ if (InputFile) {\r
+ fprintf (stderr, "additional file specs ignored\n");\r
+ } else {\r
+ InputFile = Arg;\r
+ }\r
+ }\r
+\r
+ /* Next argument */\r
+ ++I;\r
+ }\r
+\r
+ if (!InputFile) AbEnd ("No input file");\r
+\r
+ if (!OutputFile) {\r
+ const size_t len = strlen(InputFile) + sizeof(C1P_SUFFIX);\r
+ \r
+ GeneratedOutputFile = (char *) xmalloc(len);\r
+ sprintf(GeneratedOutputFile, "%s%s", InputFile, C1P_SUFFIX);\r
+ OutputFile = GeneratedOutputFile;\r
+ }\r
+\r
+ /* Open input and output files */\r
+ InputFileFp = fopen(InputFile, "rb");\r
+ if (!InputFileFp) AbEnd ("Unable to open input file");\r
+\r
+ OutputFileFp = fopen(OutputFile, "wb");\r
+ if (!OutputFileFp) AbEnd ("Unable to open output file");\r
+\r
+ /* Generate object file */\r
+ Transform (StartAddr, InputFileFp, OutputFileFp);\r
+\r
+ /* Cleanup */\r
+ if (fclose(InputFileFp) == EOF) AbEnd ("Error closing input file");\r
+\r
+ if (fclose(OutputFileFp) == EOF) AbEnd ("Error closing output file");\r
+\r
+ if (GeneratedOutputFile) {\r
+ xfree(GeneratedOutputFile);\r
+ }\r
+\r
+ return EXIT_SUCCESS;\r
+}\r