/* */
/* */
/* */
-/* (C) 1998-2012, Ullrich von Bassewitz */
+/* (c) 1998-2013, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#include "objdata.h"
#include "scanner.h"
#include "spool.h"
+#include "xex.h"
} CfgSymType;
/* Symbol structure. It is used for o65 imports and exports, but also for
- * symbols from the SYMBOLS sections (symbols defined in the config file or
- * forced imports).
- */
+** symbols from the SYMBOLS sections (symbols defined in the config file or
+** forced imports).
+*/
typedef struct CfgSymbol CfgSymbol;
struct CfgSymbol {
CfgSymType Type; /* Type of symbol */
/* Descriptor holding information about the binary formats */
static BinDesc* BinFmtDesc = 0;
static O65Desc* O65FmtDesc = 0;
+static XexDesc* XexFmtDesc = 0;
{
MemoryArea* M = CfgFindMemory (Name);
if (M == 0) {
- CfgError (&CfgErrorPos, "Invalid memory area `%s'", GetString (Name));
+ CfgError (&CfgErrorPos, "Invalid memory area '%s'", GetString (Name));
}
return M;
}
static CfgSymbol* NewCfgSymbol (CfgSymType Type, unsigned Name)
/* Create a new CfgSymbol structure with the given type and name. The
- * current config file position is recorded in the returned struct. The
- * created struct is inserted into the CfgSymbols collection and returned.
- */
+** current config file position is recorded in the returned struct. The
+** created struct is inserted into the CfgSymbols collection and returned.
+*/
{
/* Allocate memory */
CfgSymbol* Sym = xmalloc (sizeof (CfgSymbol));
MemoryArea* M = CfgFindMemory (Name);
if (M) {
CfgError (&CfgErrorPos,
- "Memory area `%s' defined twice",
+ "Memory area '%s' defined twice",
GetString (Name));
}
/* Check for duplicate names */
SegDesc* S = CfgFindSegDesc (Name);
if (S) {
- CfgError (&CfgErrorPos, "Segment `%s' defined twice", GetString (Name));
+ CfgError (&CfgErrorPos, "Segment '%s' defined twice", GetString (Name));
}
/* Allocate memory */
static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name)
/* Check if the item is already defined. Print an error if so. If not, set
- * the marker that we have a definition now.
- */
+** the marker that we have a definition now.
+*/
{
if (*Flags & Mask) {
CfgError (&CfgErrorPos, "%s is already defined", Name);
AttrCheck (M->Attr, MA_SIZE, "SIZE");
/* If we don't have a file name for output given, use the default
- * file name.
- */
+ ** file name.
+ */
if ((M->Attr & MA_FILE) == 0) {
FileInsert (GetFile (GetStringId (OutputName)), M);
OutputNameUsed = 1;
{ "FORMAT", CFGTOK_FORMAT },
};
static const IdentTok Formats [] = {
+ { "ATARI", CFGTOK_ATARIEXE },
{ "O65", CFGTOK_O65 },
{ "BIN", CFGTOK_BIN },
{ "BINARY", CFGTOK_BIN },
F = FindFile (GetStrBufId (&CfgSVal));
if (F == 0) {
CfgError (&CfgErrorPos,
- "File `%s' not found in MEMORY section",
+ "File '%s' not found in MEMORY section",
SB_GetConstBuf (&CfgSVal));
}
F->Format = BINFMT_O65;
break;
+ case CFGTOK_ATARIEXE:
+ F->Format = BINFMT_ATARIEXE;
+ break;
+
default:
Error ("Unexpected format token");
}
{ "RW", CFGTOK_RW },
{ "BSS", CFGTOK_BSS },
{ "ZP", CFGTOK_ZP },
+ { "OVERWRITE", CFGTOK_OVERWRITE },
};
unsigned Count;
FlagAttr (&S->Attr, SA_TYPE, "TYPE");
CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type");
switch (CfgTok) {
- case CFGTOK_RO: S->Flags |= SF_RO; break;
- case CFGTOK_RW: /* Default */ break;
- case CFGTOK_BSS: S->Flags |= SF_BSS; break;
- case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break;
- default: Internal ("Unexpected token: %d", CfgTok);
+ case CFGTOK_RO: S->Flags |= SF_RO; break;
+ case CFGTOK_RW: /* Default */ break;
+ case CFGTOK_BSS: S->Flags |= SF_BSS; break;
+ case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break;
+ case CFGTOK_OVERWRITE: S->Flags |= (SF_OVERWRITE | SF_RO); break;
+ default: Internal ("Unexpected token: %d", CfgTok);
}
CfgNextTok ();
break;
}
/* An attribute of ALIGN_LOAD doesn't make sense if there are no
- * separate run and load memory areas.
- */
+ ** separate run and load memory areas.
+ */
if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) {
CfgWarning (&CfgErrorPos,
"ALIGN_LOAD attribute specified, but no separate "
}
/* If the segment is marked as BSS style, it may not have separate
- * load and run memory areas, because it's is never written to disk.
- */
+ ** load and run memory areas, because it's is never written to disk.
+ */
if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) {
CfgWarning (&CfgErrorPos,
- "Segment with type `bss' has both LOAD and RUN "
+ "Segment with type 'bss' has both LOAD and RUN "
"memory areas assigned");
}
if ((S->Flags & SF_RO) == 0) {
if (S->Run->Flags & MF_RO) {
CfgError (&CfgErrorPos,
- "Cannot put r/w segment `%s' in r/o memory area `%s'",
+ "Cannot put r/w segment '%s' in r/o memory area '%s'",
GetString (S->Name), GetString (S->Run->Name));
}
}
/* Cannot use this attribute twice */
FlagAttr (&AttrFlags, atOS, "OS");
/* Get the operating system. It may be specified as name or
- * as a number in the range 1..255.
- */
+ ** as a number in the range 1..255.
+ */
if (CfgTok == CFGTOK_INTCON) {
CfgRangeCheck (O65OS_MIN, O65OS_MAX);
OS = (unsigned) CfgIVal;
+static void ParseXex (void)
+/* Parse the o65 format section */
+{
+ static const IdentTok Attributes [] = {
+ { "RUNAD", CFGTOK_RUNAD },
+ { "INITAD", CFGTOK_INITAD },
+ };
+
+ /* Remember the attributes read */
+ /* Bitmask to remember the attributes we got already */
+ enum {
+ atNone = 0x0000,
+ atRunAd = 0x0001,
+ };
+ unsigned AttrFlags = atNone;
+ Import *RunAd = 0;
+ Import *InitAd;
+ MemoryArea *InitMem;
+
+ /* Read the attributes */
+ while (CfgTok == CFGTOK_IDENT) {
+
+ /* Map the identifier to a token */
+ cfgtok_t AttrTok;
+ CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute");
+ AttrTok = CfgTok;
+
+ /* An optional assignment follows */
+ CfgNextTok ();
+ CfgOptionalAssign ();
+
+ /* Check which attribute was given */
+ switch (AttrTok) {
+
+ case CFGTOK_RUNAD:
+ /* Cannot have this attribute twice */
+ FlagAttr (&AttrFlags, atRunAd, "RUNAD");
+ /* We expect an identifier */
+ CfgAssureIdent ();
+ /* Generate an import for the symbol */
+ RunAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS));
+ /* Remember the file position */
+ CollAppend (&RunAd->RefLines, GenLineInfo (&CfgErrorPos));
+ /* Eat the identifier token */
+ CfgNextTok ();
+ break;
+
+ case CFGTOK_INITAD:
+ /* We expect a memory area followed by a colon and an identifier */
+ CfgAssureIdent ();
+ InitMem = CfgGetMemory (GetStrBufId (&CfgSVal));
+ CfgNextTok ();
+ CfgConsumeColon ();
+ CfgAssureIdent ();
+ /* Generate an import for the symbol */
+ InitAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS));
+ /* Remember the file position */
+ CollAppend (&InitAd->RefLines, GenLineInfo (&CfgErrorPos));
+ /* Eat the identifier token */
+ CfgNextTok ();
+ /* Add to XEX */
+ if (XexAddInitAd (XexFmtDesc, InitMem, InitAd))
+ CfgError (&CfgErrorPos, "INITAD already given for memory area");
+ break;
+
+ default:
+ FAIL ("Unexpected attribute token");
+
+ }
+
+ /* Skip an optional comma */
+ CfgOptionalComma ();
+ }
+
+ /* Set the RUNAD import if we have one */
+ if ( RunAd )
+ XexSetRunAd (XexFmtDesc, RunAd);
+}
+
+
+
static void ParseFormats (void)
/* Parse a target format section */
{
{ "O65", CFGTOK_O65 },
{ "BIN", CFGTOK_BIN },
{ "BINARY", CFGTOK_BIN },
+ { "ATARI", CFGTOK_ATARIEXE },
};
while (CfgTok == CFGTOK_IDENT) {
ParseO65 ();
break;
+ case CFGTOK_ATARIEXE:
+ ParseXex ();
+ break;
+
case CFGTOK_BIN:
/* No attribibutes available */
break;
AttrCheck (AttrFlags, atDefault, "DEFAULT");
/* If no start address was given on the command line, use the one given
- * here
- */
+ ** here
+ */
if (!HaveStartAddr) {
StartAddr = DefStartAddr;
}
CfgNextTok ();
/* Expected a curly brace */
- CfgConsume (CFGTOK_LCURLY, "`{' expected");
+ CfgConsume (CFGTOK_LCURLY, "'{' expected");
/* Read the block */
switch (BlockTok) {
}
/* Skip closing brace */
- CfgConsume (CFGTOK_RCURLY, "`}' expected");
+ CfgConsume (CFGTOK_RCURLY, "'}' expected");
} while (CfgTok != CFGTOK_EOF);
}
/* Create the descriptors for the binary formats */
BinFmtDesc = NewBinDesc ();
O65FmtDesc = NewO65Desc ();
+ XexFmtDesc = NewXexDesc ();
/* If we have a config name given, open the file, otherwise we will read
- * from a buffer.
- */
+ ** from a buffer.
+ */
CfgOpenInput ();
/* Parse the file */
SegDesc* S = CollAtUnchecked (&SegDescList, I);
/* Search for the actual segment in the input files. The function may
- * return NULL (no such segment), this is checked later.
- */
+ ** return NULL (no such segment), this is checked later.
+ */
S->Seg = SegFind (S->Name);
/* If the segment is marked as BSS style, and if the segment exists
- * in any of the object file, check that there's no initialized data
- * in the segment.
- */
+ ** in any of the object file, check that there's no initialized data
+ ** in the segment.
+ */
if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) {
CfgWarning (GetSourcePos (S->LI),
- "Segment `%s' with type `bss' contains initialized data",
+ "Segment '%s' with type 'bss' contains initialized data",
GetString (S->Name));
}
/* If this segment does exist in any of the object files, insert the
- * segment into the load/run memory areas. Otherwise print a warning
- * and discard it, because the segment pointer in the descriptor is
- * invalid.
- */
+ ** segment into the load/run memory areas. Otherwise print a warning
+ ** and discard it, because the segment pointer in the descriptor is
+ ** invalid.
+ */
if (S->Seg != 0) {
/* Insert the segment into the memory area list */
/* Print a warning if the segment is not optional */
if ((S->Flags & SF_OPTIONAL) == 0) {
CfgWarning (&CfgErrorPos,
- "Segment `%s' does not exist",
+ "Segment '%s' does not exist",
GetString (S->Name));
}
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
- "Exported o65 symbol `%s' cannot also be an o65 import",
+ "Exported o65 symbol '%s' cannot also be an o65 import",
GetString (Sym->Name)
);
}
/* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
+ ** routine will check this also, but we get a more verbose
+ ** error message when checking it here.
+ */
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
- "Duplicate exported o65 symbol: `%s'",
+ "Duplicate exported o65 symbol: '%s'",
GetString (Sym->Name)
);
}
if (O65GetExport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
- "Imported o65 symbol `%s' cannot also be an o65 export",
+ "Imported o65 symbol '%s' cannot also be an o65 export",
GetString (Sym->Name)
);
}
/* Check if we have this symbol defined already. The entry
- * routine will check this also, but we get a more verbose
- * error message when checking it here.
- */
+ ** routine will check this also, but we get a more verbose
+ ** error message when checking it here.
+ */
if (O65GetImport (O65FmtDesc, Sym->Name) != 0) {
CfgError (
GetSourcePos (Sym->LI),
- "Duplicate imported o65 symbol: `%s'",
+ "Duplicate imported o65 symbol: '%s'",
GetString (Sym->Name)
);
}
unsigned CfgProcess (void)
-/* Process the config file after reading in object files and libraries. This
- * includes postprocessing of the config file data but also assigning segments
- * and defining segment/memory area related symbols. The function will return
- * the number of memory area overflows (so zero means anything went ok).
- * In case of overflows, a short mapfile can be generated later, to ease the
- * task of rearranging segments for the user.
- */
+/* Process the config file, after reading in object files and libraries. This
+** includes postprocessing of the config file data; but also assigning segments,
+** and defining segment/memory-area related symbols. The function will return
+** the number of memory area overflows (so, zero means everything went OK).
+** In case of overflows, a short mapfile can be generated later, to ease the
+** user's task of re-arranging segments.
+*/
{
unsigned Overflows = 0;
unsigned I;
/* Postprocess symbols. We must do that first, since weak symbols are
- * defined here, which may be needed later.
- */
+ ** defined here, which may be needed later.
+ */
ProcessSymbols ();
/* Postprocess segments */
ProcessSegments ();
- /* Walk through each of the memory sections. Add up the sizes and check
- * for an overflow of the section. Assign the start addresses of the
- * segments while doing this.
- */
+ /* Walk through each of the memory sections. Add up the sizes; and, check
+ ** for an overflow of the section. Assign the start addresses of the
+ ** segments while doing that.
+ */
for (I = 0; I < CollCount (&MemoryAreas); ++I) {
-
unsigned J;
unsigned long Addr;
+ unsigned Overwrites = 0;
/* Get the next memory area */
MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
/* Remember if this is a relocatable memory area */
M->Relocatable = RelocatableBinFmt (M->F->Format);
- /* Resolve the start address expression, remember the start address
- * and mark the memory area as placed.
- */
+ /* Resolve the start address expression, remember the start address,
+ ** and mark the memory area as placed.
+ */
if (!IsConstExpr (M->StartExpr)) {
CfgError (GetSourcePos (M->LI),
- "Start address of memory area `%s' is not constant",
+ "Start address of memory area '%s' is not constant",
GetString (M->Name));
}
Addr = M->Start = GetExprVal (M->StartExpr);
M->Flags |= MF_PLACED;
/* If requested, define the symbol for the start of the memory area.
- * Doing it here means that the expression for the size of the area
- * may reference this symbol.
- */
+ ** Doing it here means that the expression for the size of the area
+ ** may reference this symbol.
+ */
if (M->Flags & MF_DEFINE) {
Export* E;
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
/* Resolve the size expression */
if (!IsConstExpr (M->SizeExpr)) {
CfgError (GetSourcePos (M->LI),
- "Size of memory area `%s' is not constant",
+ "Size of memory area '%s' is not constant",
GetString (M->Name));
}
M->Size = GetExprVal (M->SizeExpr);
/* Walk through the segments in this memory area */
for (J = 0; J < CollCount (&M->SegList); ++J) {
-
/* Get the segment */
SegDesc* S = CollAtUnchecked (&M->SegList, J);
/* Remember the start address before handling this segment */
unsigned long StartAddr = Addr;
- /* Some actions depend on wether this is the load or run memory
- * area.
- */
- if (S->Run == M) {
+ /* Take note of "overwrite" segments and make sure there are no
+ ** other segment types following them in current memory region.
+ */
+ if (S->Flags & SF_OVERWRITE) {
+ if (S->Flags & (SF_OFFSET | SF_START)) {
+ ++Overwrites;
+ } else {
+ CfgError (GetSourcePos (M->LI),
+ "Segment '%s' of type 'overwrite' requires either"
+ " 'Start' or 'Offset' attribute to be specified",
+ GetString (S->Name));
+ }
+ } else {
+ if (Overwrites > 0) {
+ CfgError (GetSourcePos (M->LI),
+ "Segment '%s' is preceded by at least one segment"
+ " of type 'overwrite'",
+ GetString (S->Name));
+ }
+ }
+ /* Some actions depend on whether this is the load or run memory
+ ** area.
+ */
+ if (S->Run == M) {
/* This is the run (and maybe load) memory area. Handle
- * alignment and explict start address and offset.
- */
+ ** alignment and explict start address and offset.
+ */
+
+ /* Check if the alignment for the segment from the linker
+ ** config is a multiple for that of the segment.
+ ** If START or OFFSET is provided instead of ALIGN, check
+ ** if its address fits alignment requirements.
+ */
+ unsigned long AlignedBy = (S->Flags & SF_START) ? S->Addr
+ : (S->Flags & SF_OFFSET) ? (S->Addr + M->Start)
+ : S->RunAlignment;
+ if ((AlignedBy % S->Seg->Alignment) != 0) {
+ /* Segment requires another alignment than configured
+ ** in the linker.
+ */
+ CfgWarning (GetSourcePos (S->LI),
+ "Segment '%s' isn't aligned properly; the"
+ " resulting executable might not be functional.",
+ GetString (S->Name));
+ }
+
if (S->Flags & SF_ALIGN) {
/* Align the address */
unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
/* If the first segment placed in the memory area needs
- * fill bytes for the alignment, emit a warning, since
- * this is somewhat suspicious.
- */
+ ** fill bytes for the alignment, emit a warning, since
+ ** that is somewhat suspicious.
+ */
if (M->FillLevel == 0 && NewAddr > Addr) {
CfgWarning (GetSourcePos (S->LI),
- "First segment in memory area `%s' does "
- "already need fill bytes for alignment",
+ "The first segment in memory area '%s' "
+ "needs fill bytes for alignment.",
GetString (M->Name));
}
/* Use the aligned address */
Addr = NewAddr;
- } else if (S->Flags & (SF_OFFSET | SF_START)) {
+ } else if ((S->Flags & (SF_OFFSET | SF_START)) != 0 &&
+ (M->Flags & MF_OVERFLOW) == 0) {
/* Give the segment a fixed starting address */
unsigned long NewAddr = S->Addr;
+
if (S->Flags & SF_OFFSET) {
/* An offset was given, no address, make an address */
NewAddr += M->Start;
}
- if (Addr > NewAddr) {
- /* Offset already too large */
- if (S->Flags & SF_OFFSET) {
- CfgError (GetSourcePos (M->LI),
- "Offset too small in `%s', segment `%s'",
- GetString (M->Name),
- GetString (S->Name));
+
+ if (S->Flags & SF_OVERWRITE) {
+ if (NewAddr < M->Start) {
+ CfgError (GetSourcePos (S->LI),
+ "Segment '%s' begins before memory area '%s'",
+ GetString (S->Name), GetString (M->Name));
} else {
- CfgError (GetSourcePos (M->LI),
- "Start address too low in `%s', segment `%s'",
- GetString (M->Name),
- GetString (S->Name));
+ Addr = NewAddr;
+ }
+ } else {
+ if (NewAddr < Addr) {
+ /* Offset already too large */
+ ++Overflows;
+ if (S->Flags & SF_OFFSET) {
+ CfgWarning (GetSourcePos (S->LI),
+ "Segment '%s' offset is too small in '%s' by %lu byte%c",
+ GetString (S->Name), GetString (M->Name),
+ Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+ } else {
+ CfgWarning (GetSourcePos (S->LI),
+ "Segment '%s' start address is too low in '%s' by %lu byte%c",
+ GetString (S->Name), GetString (M->Name),
+ Addr - NewAddr, (Addr - NewAddr == 1) ? ' ' : 's');
+ }
+ } else {
+ Addr = NewAddr;
}
}
- Addr = NewAddr;
}
/* Set the start address of this segment, set the readonly flag
- * in the segment and and remember if the segment is in a
- * relocatable file or not.
- */
+ ** in the segment, and remember if the segment is in a
+ ** relocatable file or not.
+ */
S->Seg->PC = Addr;
S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
/* Remember the run memory for this segment, which is also a
- * flag that the segment has been placed.
- */
+ ** flag that the segment has been placed.
+ */
S->Seg->MemArea = M;
} else if (S->Load == M) {
-
- /* This is the load memory area, *and* run and load are
- * different (because of the "else" above). Handle alignment.
- */
+ /* This is the load memory area; *and*, run and load are
+ ** different (because of the "else" above). Handle alignment.
+ */
if (S->Flags & SF_ALIGN_LOAD) {
/* Align the address */
Addr = AlignAddr (Addr, S->LoadAlignment);
}
-
}
- /* If this is the load memory area and the segment doesn't have a
- * fill value defined, use the one from the memory area.
- */
+ /* If this is the load memory area, and the segment doesn't have a
+ ** fill value defined, use the one from the memory area.
+ */
if (S->Load == M && (S->Flags & SF_FILLVAL) == 0) {
S->Seg->FillVal = M->FillVal;
}
- /* Increment the fill level of the memory area and check for an
- * overflow.
- */
+ /* Increment the fill level of the memory area; and, check for an
+ ** overflow.
+ */
M->FillLevel = Addr + S->Seg->Size - M->Start;
if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
++Overflows;
M->Flags |= MF_OVERFLOW;
CfgWarning (GetSourcePos (M->LI),
- "Memory area overflow in `%s', segment `%s' (%lu bytes)",
- GetString (M->Name), GetString (S->Name),
- M->FillLevel - M->Size);
+ "Segment '%s' overflows memory area '%s' by %lu byte%c",
+ GetString (S->Name), GetString (M->Name),
+ M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's');
}
/* If requested, define symbols for the start and size of the
- * segment.
- */
+ ** segment.
+ */
if (S->Flags & SF_DEFINE) {
if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) {
CreateRunDefines (S, Addr);
/* Calculate the new address */
Addr += S->Seg->Size;
- /* If this segment goes out to the file, increase the file size */
- if ((S->Flags & SF_BSS) == 0 && S->Load == M) {
+ /* If this segment will go out to the file, or its place
+ ** in the file will be filled, then increase the file size.
+ */
+ if (S->Load == M &&
+ ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) {
M->F->Size += Addr - StartAddr;
}
-
}
- /* If requested, define symbols for start, size and offset of the
- * memory area
- */
+ /* If requested, define symbols for start, size, and offset of the
+ ** memory area
+ */
if (M->Flags & MF_DEFINE) {
Export* E;
StrBuf Buf = STATIC_STRBUF_INITIALIZER;
CollAppend (&E->DefLines, M->LI);
/* Define the file offset of the memory area. This isn't of much
- * use for relocatable output files.
- */
+ ** use for relocatable output files.
+ */
if (!M->Relocatable) {
SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name));
E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs);
SB_Done (&Buf);
}
- /* If we didn't have an overflow and are requested to fill the memory
- * area, acount for that in the file size.
- */
+ /* If we didn't have an overflow, and are requested to fill the memory
+ ** area, account for that in the file size.
+ */
if ((M->Flags & MF_OVERFLOW) == 0 && (M->Flags & MF_FILL) != 0) {
M->F->Size += (M->Size - M->FillLevel);
}
O65WriteTarget (O65FmtDesc, F);
break;
+ case BINFMT_ATARIEXE:
+ XexWriteTarget (XexFmtDesc, F);
+ break;
+
default:
Internal ("Invalid binary format: %u", F->Format);
} else {
/* No output file. Walk through the list and mark all segments
- * loading into these memory areas in this file as dumped.
- */
+ ** loading into these memory areas in this file as dumped.
+ */
unsigned J;
for (J = 0; J < CollCount (&F->MemoryAreas); ++J) {
MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J);
/* Debugging */
- Print (stdout, 2, "Skipping `%s'...\n", GetString (M->Name));
+ Print (stdout, 2, "Skipping '%s'...\n", GetString (M->Name));
/* Walk throught the segments */
for (K = 0; K < CollCount (&M->SegList); ++K) {
}
}
}
-
-
-