1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-28 06:30:16 +00:00

Add support for INITAD to the Atari binary format.

This commit is contained in:
Daniel Serpell 2019-02-18 00:24:52 -03:00
parent 417ef278a3
commit b03ae76b54
8 changed files with 108 additions and 7 deletions

View 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 {

View 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");

View File

@ -94,6 +94,7 @@ typedef enum {
CFGTOK_VERSION,
CFGTOK_FORMAT,
CFGTOK_RUNAD,
CFGTOK_INITAD,
CFGTOK_LOAD,
CFGTOK_RUN,

View File

@ -58,6 +58,12 @@
/* 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,8 +120,35 @@ 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)),
void* Data)
@ -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 */

View 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 */

View 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;

View File

@ -14,8 +14,25 @@
.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"

Binary file not shown.