From 631aeb2a8d27b4caa4df7037a96db43fdb5b56de Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 11 Feb 2003 22:33:12 +0000 Subject: [PATCH] Working git-svn-id: svn://svn.cc65.org/cc65/trunk@1971 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/co65/convert.c | 491 +++++++++++++++++++++++++++++++++++++++ src/co65/convert.h | 68 ++++++ src/co65/main.c | 342 ++++----------------------- src/co65/make/gcc.mak | 4 +- src/co65/make/watcom.mak | 4 +- src/co65/model.c | 94 ++++++++ src/co65/model.h | 84 +++++++ src/co65/o65.h | 30 ++- 8 files changed, 801 insertions(+), 316 deletions(-) create mode 100644 src/co65/convert.c create mode 100644 src/co65/convert.h create mode 100644 src/co65/model.c create mode 100644 src/co65/model.h diff --git a/src/co65/convert.c b/src/co65/convert.c new file mode 100644 index 000000000..ed9ff15a1 --- /dev/null +++ b/src/co65/convert.c @@ -0,0 +1,491 @@ +/*****************************************************************************/ +/* */ +/* convert.c */ +/* */ +/* Actual conversion routines for the co65 object file converter */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include +#include +#include + +/* common */ +#include "debugflag.h" +#include "print.h" +#include "version.h" +#include "xmalloc.h" +#include "xsprintf.h" + +/* co65 */ +#include "error.h" +#include "global.h" +#include "model.h" +#include "o65.h" +#include "convert.h" + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static void PrintO65Stats (const O65Data* D) +/* Print information about the O65 file if --verbose is given */ +{ + Print (stdout, 1, "Size of text segment: %5lu\n", D->Header.tlen); + Print (stdout, 1, "Size of data segment: %5lu\n", D->Header.dlen); + Print (stdout, 1, "Size of bss segment: %5lu\n", D->Header.blen); + Print (stdout, 1, "Size of zeropage segment: %5lu\n", D->Header.zlen); + Print (stdout, 1, "Number of imports: %5u\n", CollCount (&D->Imports)); + Print (stdout, 1, "Number of exports: %5u\n", CollCount (&D->Exports)); + Print (stdout, 1, "Number of text segment relocations: %5u\n", CollCount (&D->TextReloc)); + Print (stdout, 1, "Number of data segment relocations: %5u\n", CollCount (&D->DataReloc)); +} + + + +static void SetupSegLabels (FILE* F) +/* Setup the segment label names */ +{ + if (BssLabel) { + fprintf (F, ".export\t\t%s\n", BssLabel); + } else { + BssLabel = xstrdup ("BSS"); + } + if (CodeLabel) { + fprintf (F, ".export\t\t%s\n", CodeLabel); + } else { + CodeLabel = xstrdup ("CODE"); + } + if (DataLabel) { + fprintf (F, ".export\t\t%s\n", DataLabel); + } else { + DataLabel = xstrdup ("DATA"); + } + if (ZeropageLabel) { + fprintf (F, ".export\t\t%s\n", ZeropageLabel); + } else { + ZeropageLabel = xstrdup ("ZEROPAGE"); + } +} + + + +static void ConvertImports (FILE* F, const O65Data* D) +/* Convert the imports */ +{ + unsigned I; + + if (CollCount (&D->Imports) > 0) { + for (I = 0; I < CollCount (&D->Imports); ++I) { + + /* Get the next import */ + const O65Import* Import = CollConstAt (&D->Imports, I); + + /* Import it by name */ + fprintf (F, ".import\t%s\n", Import->Name); + } + fprintf (F, "\n"); + } +} + + + +static void ConvertExports (FILE* F, const O65Data* D) +/* Convert the exports */ +{ + unsigned I; + + if (CollCount (&D->Exports) > 0) { + for (I = 0; I < CollCount (&D->Exports); ++I) { + + /* Get the next import */ + const O65Export* Export = CollConstAt (&D->Exports, I); + + /* First define it */ + fprintf (F, "%s = XXX\n", Export->Name); /* ### */ + + /* Then export it by name */ + fprintf (F, ".export\t%s\n", Export->Name); + } + fprintf (F, "\n"); + } +} + + + +static const char* LabelPlusOffs (const char* Label, long Offs) +/* Generate "Label+xxx" in a static buffer and return a pointer to the buffer */ +{ + static char Buf[256]; + xsprintf (Buf, sizeof (Buf), "%s%+ld", Label, Offs); + return Buf; +} + + + +static const char* RelocExpr (const O65Data* D, const O65Reloc* R, unsigned long Val) +/* Generate the segment relative relocation expression */ +{ + const O65Import* Import; + + switch (R->SegID) { + + case O65_SEGID_UNDEF: + if (R->SymIdx >= CollCount (&D->Imports)) { + Error ("Import index out of range (input file corrupt)"); + } + Import = CollConstAt (&D->Imports, R->SymIdx); + return LabelPlusOffs (Import->Name, Val); + + case O65_SEGID_TEXT: + return LabelPlusOffs (CodeLabel, Val - D->Header.tbase); + + case O65_SEGID_DATA: + return LabelPlusOffs (DataLabel, Val - D->Header.dbase); + + case O65_SEGID_BSS: + return LabelPlusOffs (BssLabel, Val - D->Header.bbase); + + case O65_SEGID_ZP: + return LabelPlusOffs (ZeropageLabel, Val - D->Header.zbase); + + case O65_SEGID_ABS: + return LabelPlusOffs ("", Val); + + default: + Internal ("Cannot handle this segment reference in reloc entry"); + } + + /* NOTREACHED */ + return 0; +} + + + +static void ConvertSeg (FILE* F, const O65Data* D, const Collection* Relocs, + const unsigned char* Data, unsigned long Size) +/* Convert one segment */ +{ + const O65Reloc* R; + unsigned RIdx; + unsigned long Byte; + + /* Get the pointer to the first relocation entry if there are any */ + R = (CollCount (Relocs) > 0)? CollConstAt (Relocs, 0) : 0; + + /* Initialize for the loop */ + RIdx = 0; + Byte = 0; + + /* Walk over the segment data */ + while (Byte < Size) { + + if (R && R->Offs == Byte) { + /* We've reached an entry that must be relocated */ + unsigned long Val; + switch (R->Type) { + + case O65_RTYPE_WORD: + if (Byte >= Size - 1) { + Error ("Found WORD relocation, but not enough bytes left"); + } else { + Val = (Data[Byte+1] << 8) + Data[Byte]; + Byte += 2; + fprintf (F, "\t.word\t%s\n", RelocExpr (D, R, Val)); + } + break; + + case O65_RTYPE_HIGH: + Val = (Data[Byte++] << 8) + R->Val; + fprintf (F, "\t.byte\t>(%s)\n", RelocExpr (D, R, Val)); + break; + + case O65_RTYPE_LOW: + Val = Data[Byte++]; + fprintf (F, "\t.byte\t<(%s)\n", RelocExpr (D, R, Val)); + break; + + case O65_RTYPE_SEGADDR: + if (Byte >= Size - 2) { + Error ("Found SEGADDR relocation, but not enough bytes left"); + } else { + Val = (((unsigned long) Data[Byte+2]) << 16) + + (((unsigned long) Data[Byte+1]) << 8) + + (((unsigned long) Data[Byte+0]) << 0) + + R->Val; + Byte += 3; + fprintf (F, "\t.faraddr\t%s\n", RelocExpr (D, R, Val)); + } + break; + + case O65_RTYPE_SEG: + /* FALLTHROUGH for now */ + default: + Internal ("Cannot handle relocation type %d at %lu", + R->Type, Byte); + } + + /* Get the next relocation entry */ + if (++RIdx < CollCount (Relocs)) { + R = CollConstAt (Relocs, RIdx); + } else { + R = 0; + } + + } else { + /* Just a constant value */ + fprintf (F, "\t.byte\t$%02X\n", Data[Byte++]); + } + } + + fprintf (F, "\n"); +} + + + +static void ConvertCodeSeg (FILE* F, const O65Data* D) +/* Do code segment conversion */ +{ + /* Header */ + fprintf (F, + ";\n; CODE SEGMENT\n;\n" + ".segment\t\"%s\"\n" + "%s:\n", + CodeSeg, + CodeLabel); + + /* Segment data */ + ConvertSeg (F, D, &D->TextReloc, D->Text, D->Header.tlen); +} + + + +static void ConvertDataSeg (FILE* F, const O65Data* D) +/* Do data segment conversion */ +{ + /* Header */ + fprintf (F, + ";\n; DATA SEGMENT\n;\n" + ".segment\t\"%s\"\n" + "%s:\n", + DataSeg, + DataLabel); + + /* Segment data */ + ConvertSeg (F, D, &D->DataReloc, D->Data, D->Header.dlen); +} + + + +static void ConvertBssSeg (FILE* F, const O65Data* D) +/* Do bss segment conversion */ +{ + /* Header */ + fprintf (F, + ";\n; BSS SEGMENT\n;\n" + ".segment\t\"%s\"\n" + "%s:\n", + BssSeg, + BssLabel); + + /* Segment data */ + fprintf (F, "\t.res\t%lu\n", D->Header.blen); + fprintf (F, "\n"); +} + + + +static void ConvertZeropageSeg (FILE* F, const O65Data* D) +/* Do zeropage segment conversion */ +{ + /* Header */ + fprintf (F, ";\n; ZEROPAGE SEGMENT\n;\n"); + + if (Model == O65_MODEL_CC65_MODULE) { + /* o65 files of type cc65-module are linked together with a definition + * file for the zero page, but the zero page is not allocated in the + * module itself, but the locations are mapped to the zp locations of + * the main file. + */ + fprintf (F, ".import\t__ZP_START__\t\t; Linker generated symbol\n"); + fprintf (F, "%s = __ZP_START__\n", ZeropageLabel); + } else { + /* Header */ + fprintf (F, ".segment\t\"%s\", zeropage\n%s:\n", ZeropageSeg, ZeropageLabel); + + /* Segment data */ + fprintf (F, "\t.res\t%lu\n", D->Header.zlen); + } + fprintf (F, "\n"); +} + + + +void Convert (const O65Data* D, const char* OutputFile) +/* Convert the o65 file in D using the given output file. */ +{ + FILE* F; + unsigned I; + char* Author = 0; + + /* For now, we do only accept o65 files generated by the ld65 linker which + * have a specific format. + */ + if (!Debug && D->Header.mode != O65_MODE_CC65) { + Error ("Cannot convert o65 files of this type"); + } + + /* Output statistics */ + PrintO65Stats (D); + + /* Walk through the options and print them if verbose mode is enabled. + * Check for a os=cc65 option and bail out if we didn't find one (for + * now - later we switch to special handling). + */ + for (I = 0; I < CollCount (&D->Options); ++I) { + + /* Get the next option */ + const O65Option* O = CollConstAt (&D->Options, I); + + /* Check the type of the option */ + switch (O->Type) { + + case O65_OPT_FILENAME: + Print (stdout, 1, "O65 filename option: `%s'\n", + GetO65OptionText (O)); + break; + + case O65_OPT_OS: + if (O->Len == 2) { + Warning ("Operating system option without data found"); + } else { + Print (stdout, 1, "O65 operating system option: `%s'\n", + GetO65OSName (O->Data[0])); + switch (O->Data[0]) { + case O65_OS_CC65_MODULE: + if (Model != O65_MODEL_NONE && + Model != O65_MODEL_CC65_MODULE) { + Warning ("Wrong o65 model"); + } else { + Model = O65_MODEL_CC65_MODULE; + } + break; + } + } + break; + + case O65_OPT_ASM: + Print (stdout, 1, "O65 assembler option: `%s'\n", + GetO65OptionText (O)); + break; + + case O65_OPT_AUTHOR: + if (Author) { + xfree (Author); + } + Author = xstrdup (GetO65OptionText (O)); + Print (stdout, 1, "O65 author option: `%s'\n", Author); + break; + + case O65_OPT_TIMESTAMP: + Print (stdout, 1, "O65 timestamp option: `%s'\n", + GetO65OptionText (O)); + break; + + default: + Warning ("Found unknown option, type %d, length %d", + O->Type, O->Len); + break; + } + } + + /* Open the output file */ + F = fopen (OutputFile, "wb"); + if (F == 0) { + Error ("Cannot open `%s': %s", OutputFile, strerror (errno)); + } + + /* Create a header */ + fprintf (F, ";\n; File generated by co65 v %u.%u.%u using model `%s'\n;\n", + VER_MAJOR, VER_MINOR, VER_PATCH, GetModelName (Model)); + + /* Select the CPU */ + if ((D->Header.mode & O65_CPU_MASK) == O65_CPU_65816) { + fprintf (F, ".p816\n"); + } + + /* Object file options */ + fprintf (F, ".fopt\t\tcompiler,\"co65 v %u.%u.%u\"\n", + VER_MAJOR, VER_MINOR, VER_PATCH); + if (Author) { + fprintf (F, ".fopt\t\tauthor, \"%s\"\n", Author); + xfree (Author); + Author = 0; + } + + /* Several other assembler options */ + fprintf (F, ".case\t\ton\n"); + fprintf (F, ".debuginfo\t%s\n", (DebugInfo != 0)? "on" : "off"); + + /* Setup/export the segment labels */ + SetupSegLabels (F); + + /* End of header */ + fprintf (F, "\n"); + + /* Imported identifiers */ + ConvertImports (F, D); + + /* Exported identifiers */ + ConvertExports (F, D); + + /* Code segment */ + ConvertCodeSeg (F, D); + + /* Data segment */ + ConvertDataSeg (F, D); + + /* BSS segment */ + ConvertBssSeg (F, D); + + /* Zero page segment */ + ConvertZeropageSeg (F, D); + + /* End of data */ + fprintf (F, ".end\n"); + fclose (F); +} + + + diff --git a/src/co65/convert.h b/src/co65/convert.h new file mode 100644 index 000000000..5773fd461 --- /dev/null +++ b/src/co65/convert.h @@ -0,0 +1,68 @@ +/*****************************************************************************/ +/* */ +/* convert.h */ +/* */ +/* Actual conversion routines for the co65 object file converter */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef CONVERT_H +#define CONVERT_H + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Forward definition */ +struct O65Data; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void Convert (const struct O65Data* D, const char* OutputFile); +/* Convert the o65 file in D using the given output file. */ + + + +/* End of convert.h */ + +#endif + + + diff --git a/src/co65/main.c b/src/co65/main.c index 4da4a8433..db07b6a08 100644 --- a/src/co65/main.c +++ b/src/co65/main.c @@ -42,6 +42,7 @@ /* common */ #include "chartype.h" #include "cmdline.h" +#include "debugflag.h" #include "fname.h" #include "print.h" #include "segnames.h" @@ -50,8 +51,10 @@ #include "xsprintf.h" /* co65 */ +#include "convert.h" #include "error.h" #include "global.h" +#include "model.h" #include "o65.h" @@ -71,6 +74,7 @@ static void Usage (void) " -V\t\t\tPrint the version number\n" " -g\t\t\tAdd debug info to object file\n" " -h\t\t\tHelp (this text)\n" + " -m model\t\tOverride the o65 model\n" " -o name\t\tName the output file\n" " -v\t\t\tIncrease verbosity\n" "\n" @@ -83,6 +87,7 @@ static void Usage (void) " --data-name seg\tSet the name of the DATA segment\n" " --debug-info\t\tAdd debug info to object file\n" " --help\t\tHelp (this text)\n" + " --o65-model model\tOverride the o65 model\n" " --verbose\t\tIncrease verbosity\n" " --version\t\tPrint the version number\n" " --zeropage-label name\tDefine and export a ZEROPAGE segment label\n" @@ -195,6 +200,15 @@ static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) +static void OptDebug (const char* Opt attribute ((unused)), + const char* Arg attribute ((unused))) +/* Enable debugging code */ +{ + ++Debug; +} + + + static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add debug info to the object file */ @@ -214,6 +228,18 @@ static void OptHelp (const char* Opt attribute ((unused)), +static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg) +/* Handle the --o65-model option */ +{ + /* Search for the model name */ + Model = FindModel (Arg); + if (Model == O65_MODEL_INVALID) { + Error ("Unknown o65 model `%s'", Arg); + } +} + + + static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ @@ -258,312 +284,18 @@ static void OptZeropageName (const char* Opt attribute ((unused)), const char* A -static const char* SegReloc (const O65Data* D, const O65Reloc* R, unsigned long Val) -{ - static char Buf[256]; - const O65Import* Import; - - switch (R->SegID) { - - case O65_SEGID_UNDEF: - if (R->SymIdx >= CollCount (&D->Imports)) { - Error ("Import index out of range (input file corrupt)"); - } - Import = CollConstAt (&D->Imports, R->SymIdx); - xsprintf (Buf, sizeof (Buf), "%s%+ld", Import->Name, (long) Val); - break; - - case O65_SEGID_TEXT: - xsprintf (Buf, sizeof (Buf), "%s%+ld", CodeLabel, (long) (Val - D->Header.tbase)); - break; - - case O65_SEGID_DATA: - xsprintf (Buf, sizeof (Buf), "%s%+ld", DataLabel, (long) (Val - D->Header.dbase)); - break; - - case O65_SEGID_BSS: - xsprintf (Buf, sizeof (Buf), "%s%+ld", BssLabel, (long) (Val - D->Header.bbase)); - break; - - case O65_SEGID_ZP: - xsprintf (Buf, sizeof (Buf), "%s%+ld", ZeropageLabel, (long) Val - D->Header.zbase); - break; - - case O65_SEGID_ABS: - Error ("Relocation entry contains O65_SEGID_ABS"); - break; - - default: - Internal ("Cannot handle this segment reference in reloc entry"); - } - - return Buf; -} - - - -static void ConvertSeg (FILE* F, const O65Data* D, const Collection* Relocs, - const unsigned char* Data, unsigned long Size) -/* Convert one segment */ -{ - const O65Reloc* R; - unsigned RIdx; - unsigned long Byte; - - /* Get the pointer to the first relocation entry if there are any */ - R = (CollCount (Relocs) > 0)? CollConstAt (Relocs, 0) : 0; - - /* Initialize for the loop */ - RIdx = 0; - Byte = 0; - - /* Walk over the segment data */ - while (Byte < Size) { - - if (R && R->Offs == Byte) { - /* We've reached an entry that must be relocated */ - unsigned long Val; - switch (R->Type) { - - case O65_RTYPE_WORD: - if (Byte >= Size - 1) { - Error ("Found WORD relocation, but not enough bytes left"); - } else { - Val = (Data[Byte+1] << 8) + Data[Byte]; - Byte += 2; - fprintf (F, "\t.word\t%s\n", SegReloc (D, R, Val)); - } - break; - - case O65_RTYPE_HIGH: - Val = (Data[Byte++] << 8) + R->Val; - fprintf (F, "\t.byte\t>(%s)\n", SegReloc (D, R, Val)); - break; - - case O65_RTYPE_LOW: - Val = Data[Byte++]; - fprintf (F, "\t.byte\t<(%s)\n", SegReloc (D, R, Val)); - break; - - case O65_RTYPE_SEGADDR: - if (Byte >= Size - 2) { - Error ("Found SEGADDR relocation, but not enough bytes left"); - } else { - Val = (((unsigned long) Data[Byte+2]) << 16) + - (((unsigned long) Data[Byte+1]) << 8) + - (((unsigned long) Data[Byte+0]) << 0) + - R->Val; - Byte += 3; - fprintf (F, "\t.faraddr\t%s\n", SegReloc (D, R, Val)); - } - break; - - case O65_RTYPE_SEG: - /* FALLTHROUGH for now */ - default: - Internal ("Cannot handle relocation type %d at %lu", - R->Type, Byte); - } - - /* Get the next relocation entry */ - if (++RIdx < CollCount (Relocs)) { - R = CollConstAt (Relocs, RIdx); - } else { - R = 0; - } - - } else { - /* Just a constant value */ - fprintf (F, "\t.byte\t$%02X\n", Data[Byte++]); - } - } - - fprintf (F, "\n"); -} - - - -static void Convert (void) +static void ConvertOneFile (const char* InputFile, const char* OutputFile) /* Do file conversion */ { - FILE* F; - unsigned I; - int cc65; - char* Author = 0; - /* Read the o65 file into memory */ - O65Data* D = ReadO65File (InputName); - - /* For now, we do only accept o65 files generated by the ld65 linker which - * have a specific format. - */ - if (D->Header.mode != O65_MODE_CC65) { - Error ("Cannot convert o65 files of this type"); - } - - /* Output statistics */ - Print (stdout, 1, "Size of text segment: %5lu\n", D->Header.tlen); - Print (stdout, 1, "Size of data segment: %5lu\n", D->Header.dlen); - Print (stdout, 1, "Size of bss segment: %5lu\n", D->Header.blen); - Print (stdout, 1, "Size of zeropage segment: %5lu\n", D->Header.zlen); - Print (stdout, 1, "Number of imports: %5u\n", CollCount (&D->Imports)); - Print (stdout, 1, "Number of exports: %5u\n", CollCount (&D->Exports)); - Print (stdout, 1, "Number of text segment relocations: %5u\n", CollCount (&D->TextReloc)); - Print (stdout, 1, "Number of data segment relocations: %5u\n", CollCount (&D->DataReloc)); - - /* Walk through the options and print them if verbose mode is enabled. - * Check for a os=cc65 option and bail out if we didn't find one (for - * now - later we switch to special handling). - */ - cc65 = 0; - for (I = 0; I < CollCount (&D->Options); ++I) { - - /* Get the next option */ - const O65Option* O = CollConstAt (&D->Options, I); - - /* Check the type */ - switch (O->Type) { - case O65_OPT_FILENAME: - Print (stdout, 1, "O65 filename option: `%s'\n", - GetO65OptionText (O)); - break; - case O65_OPT_OS: - if (O->Len == 2) { - Warning ("Operating system option without data found"); - } else { - cc65 = (O->Data[0] == O65_OS_CC65_MODULE); - Print (stdout, 1, "O65 operating system option: `%s'\n", - GetO65OSName (O->Data[0])); - } - break; - case O65_OPT_ASM: - Print (stdout, 1, "O65 assembler option: `%s'\n", - GetO65OptionText (O)); - break; - case O65_OPT_AUTHOR: - if (Author) { - xfree (Author); - } - Author = xstrdup (GetO65OptionText (O)); - Print (stdout, 1, "O65 author option: `%s'\n", Author); - break; - case O65_OPT_TIMESTAMP: - Print (stdout, 1, "O65 timestamp option: `%s'\n", - GetO65OptionText (O)); - break; - default: - Warning ("Found unknown option, type %d, length %d", - O->Type, O->Len); - break; - } - } - - /* Open the output file */ - F = fopen (OutputName, "wb"); - if (F == 0) { - Error ("Cannot open `%s': %s", OutputName, strerror (errno)); - } - - /* Create a header */ - fprintf (F, ";\n; File generated by co65 v %u.%u.%u\n;\n", - VER_MAJOR, VER_MINOR, VER_PATCH); - - /* Select the CPU */ - if ((D->Header.mode & O65_CPU_MASK) == O65_CPU_65816) { - fprintf (F, "\t.p816\n"); - } - - /* Object file options */ - fprintf (F, "\t.fopt\t\tcompiler,\"co65 v %u.%u.%u\"\n", - VER_MAJOR, VER_MINOR, VER_PATCH); - if (Author) { - fprintf (F, "\t.fopt\t\tauthor, \"%s\"\n", Author); - xfree (Author); - Author = 0; - } - - /* Several other assembler options */ - fprintf (F, "\t.case\t\ton\n"); - fprintf (F, "\t.debuginfo\t%s\n", (DebugInfo != 0)? "on" : "off"); + O65Data* D = ReadO65File (InputFile); - /* Setup/export the segment labels */ - if (BssLabel) { - fprintf (F, "\t.export\t\t%s\n", BssLabel); - } else { - BssLabel = xstrdup ("__BSS__"); - } - if (CodeLabel) { - fprintf (F, "\t.export\t\t%s\n", CodeLabel); - } else { - CodeLabel = xstrdup ("__CODE__"); - } - if (DataLabel) { - fprintf (F, "\t.export\t\t%s\n", DataLabel); - } else { - DataLabel = xstrdup ("__DATA__"); - } - if (ZeropageLabel) { - fprintf (F, "\t.export\t\t%s\n", ZeropageLabel); - } else { - /* If this is a cc65 module, override the name for the zeropage segment */ - if (cc65) { - ZeropageLabel = "__ZP_START__"; - fprintf (F, "\t.import\t\t__ZP_START__\t; Linker generated symbol\n"); - } else { - ZeropageLabel = xstrdup ("__ZEROPAGE__"); - } - } - - /* End of header */ - fprintf (F, "\n"); - - /* Imported identifiers */ - if (CollCount (&D->Imports) > 0) { - for (I = 0; I < CollCount (&D->Imports); ++I) { - - /* Get the next import */ - O65Import* Import = CollAtUnchecked (&D->Imports, I); - - /* Import it by name */ - fprintf (F, "\t.import\t%s\n", Import->Name); - } - fprintf (F, "\n"); - } - - /* Exported identifiers */ - if (CollCount (&D->Exports) > 0) { - for (I = 0; I < CollCount (&D->Exports); ++I) { - - /* Get the next import */ - O65Export* Export = CollAtUnchecked (&D->Exports, I); - - /* First define it */ - fprintf (F, "%s = XXX\n", Export->Name); /* ### */ - - /* The export it by name */ - fprintf (F, "\t.export\t%s\n", Export->Name); - } - fprintf (F, "\n"); - } - - /* Code segment */ - fprintf (F, ".segment\t\"%s\"\n", CodeSeg); - fprintf (F, "%s:\n", CodeLabel); - ConvertSeg (F, D, &D->TextReloc, D->Text, D->Header.tlen); - - /* Data segment */ - fprintf (F, ".segment\t\"%s\"\n", DataSeg); - fprintf (F, "%s:\n", DataLabel); - ConvertSeg (F, D, &D->DataReloc, D->Data, D->Header.dlen); + /* Do the conversion */ + Convert (D, OutputFile); - /* BSS segment */ - fprintf (F, ".segment\t\"%s\"\n", BssSeg); - fprintf (F, "%s:\n", BssLabel); - fprintf (F, "\t.res\t%lu\n", D->Header.blen); - fprintf (F, "\n"); + /* Free the o65 module data */ + /* ### */ - fprintf (F, "\t.end\n"); - fclose (F); } @@ -579,8 +311,10 @@ int main (int argc, char* argv []) { "--code-name", 1, OptCodeName }, { "--data-label", 1, OptDataLabel }, { "--data-name", 1, OptDataName }, + { "--debug", 0, OptDebug }, { "--debug-info", 0, OptDebugInfo }, - { "--help", 0, OptHelp }, + { "--help", 0, OptHelp }, + { "--o65-model", 1, OptO65Model }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, { "--zeropage-label", 1, OptZeropageLabel }, @@ -615,6 +349,10 @@ int main (int argc, char* argv []) OptHelp (Arg, 0); break; + case 'm': + OptO65Model (Arg, GetArg (&I, 2)); + break; + case 'o': OutputName = GetArg (&I, 2); break; @@ -656,7 +394,7 @@ int main (int argc, char* argv []) } /* Do the conversion */ - Convert (); + ConvertOneFile (InputName, OutputName); /* Return an apropriate exit code */ return EXIT_SUCCESS; diff --git a/src/co65/make/gcc.mak b/src/co65/make/gcc.mak index 7b0cb3930..58f2dd40d 100644 --- a/src/co65/make/gcc.mak +++ b/src/co65/make/gcc.mak @@ -10,10 +10,12 @@ CC = gcc EBIND = emxbind LDFLAGS = -OBJS = error.o \ +OBJS = convert.o \ + error.o \ fileio.o \ global.o \ main.o \ + model.o \ o65.o LIBS = $(COMMON)/common.a diff --git a/src/co65/make/watcom.mak b/src/co65/make/watcom.mak index 42f99183a..4adac350b 100644 --- a/src/co65/make/watcom.mak +++ b/src/co65/make/watcom.mak @@ -43,10 +43,12 @@ CFLAGS += -i=..\common # ------------------------------------------------------------------------------ # All library OBJ files -OBJS = error.obj \ +OBJS = convert.obj \ + error.obj \ fileio.obj \ global.obj \ main.obj \ + model.obj \ o65.obj LIBS = ..\common\common.lib diff --git a/src/co65/model.c b/src/co65/model.c new file mode 100644 index 000000000..db0232f63 --- /dev/null +++ b/src/co65/model.c @@ -0,0 +1,94 @@ +/*****************************************************************************/ +/* */ +/* model.c */ +/* */ +/* o65 model definitions for the co65 object file converter */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* common */ +#include "strutil.h" + +/* co65 */ +#include "error.h" +#include "model.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Current model */ +O65Model Model = O65_MODEL_NONE; + +/* Name table */ +static const char* NameTable[O65_MODEL_COUNT] = { + "none", + "cc65-module" +}; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +const char* GetModelName (O65Model M) +/* Map the model to its name. */ +{ + if (M < 0 || M >= O65_MODEL_COUNT) { + Internal ("O65 Model %d not found", M); + } + return NameTable[M]; +} + + + +O65Model FindModel (const char* ModelName) +/* Map a model name to its identifier. Return O65_MODEL_INVALID if the name + * could not be found. Case is ignored when comparing names. + */ +{ + O65Model M; + for (M = O65_MODEL_NONE; M < O65_MODEL_COUNT; ++M) { + if (StrCaseCmp (ModelName, NameTable[M]) == 0) { + return M; + } + } + return O65_MODEL_INVALID; +} + + + diff --git a/src/co65/model.h b/src/co65/model.h new file mode 100644 index 000000000..aa35a8f27 --- /dev/null +++ b/src/co65/model.h @@ -0,0 +1,84 @@ +/*****************************************************************************/ +/* */ +/* model.h */ +/* */ +/* o65 model definitions for the co65 object file converter */ +/* */ +/* */ +/* */ +/* (C) 2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef MODEL_H +#define MODEL_H + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Supported models */ +typedef enum { + O65_MODEL_INVALID = -1, /* Invalid model */ + O65_MODEL_NONE, /* No model given */ + O65_MODEL_CC65_MODULE, + + O65_MODEL_COUNT /* Number of available models */ +} O65Model; + + + +/* Current model */ +extern O65Model Model; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +const char* GetModelName (O65Model M); +/* Map the model to its name. */ + +O65Model FindModel (const char* ModelName); +/* Map a model name to its identifier. Return O65_MODEL_INVALID if the name + * could not be found. Case is ignored when comparing names. + */ + + + +/* End of model.h */ + +#endif + + + diff --git a/src/co65/o65.h b/src/co65/o65.h index e2ee4fa4a..9c88c2ffc 100644 --- a/src/co65/o65.h +++ b/src/co65/o65.h @@ -60,7 +60,8 @@ /* Define a structure for the o65 file header */ -typedef struct { +typedef struct O65Header O65Header; +struct O65Header { char marker[2]; /* Non-C64 marker */ char magic[3]; /* o65 magic */ char version; /* Version number */ @@ -74,38 +75,43 @@ typedef struct { unsigned long zbase; /* Original zp segment address */ unsigned long zlen; /* Size of zp segment */ unsigned long stack; /* Stacksize needed */ -} O65Header; +}; /* o65 option */ -typedef struct { +typedef struct O65Option O65Option; +struct O65Option { unsigned char Len; /* Option length */ unsigned char Type; /* Option type */ unsigned char Data[1]; /* Option data (dynamically allocated) */ -} O65Option; +}; /* o65 relocation entry */ -typedef struct { +typedef struct O65Reloc O65Reloc; +struct O65Reloc { unsigned long Offs; /* Offset in segment */ unsigned char Type; /* Relocation type */ unsigned char SegID; /* Segment ID */ unsigned Val; /* Any offset value needed for relocation */ unsigned long SymIdx; /* Index into list of imported symbols */ -} O65Reloc; +}; /* o65 import */ -typedef struct { +typedef struct O65Import O65Import; +struct O65Import { char Name[1]; /* Name of the import (dynamically allocated) */ -} O65Import; +}; /* o65 export */ -typedef struct { +typedef struct O65Export O65Export; +struct O65Export { unsigned char SegID; /* Segment ID */ unsigned long Val; /* Relocation value */ char Name[1]; /* Name of the export (dynamically allocated) */ -} O65Export; +}; /* Complete o65 file data */ -typedef struct { +typedef struct O65Data O65Data; +struct O65Data { O65Header Header; /* File header */ Collection Options; /* O65 options */ unsigned char* Text; /* Text segment data (unrelocated) */ @@ -114,7 +120,7 @@ typedef struct { Collection DataReloc; /* Relocation entries for the data segment */ Collection Imports; /* Imported symbols */ Collection Exports; /* Exported symbols */ -} O65Data; +}; -- 2.39.5