1
0
mirror of https://github.com/cc65/cc65.git synced 2025-08-12 17:25:11 +00:00

Enter bytes in a loop in data mode

This commit is contained in:
Stephan Mühlstrasser
2014-11-02 23:22:41 +01:00
parent 57a422d064
commit 29801cd45f

View File

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