}
</verb></tscreen>
-This will define three external symbols that may be used in your code:
+This will define some external symbols that may be used in your code:
<tscreen><verb>
__STACK_START__ This is set to the start of the memory
- area, $C000 in this example.
+ area, $C000 in this example.
__STACK_SIZE__ The size of the area, here $1000.
__STACK_LAST__ This is NOT the same as START+SIZE.
- Instead, it it defined as the first
- address that is not used by data. If we
- don't define any segments for this area,
- the value will be the same as START.
-</verb></tscreen>
+ Instead, it it defined as the first
+ address that is not used by data. If we
+ don't define any segments for this area,
+ the value will be the same as START.
+ __STACK_FILEOFFS__ The binary offset in the output file. This
+ is not defined for relocatable output file
+ formats (o65).
+</verb></tscreen>
A memory section may also have a type. Valid types are
static void BinWriteMem (BinDesc* D, MemoryArea* M)
/* Write the segments of one memory area to a file */
{
+ unsigned I;
+
/* Get the start address of this memory area */
unsigned long Addr = M->Start;
+ /* Debugging: Check that the file offset is correct */
+ if (ftell (D->F) != (long)M->FileOffs) {
+ Internal ("Invalid file offset for memory area %s: %ld/%lu",
+ GetString (M->Name), ftell (D->F), M->FileOffs);
+ }
+
/* Walk over all segments in this memory area */
- unsigned I;
for (I = 0; I < CollCount (&M->SegList); ++I) {
int DoWrite;
*/
Warning ("Segment `%s' is not aligned properly. Resulting "
"executable may not be functional.",
- GetString (S->Name));
+ GetString (S->Name));
}
/* If this is the run memory area, we must apply run alignment. If
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
+/* With contributions from: */
+/* */
+/* - "David M. Lloyd" <david.lloyd@redhat.com> */
+/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
F->Name = Name;
F->Flags = 0;
F->Format = BINFMT_DEFAULT;
+ F->Size = 0;
InitCollection (&F->MemoryAreas);
/* Insert the struct into the list */
/* Get the next memory area */
MemoryArea* M = CollAtUnchecked (&MemoryAreas, I);
+ /* Remember the offset in the output file */
+ M->FileOffs = M->F->Size;
+
/* Remember if this is a relocatable memory area */
M->Relocatable = RelocatableBinFmt (M->F->Format);
}
- /* If requested, define symbols for start and size 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;
SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
CollAppend (&E->DefLines, M->LI);
+
+ /* Define the file offset of the memory area. This isn't of much
+ * use for relocatable output files.
+ */
+ if (!M->Relocatable) {
+ SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name));
+ E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs);
+ CollAppend (&E->DefLines, M->LI);
+ }
+ /* Throw away the string buffer */
SB_Done (&Buf);
}
+ /* Grow the file by the size of the memory area */
+ if (M->Flags & MF_FILL) {
+ M->F->Size += M->Size;
+ } else {
+ M->F->Size += M->FillLevel;
+ }
}
/* Return the number of memory area overflows */
unsigned Name; /* Name index of the file */
unsigned Flags;
unsigned Format; /* Output format */
+ unsigned long Size; /* Size of the generated file */
Collection MemoryAreas; /* List of memory areas in this file */
};
M->Name = Name;
M->Attr = 0;
M->Flags = 0;
+ M->FileOffs = ~0UL;
M->StartExpr = 0;
M->Start = 0;
M->SizeExpr = 0;
unsigned Name; /* Name index of the memory area */
unsigned Attr; /* Which values are valid? */
unsigned Flags; /* Set of bitmapped flags */
+ unsigned long FileOffs; /* Offset in output file */
struct ExprNode* StartExpr; /* Expression for start address */
unsigned long Start; /* Start address */
struct ExprNode* SizeExpr; /* Expression for size */