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:
parent
417ef278a3
commit
b03ae76b54
@ -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 {
|
||||
|
@ -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");
|
||||
|
||||
|
@ -94,6 +94,7 @@ typedef enum {
|
||||
CFGTOK_VERSION,
|
||||
CFGTOK_FORMAT,
|
||||
CFGTOK_RUNAD,
|
||||
CFGTOK_INITAD,
|
||||
|
||||
CFGTOK_LOAD,
|
||||
CFGTOK_RUN,
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
BIN
testcode/lib/atari/multi.xex
Normal file
BIN
testcode/lib/atari/multi.xex
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user