]> git.sur5r.net Git - cc65/commitdiff
Add support for INITAD to the Atari binary format.
authorDaniel Serpell <daniel.serpell@gmail.com>
Mon, 18 Feb 2019 03:24:52 +0000 (00:24 -0300)
committerDaniel Serpell <daniel.serpell@gmail.com>
Thu, 21 Feb 2019 22:00:03 +0000 (19:00 -0300)
doc/ld65.sgml
src/ld65/config.c
src/ld65/scanner.h
src/ld65/xex.c
src/ld65/xex.h
testcode/lib/atari/multi-xex.cfg
testcode/lib/atari/multi-xex.s
testcode/lib/atari/multi.xex [new file with mode: 0644]

index 9116eb4420f342afab8b47065ee447cfd1872c8c..3f159b39bc106941cd1536b6f93143d33c244678 100644 (file)
@@ -938,9 +938,24 @@ has several attributes that may be defined here.
     }
 </verb></tscreen>
 
-The Atari file format has only one attribute, <tt/RUNAD/ that allows to specify
-a symbol as the run address of the binary. If the attribute is omiteed, no run
-address is specified.
+The Atari file format has two attributes:
+
+<descrip>
+
+  <tag><tt>RUNAD = symbol</tt></tag>
+
+  Specify a symbol as the run address of the binary, the loader will call this
+  address after all the file is loaded in memory. If the attribute is omitted,
+  no run address is included in the file.
+
+  <tag><tt>INITAD = memory_area : symbol</tt></tag>
+
+  Specify a symbol as the initialization address for the given memory area.
+  The binary loader will call this address just after the memory area is loaded
+  into memory, before continuing loading the rest of the file.
+
+</descrip>
+
 
 <tscreen><verb>
     FORMATS {
index fafbed290bf06c18cb4d9a5b57ebc9c212d8ab1f..f8bff2ac050fa5b5008e9d5b8b4be4d359f2fd55 100644 (file)
@@ -1007,6 +1007,7 @@ static void ParseXex (void)
 {
     static const IdentTok Attributes [] = {
         {   "RUNAD",    CFGTOK_RUNAD            },
+        {   "INITAD",   CFGTOK_INITAD           },
     };
 
     /* Remember the attributes read */
@@ -1017,6 +1018,8 @@ static void ParseXex (void)
     };
     unsigned AttrFlags = atNone;
     Import *RunAd = 0;
+    Import *InitAd;
+    MemoryArea *InitMem;
 
     /* Read the attributes */
     while (CfgTok == CFGTOK_IDENT) {
@@ -1046,6 +1049,24 @@ static void ParseXex (void)
                 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");
 
index 77fa91da81a3031a2b54f61d04d6dd3e2d070f57..aeabbdca81e597e480424f36b689fb01c6850d03 100644 (file)
@@ -94,6 +94,7 @@ typedef enum {
     CFGTOK_VERSION,
     CFGTOK_FORMAT,
     CFGTOK_RUNAD,
+    CFGTOK_INITAD,
 
     CFGTOK_LOAD,
     CFGTOK_RUN,
index 18190c063641e4f1c036afa69b8d942b69a625d8..e7674949a01910786f8424c959bff199b7ab50a0 100644 (file)
 /*                                   Data                                    */
 /*****************************************************************************/
 
+/* Linked list of memory area initialization addresses */
+typedef struct XexInitAd {
+    MemoryArea *InitMem;
+    Import *InitAd;
+    struct XexInitAd *next;
+} XexInitAd;
 
 
 struct XexDesc {
@@ -65,13 +71,13 @@ struct XexDesc {
     FILE*       F;              /* Output file */
     const char* Filename;       /* Name of output file */
     Import*     RunAd;          /* Run Address */
+    XexInitAd*  InitAds;        /* List of Init Addresses */
     unsigned long HeadPos;      /* Position in the file of current header */
     unsigned long HeadEnd;      /* End address of current header */
     unsigned long HeadSize;     /* Last header size, can be removed if zero */
 };
 
 
-
 /*****************************************************************************/
 /*                                   Code                                    */
 /*****************************************************************************/
@@ -89,6 +95,7 @@ XexDesc* NewXexDesc (void)
     D->F        = 0;
     D->Filename = 0;
     D->RunAd    = 0;
+    D->InitAds  = 0;
     D->HeadPos  = 0;
     D->HeadEnd  = 0;
     D->HeadSize = 0;
@@ -113,7 +120,34 @@ void XexSetRunAd (XexDesc* D, Import *RunAd)
     D->RunAd = RunAd;
 }
 
+XexInitAd* XexSearchInitMem(XexDesc* D, MemoryArea *InitMem)
+{
+    XexInitAd* I;
+    for (I=D->InitAds; I != 0; I=I->next)
+    {
+        if (I->InitMem == InitMem)
+            return I;
+    }
+    return NULL;
+}
+
 
+int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd)
+/* Sets and INITAD for the given memory area */
+{
+    XexInitAd* I;
+
+    /* Search for repeated entry */
+    if (XexSearchInitMem (D, InitMem))
+        return 1;
+
+    I = xmalloc (sizeof (XexInitAd));
+    I->InitAd  = InitAd;
+    I->InitMem = InitMem;
+    I->next    = D->InitAds;
+    D->InitAds = I;
+    return 0;
+}
 
 static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
                               unsigned long Offs attribute ((unused)),
@@ -369,8 +403,15 @@ void XexWriteTarget (XexDesc* D, struct File* F)
     for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
         /* Get this entry */
         MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
+        /* See if we have an init address for this area */
+        XexInitAd* I = XexSearchInitMem (D, M);
         Print (stdout, 1, "  ATARI EXE Dumping `%s'\n", GetString (M->Name));
         XexWriteMem (D, M);
+        if (I) {
+            Write16 (D->F, 0x2E2);
+            Write16 (D->F, 0x2E3);
+            Write16 (D->F, GetExportVal (I->InitAd->Exp));
+        }
     }
 
     /* Write RUNAD at file end */
index c74f78eca3bf768019a0573c5e9277c98a425646..2eb80de8682e5132fbc668c3b0810d0d1253a335 100644 (file)
@@ -69,6 +69,8 @@ void XexWriteTarget (XexDesc* D, File* F);
 void XexSetRunAd (XexDesc* D, Import *RunAd);
 /* Set the RUNAD export */
 
+int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd);
+/* Sets and INITAD for the given memory area */
 
 /* End of xex.h */
 
index 18dfff82046223ec3caaa4e0d0e088d4c7225d35..7558aa8950044e16383051db0a213d8172490b12 100644 (file)
@@ -3,10 +3,12 @@ FEATURES {
 }
 MEMORY {
     ZP:      file = "", define = yes, start = $0082, size = $007E;
+    # First memory segment in file, show message
+    LOADER:  file = %O, start = $680, size = 128;
     # First memory segment in file, load over COLOR registers:
     COLOR:   file = %O, start = $2C4, size = 5;
     # Second memory segment, load at page 6:
-    PAGE6:   file = %O, start = $600, size = 256;
+    PAGE6:   file = %O, start = $600, size = 128;
     # Third memory segment in file, load over SDLST register:
     SDLST:   file = %O, start = $230, size = 2;
     # Main segment, load at "STARTADDRESS"
@@ -16,11 +18,13 @@ FILES {
     %O: format = atari;
 }
 FORMATS {
-    atari: runad = start;
+    atari: runad = start,
+           initad = LOADER: show_load;
 }
 SEGMENTS {
     ZEROPAGE: load = ZP,      type = zp,  optional = yes;
     # Place segments in memory areas:
+    LOADER:   load = LOADER,  type = rw;
     COLOR:    load = COLOR,   type = rw;
     PAGE6:    load = PAGE6,   type = rw;
     SDLST:    load = SDLST,   type = rw;
index 7957ddf64109c94f76d3803c3028e167a0347b7e..cdf43469d544d0d4370897def1b5f9f384521c02 100644 (file)
         .macpack        atari
 
 ; Default RUNAD is "start", export that:
-        .export         start
+        .export         start, show_load
 
+; Loader
+        .segment        "LOADER"
+show_load:
+        ldx     #0              ; channel 0
+        lda     #<msg_load
+        sta     ICBAL,x         ; address
+        lda     #>msg_load
+        sta     ICBAH,x
+        lda     #$FF
+        sta     ICBLL,x         ; length
+        sta     ICBLH,x
+        lda     #PUTREC
+        sta     ICCOM,x
+        jmp     CIOV
+
+msg_load:
+        .byte   "Loading....", ATEOL
 
 ; We load color values directly into registers
         .segment        "COLOR"
diff --git a/testcode/lib/atari/multi.xex b/testcode/lib/atari/multi.xex
new file mode 100644 (file)
index 0000000..7da39ad
Binary files /dev/null and b/testcode/lib/atari/multi.xex differ