]> git.sur5r.net Git - cc65/commitdiff
Working
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 11 Feb 2003 22:33:12 +0000 (22:33 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 11 Feb 2003 22:33:12 +0000 (22:33 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1971 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/co65/convert.c [new file with mode: 0644]
src/co65/convert.h [new file with mode: 0644]
src/co65/main.c
src/co65/make/gcc.mak
src/co65/make/watcom.mak
src/co65/model.c [new file with mode: 0644]
src/co65/model.h [new file with mode: 0644]
src/co65/o65.h

diff --git a/src/co65/convert.c b/src/co65/convert.c
new file mode 100644 (file)
index 0000000..ed9ff15
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* 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 (file)
index 0000000..5773fd4
--- /dev/null
@@ -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
+
+
+
index 4da4a8433fc6473fcdd520c9f53adc394d83bb85..db07b6a0856256ebcbe0bd2683598d25d15db7b1 100644 (file)
@@ -42,6 +42,7 @@
 /* common */
 #include "chartype.h"
 #include "cmdline.h"
+#include "debugflag.h"
 #include "fname.h"
 #include "print.h"
 #include "segnames.h"
 #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;
index 7b0cb39300144516fbec391257b0459e6ae2f6f0..58f2dd40d397753e8d0e2045cf263511fc79a2e4 100644 (file)
@@ -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
index 42f99183aec660434976e4d1f1ce8e490d948a2d..4adac350b626a98e15d65d405a519d19f606f89f 100644 (file)
@@ -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 (file)
index 0000000..db0232f
--- /dev/null
@@ -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 (file)
index 0000000..aa35a8f
--- /dev/null
@@ -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
+
+
+
index e2ee4fa4aff6ebc030d5fcbd8798ddc675c0a21c..9c88c2ffc461c1c7358404fa4ca1791f730a1b09 100644 (file)
@@ -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;
+};