From 8b584cb89fe4fa598c3fb16fb7ee215dffa20dea Mon Sep 17 00:00:00 2001 From: Laubzega Date: Sat, 25 Aug 2018 10:18:23 -0700 Subject: [PATCH] Add segment type "overlay". --- src/ld65/bin.c | 9 +++++-- src/ld65/config.c | 63 ++++++++++++++++++++++++++++++++++++---------- src/ld65/config.h | 1 + src/ld65/scanner.h | 1 + 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/ld65/bin.c b/src/ld65/bin.c index c3efd9cd1..927719016 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -193,8 +193,13 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { - WriteMult (D->F, M->FillVal, NewAddr-Addr); - PrintNumVal ("SF_OFFSET", NewAddr - Addr); + /* Seek back for "overlay" segments */ + if (NewAddr < Addr) { + fseek(D->F, NewAddr - M->Start, SEEK_SET); + } else { + WriteMult (D->F, M->FillVal, NewAddr-Addr); + PrintNumVal ("SF_OFFSET", NewAddr - Addr); + } } Addr = NewAddr; } diff --git a/src/ld65/config.c b/src/ld65/config.c index 5959067b2..f6603d628 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -653,6 +653,7 @@ static void ParseSegments (void) { "RW", CFGTOK_RW }, { "BSS", CFGTOK_BSS }, { "ZP", CFGTOK_ZP }, + { "OVERLAY", CFGTOK_OVERLAY }, }; unsigned Count; @@ -757,6 +758,7 @@ static void ParseSegments (void) 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_OVERLAY: S->Flags |= SF_OVERLAY; break; default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); @@ -1795,6 +1797,7 @@ unsigned CfgProcess (void) for (I = 0; I < CollCount (&MemoryAreas); ++I) { unsigned J; unsigned long Addr; + unsigned Overlays = 0; /* Get the next memory area */ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); @@ -1848,6 +1851,29 @@ unsigned CfgProcess (void) /* Remember the start address before handling this segment */ unsigned long StartAddr = Addr; + /* Take note of overlayed segments and make sure there are no other + ** segment types following them in current memory region. + */ + if (S->Flags & SF_OVERLAY) { + { + if (S->Flags & (SF_OFFSET | SF_START)) { + ++Overlays; + } else { + CfgError (GetSourcePos (M->LI), + "Segment `%s' of type `overlay' requires either" + " `Start' or `Offset' argument to be specified.", + GetString (S->Name)); + } + } + } else { + if (Overlays > 0) { + CfgError (GetSourcePos (M->LI), + "Segment `%s' is preceded by at least one segment" + " of type `overlay'", + GetString (S->Name)); + } + } + /* Some actions depend on whether this is the load or run memory ** area. */ @@ -1896,22 +1922,33 @@ unsigned CfgProcess (void) /* An offset was given, no address, make an address */ NewAddr += M->Start; } - 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'); + + if (S->Flags & SF_OVERLAY) { + if (NewAddr < M->Start) { + CfgError (GetSourcePos (S->LI), + "Segment `%s' begins before memory area `%s'.", + GetString (S->Name), GetString (M->Name)); } 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'); + Addr = NewAddr; } } else { - Addr = NewAddr; + 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; + } } } diff --git a/src/ld65/config.h b/src/ld65/config.h index 6a36af6cc..a60580da3 100644 --- a/src/ld65/config.h +++ b/src/ld65/config.h @@ -96,6 +96,7 @@ struct SegDesc { #define SF_RUN_DEF 0x0200 /* RUN symbols already defined */ #define SF_LOAD_DEF 0x0400 /* LOAD symbols already defined */ #define SF_FILLVAL 0x0800 /* Segment has separate fill value */ +#define SF_OVERLAY 0x1000 /* Segment can be overlayed on another one */ diff --git a/src/ld65/scanner.h b/src/ld65/scanner.h index 006ccfceb..e994c0547 100644 --- a/src/ld65/scanner.h +++ b/src/ld65/scanner.h @@ -105,6 +105,7 @@ typedef enum { CFGTOK_RW, CFGTOK_BSS, CFGTOK_ZP, + CFGTOK_OVERLAY, CFGTOK_O65, CFGTOK_BIN, -- 2.39.5