]> git.sur5r.net Git - cc65/commitdiff
Add segment type "overlay". 739/head
authorLaubzega <mileksmyk@gmail.com>
Sat, 25 Aug 2018 17:18:23 +0000 (10:18 -0700)
committerLaubzega <mileksmyk@gmail.com>
Sat, 25 Aug 2018 17:18:23 +0000 (10:18 -0700)
src/ld65/bin.c
src/ld65/config.c
src/ld65/config.h
src/ld65/scanner.h

index c3efd9cd1654db24f51e4e46c3cdfb77aa868337..927719016a549d676b555c0d410a7f547bf5354e 100644 (file)
@@ -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;
             }
index 5959067b221d570d7bea928c2e76993ae1759174..f6603d6285ca962f03596c023a60b9ea841151de 100644 (file)
@@ -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;
+                        }
                     }
                 }
 
index 6a36af6cc2c1e21b77d2669c5f9da5644a065a61..a60580da30c16978027127ad88e7a356ef458ea8 100644 (file)
@@ -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 */
 
 
 
index 006ccfceb1014337c280b5eb869d8efaf07d9c7c..e994c05477104f569f9961351c3271f302d6a8d4 100644 (file)
@@ -105,6 +105,7 @@ typedef enum {
     CFGTOK_RW,
     CFGTOK_BSS,
     CFGTOK_ZP,
+    CFGTOK_OVERLAY,
 
     CFGTOK_O65,
     CFGTOK_BIN,