From 9b505d7b6513e0082df17661674862f72393aee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChlstrasser?= Date: Tue, 16 Jul 2013 22:29:14 +0200 Subject: [PATCH] Created C1P object file generator. --- src/Makefile | 1 + src/c1p65.vcxproj | 94 ++++++++++++++++++++ src/c1p65/main.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 src/c1p65.vcxproj create mode 100644 src/c1p65/main.c diff --git a/src/Makefile b/src/Makefile index 3d0463147..4a80a78fb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,7 @@ ifeq ($(shell echo),) PROGS = ar65 \ + c1p65 \ ca65 \ cc65 \ cl65 \ diff --git a/src/c1p65.vcxproj b/src/c1p65.vcxproj new file mode 100644 index 000000000..2f4ff02fb --- /dev/null +++ b/src/c1p65.vcxproj @@ -0,0 +1,94 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + {4E031DE0-82B4-4204-8529-536626F7E0DF} + Win32Proj + c1p65 + + + + Application + true + v110 + + + + + Application + false + v110 + true + + + + + + + + + + + + + + + true + $(SolutionDir)..\bin\ + $(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\ + + + false + $(SolutionDir)..\bin\ + $(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\ + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + common + + + Console + true + $(IntDir)..\..\common\$(Configuration)\common.lib + + + + + Level3 + + + MaxSpeed + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + common + + + Console + true + true + true + $(IntDir)..\..\common\$(Configuration)\common.lib + + + + + + \ No newline at end of file diff --git a/src/c1p65/main.c b/src/c1p65/main.c new file mode 100644 index 000000000..c15c77a88 --- /dev/null +++ b/src/c1p65/main.c @@ -0,0 +1,219 @@ +/* Object file conversion utility for Challenger 1P + + by Stephan Muehlstrasser +*/ + + +#include +#include +#include +#include +#include +#include + +/* 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: )\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; +}