Merge remote-tracking branch 'dmsc/xex-c' into upstream-master
This commit is contained in:
24
cfg/atari-asm-xex.cfg
Normal file
24
cfg/atari-asm-xex.cfg
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $2E00;
|
||||||
|
}
|
||||||
|
SYMBOLS {
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
}
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = "", define = yes, start = $0082, size = $007E;
|
||||||
|
MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S;
|
||||||
|
}
|
||||||
|
FILES {
|
||||||
|
%O: format = atari;
|
||||||
|
}
|
||||||
|
FORMATS {
|
||||||
|
atari: runad = start;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||||
|
EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs
|
||||||
|
CODE: load = MAIN, type = rw, define = yes;
|
||||||
|
RODATA: load = MAIN, type = ro optional = yes;
|
||||||
|
DATA: load = MAIN, type = rw optional = yes;
|
||||||
|
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
||||||
|
}
|
||||||
@@ -1,24 +1,56 @@
|
|||||||
|
# Sample linker configuration for C programs using the Atari binary file support.
|
||||||
|
# Use with: cl65 -tatari -Catari-c-xex.cfg prog.c -o prog.xex
|
||||||
FEATURES {
|
FEATURES {
|
||||||
STARTADDRESS: default = $2E00;
|
STARTADDRESS: default = $2000;
|
||||||
}
|
}
|
||||||
SYMBOLS {
|
SYMBOLS {
|
||||||
|
__SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
|
||||||
|
__STACKSIZE__: type = weak, value = $0800; # 2k stack
|
||||||
__STARTADDRESS__: type = export, value = %S;
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
__RESERVED_MEMORY__: type = weak, value = $0000;
|
||||||
|
__SYSCHKHDR__: type = export, value = 0; # Disable system check header
|
||||||
|
__SYSCHKTRL__: type = export, value = 0; # Disable system check trailer
|
||||||
}
|
}
|
||||||
MEMORY {
|
MEMORY {
|
||||||
ZP: file = "", define = yes, start = $0082, size = $007E;
|
ZP: file = "", define = yes, start = $0082, size = $007E;
|
||||||
MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S;
|
# "system check" load chunk
|
||||||
|
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
|
||||||
|
# "main program" load chunk
|
||||||
|
MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;
|
||||||
}
|
}
|
||||||
FILES {
|
FILES {
|
||||||
%O: format = atari;
|
%O: format = atari;
|
||||||
}
|
}
|
||||||
FORMATS {
|
FORMATS {
|
||||||
atari: runad = start;
|
atari: runad = start,
|
||||||
|
initad = SYSCHKCHNK: __SYSTEM_CHECK__;
|
||||||
}
|
}
|
||||||
SEGMENTS {
|
SEGMENTS {
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs
|
EXTZP: load = ZP, type = zp, optional = yes;
|
||||||
CODE: load = MAIN, type = rw, define = yes;
|
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
|
||||||
RODATA: load = MAIN, type = ro optional = yes;
|
STARTUP: load = MAIN, type = ro, define = yes;
|
||||||
DATA: load = MAIN, type = rw optional = yes;
|
LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized
|
||||||
BSS: load = MAIN, type = bss, optional = yes, define = yes;
|
LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
|
||||||
|
ONCE: load = MAIN, type = ro, optional = yes;
|
||||||
|
CODE: load = MAIN, type = ro, define = yes;
|
||||||
|
RODATA: load = MAIN, type = ro;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
INIT: load = MAIN, type = rw, optional = yes;
|
||||||
|
BSS: load = MAIN, type = bss, define = yes;
|
||||||
|
}
|
||||||
|
FEATURES {
|
||||||
|
CONDES: type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__,
|
||||||
|
segment = ONCE;
|
||||||
|
CONDES: type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__,
|
||||||
|
segment = RODATA;
|
||||||
|
CONDES: type = interruptor,
|
||||||
|
label = __INTERRUPTOR_TABLE__,
|
||||||
|
count = __INTERRUPTOR_COUNT__,
|
||||||
|
segment = RODATA,
|
||||||
|
import = __CALLIRQ__;
|
||||||
}
|
}
|
||||||
|
|||||||
79
cfg/atarixl-xex.cfg
Normal file
79
cfg/atarixl-xex.cfg
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Sample linker configuration for C programs using the Atari binary file support.
|
||||||
|
# Use with: cl65 -tatarixl -Catarixl-c-xex.cfg prog.c -o prog.xex
|
||||||
|
FEATURES {
|
||||||
|
STARTADDRESS: default = $2400;
|
||||||
|
}
|
||||||
|
SYMBOLS {
|
||||||
|
__SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk
|
||||||
|
__STACKSIZE__: type = weak, value = $0800; # 2k stack
|
||||||
|
__STARTADDRESS__: type = export, value = %S;
|
||||||
|
__SYSCHKHDR__: type = export, value = 0; # Disable system check header
|
||||||
|
__SYSCHKTRL__: type = export, value = 0; # Disable system check trailer
|
||||||
|
}
|
||||||
|
MEMORY {
|
||||||
|
ZP: file = "", define = yes, start = $0082, size = $007E;
|
||||||
|
|
||||||
|
# "system check" load chunk
|
||||||
|
SYSCHKCHNK: file = %O, start = $2E00, size = $0300;
|
||||||
|
|
||||||
|
# "shadow RAM preparation" load chunk
|
||||||
|
SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned
|
||||||
|
|
||||||
|
# "main program" load chunk
|
||||||
|
MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__;
|
||||||
|
|
||||||
|
# memory beneath the ROM preceeding the character generator
|
||||||
|
HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800;
|
||||||
|
|
||||||
|
# address of relocated character generator (same addess as ROM version)
|
||||||
|
CHARGEN: file = "", define = yes, start = $E000, size = $0400;
|
||||||
|
|
||||||
|
# memory beneath the ROM
|
||||||
|
HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400;
|
||||||
|
|
||||||
|
# UNUSED - hide
|
||||||
|
UNUSED: file = "", start = $0, size = $10;
|
||||||
|
}
|
||||||
|
FILES {
|
||||||
|
%O: format = atari;
|
||||||
|
}
|
||||||
|
FORMATS {
|
||||||
|
atari: runad = start,
|
||||||
|
initad = SYSCHKCHNK: __SYSTEM_CHECK__,
|
||||||
|
initad = SRPREPCHNK: sramprep;
|
||||||
|
}
|
||||||
|
SEGMENTS {
|
||||||
|
ZEROPAGE: load = ZP, type = zp;
|
||||||
|
EXTZP: load = ZP, type = zp, optional = yes;
|
||||||
|
|
||||||
|
SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes;
|
||||||
|
LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized
|
||||||
|
SRPREP: load = SRPREPCHNK, type = rw, define = yes;
|
||||||
|
SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes;
|
||||||
|
SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes;
|
||||||
|
STARTUP: load = MAIN, type = ro, define = yes;
|
||||||
|
LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;
|
||||||
|
ONCE: load = MAIN, type = ro, optional = yes;
|
||||||
|
CODE: load = MAIN, type = ro, define = yes;
|
||||||
|
RODATA: load = MAIN, type = ro;
|
||||||
|
DATA: load = MAIN, type = rw;
|
||||||
|
INIT: load = MAIN, type = rw, optional = yes;
|
||||||
|
BSS: load = MAIN, type = bss, define = yes;
|
||||||
|
SRPREPHDR: load = UNUSED, type = ro;
|
||||||
|
SRPREPTRL: load = UNUSED, type = ro;
|
||||||
|
}
|
||||||
|
FEATURES {
|
||||||
|
CONDES: type = constructor,
|
||||||
|
label = __CONSTRUCTOR_TABLE__,
|
||||||
|
count = __CONSTRUCTOR_COUNT__,
|
||||||
|
segment = ONCE;
|
||||||
|
CONDES: type = destructor,
|
||||||
|
label = __DESTRUCTOR_TABLE__,
|
||||||
|
count = __DESTRUCTOR_COUNT__,
|
||||||
|
segment = RODATA;
|
||||||
|
CONDES: type = interruptor,
|
||||||
|
label = __INTERRUPTOR_TABLE__,
|
||||||
|
count = __INTERRUPTOR_COUNT__,
|
||||||
|
segment = RODATA,
|
||||||
|
import = __CALLIRQ__;
|
||||||
|
}
|
||||||
@@ -203,7 +203,7 @@ is <it/left out/, keep this in mind.
|
|||||||
The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/
|
The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/
|
||||||
don't matter.
|
don't matter.
|
||||||
|
|
||||||
<sect2><tt/atari-xex.cfg/<p>
|
<sect2><tt/atari-asm-xex.cfg/<p>
|
||||||
|
|
||||||
This config file allows writing multi segment binaries easily, without having to
|
This config file allows writing multi segment binaries easily, without having to
|
||||||
write the header explicitly on each segment.
|
write the header explicitly on each segment.
|
||||||
@@ -213,7 +213,8 @@ format support on LD65 instead of the standard binary output, so it does not
|
|||||||
have the <tt/__AUTOSTART/ nor the <tt/__EXEHDR__/ symbols.
|
have the <tt/__AUTOSTART/ nor the <tt/__EXEHDR__/ symbols.
|
||||||
|
|
||||||
Note that each <tt/MEMORY/ area in the configuration file will have it's own
|
Note that each <tt/MEMORY/ area in the configuration file will have it's own
|
||||||
segment in the output file with the correct headers.
|
segment in the output file with the correct headers, and you can specify and
|
||||||
|
init address INITAD) for each memory area.
|
||||||
|
|
||||||
<sect2><tt/atari-cart.cfg/<p>
|
<sect2><tt/atari-cart.cfg/<p>
|
||||||
|
|
||||||
@@ -242,6 +243,18 @@ would need to be split in more parts and the parts to be loaded manually.
|
|||||||
To write the generated file to a cassette, a utility (<tt/w2cas.com/) to run
|
To write the generated file to a cassette, a utility (<tt/w2cas.com/) to run
|
||||||
on an Atari is provided in the <tt/util/ directory of <tt/atari/ target dir.
|
on an Atari is provided in the <tt/util/ directory of <tt/atari/ target dir.
|
||||||
|
|
||||||
|
<sect2><tt/atari-xex.cfg/<p>
|
||||||
|
|
||||||
|
This config file shows how to write a binary using the ATARI (xex) file format
|
||||||
|
support on LD65, this simplifies the memory areas and allows to add new memory
|
||||||
|
areas easily without writing new headers and trailers.
|
||||||
|
|
||||||
|
Note that the default C library includes the system-check chunk, so in this
|
||||||
|
linker configuration we suppress the importing of the header and trailer for
|
||||||
|
this chunk by defining the standard import symbols to a 0 value. For the
|
||||||
|
initialization address of the system-check chunk, the INITAD is set directly in
|
||||||
|
the configuration.
|
||||||
|
|
||||||
<sect1><tt/atarixl/ config files<p>
|
<sect1><tt/atarixl/ config files<p>
|
||||||
|
|
||||||
<sect2>default config file (<tt/atarixl.cfg/)<p>
|
<sect2>default config file (<tt/atarixl.cfg/)<p>
|
||||||
@@ -265,6 +278,15 @@ The files generated by this config file include the
|
|||||||
<ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can
|
<ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can
|
||||||
optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">.
|
optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">.
|
||||||
|
|
||||||
|
<sect2><tt/atarixl-xex.cfg/<p>
|
||||||
|
|
||||||
|
Similar to the <tt/atari-xex.cfg/ above, this config file shows how to write a
|
||||||
|
binary using the ATARI (xex) file format support on LD65.
|
||||||
|
|
||||||
|
In addition to the suppressing of the system-check headers and trailers, this
|
||||||
|
also suppresses the shadow-ram-preparation headers and trailers, but does this
|
||||||
|
by defining an "UNUSED" memory area that is not written to the output file.
|
||||||
|
|
||||||
|
|
||||||
<sect>Platform specific header files<p>
|
<sect>Platform specific header files<p>
|
||||||
|
|
||||||
|
|||||||
@@ -938,9 +938,24 @@ has several attributes that may be defined here.
|
|||||||
}
|
}
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
The Atari file format has only one attribute, <tt/RUNAD/ that allows to specify
|
The Atari file format has two attributes:
|
||||||
a symbol as the run address of the binary. If the attribute is omiteed, no run
|
|
||||||
address is specified.
|
<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>
|
<tscreen><verb>
|
||||||
FORMATS {
|
FORMATS {
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
;DEBUG = 1
|
;DEBUG = 1
|
||||||
|
|
||||||
.export __SYSTEM_CHECK__: absolute = 1
|
.export __SYSTEM_CHECK__, __SYSCHK_END__
|
||||||
.import __SYSCHK_LOAD__
|
|
||||||
.import __STARTADDRESS__
|
.import __STARTADDRESS__
|
||||||
|
|
||||||
; the following imports are only needed for the 'atari' target version
|
; the following imports are only needed for the 'atari' target version
|
||||||
@@ -25,10 +24,12 @@
|
|||||||
.import __STACKSIZE__
|
.import __STACKSIZE__
|
||||||
.import __RESERVED_MEMORY__
|
.import __RESERVED_MEMORY__
|
||||||
|
|
||||||
|
; import our header and trailers
|
||||||
|
.forceimport __SYSCHKHDR__, __SYSCHKTRL__
|
||||||
|
|
||||||
.include "zeropage.inc"
|
.include "zeropage.inc"
|
||||||
.include "atari.inc"
|
.include "atari.inc"
|
||||||
|
|
||||||
|
|
||||||
.macro print_string text
|
.macro print_string text
|
||||||
.local start, cont
|
.local start, cont
|
||||||
jmp cont
|
jmp cont
|
||||||
@@ -229,25 +230,10 @@ delay1: ldx #0
|
|||||||
|
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
end:
|
__SYSTEM_CHECK__=syschk
|
||||||
|
__SYSCHK_END__:
|
||||||
|
|
||||||
.ifndef __ATARIXL__
|
.ifndef __ATARIXL__
|
||||||
tmp: ; outside of the load chunk, some kind of poor man's .bss
|
tmp: ; outside of the load chunk, some kind of poor man's .bss
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; Chunk header
|
|
||||||
|
|
||||||
.segment "SYSCHKHDR"
|
|
||||||
|
|
||||||
.word __SYSCHK_LOAD__
|
|
||||||
.word end - 1
|
|
||||||
|
|
||||||
; ------------------------------------------------------------------------
|
|
||||||
; Chunk "trailer" - sets INITAD
|
|
||||||
|
|
||||||
.segment "SYSCHKTRL"
|
|
||||||
|
|
||||||
.word INITAD
|
|
||||||
.word INITAD+1
|
|
||||||
.word syschk
|
|
||||||
|
|||||||
16
libsrc/atari/system_check_hdr.s
Normal file
16
libsrc/atari/system_check_hdr.s
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
;
|
||||||
|
; Atari startup system check headers
|
||||||
|
;
|
||||||
|
; Christian Groessler, chris@groessler.org, 2013
|
||||||
|
;
|
||||||
|
.export __SYSCHKHDR__: absolute = 1
|
||||||
|
.import __SYSCHK_LOAD__, __SYSCHK_END__
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Chunk header
|
||||||
|
|
||||||
|
.segment "SYSCHKHDR"
|
||||||
|
|
||||||
|
.word __SYSCHK_LOAD__
|
||||||
|
.word __SYSCHK_END__ - 1
|
||||||
|
|
||||||
17
libsrc/atari/system_check_trailer.s
Normal file
17
libsrc/atari/system_check_trailer.s
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
;
|
||||||
|
; Atari startup system check headers
|
||||||
|
;
|
||||||
|
; Christian Groessler, chris@groessler.org, 2013
|
||||||
|
;
|
||||||
|
.export __SYSCHKTRL__: absolute = 1
|
||||||
|
.import __SYSTEM_CHECK__
|
||||||
|
|
||||||
|
.include "atari.inc"
|
||||||
|
; ------------------------------------------------------------------------
|
||||||
|
; Chunk "trailer" - sets INITAD
|
||||||
|
|
||||||
|
.segment "SYSCHKTRL"
|
||||||
|
|
||||||
|
.word INITAD
|
||||||
|
.word INITAD+1
|
||||||
|
.word __SYSTEM_CHECK__
|
||||||
@@ -1007,6 +1007,7 @@ static void ParseXex (void)
|
|||||||
{
|
{
|
||||||
static const IdentTok Attributes [] = {
|
static const IdentTok Attributes [] = {
|
||||||
{ "RUNAD", CFGTOK_RUNAD },
|
{ "RUNAD", CFGTOK_RUNAD },
|
||||||
|
{ "INITAD", CFGTOK_INITAD },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Remember the attributes read */
|
/* Remember the attributes read */
|
||||||
@@ -1017,6 +1018,8 @@ static void ParseXex (void)
|
|||||||
};
|
};
|
||||||
unsigned AttrFlags = atNone;
|
unsigned AttrFlags = atNone;
|
||||||
Import *RunAd = 0;
|
Import *RunAd = 0;
|
||||||
|
Import *InitAd;
|
||||||
|
MemoryArea *InitMem;
|
||||||
|
|
||||||
/* Read the attributes */
|
/* Read the attributes */
|
||||||
while (CfgTok == CFGTOK_IDENT) {
|
while (CfgTok == CFGTOK_IDENT) {
|
||||||
@@ -1046,6 +1049,24 @@ static void ParseXex (void)
|
|||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
break;
|
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:
|
default:
|
||||||
FAIL ("Unexpected attribute token");
|
FAIL ("Unexpected attribute token");
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ typedef enum {
|
|||||||
CFGTOK_VERSION,
|
CFGTOK_VERSION,
|
||||||
CFGTOK_FORMAT,
|
CFGTOK_FORMAT,
|
||||||
CFGTOK_RUNAD,
|
CFGTOK_RUNAD,
|
||||||
|
CFGTOK_INITAD,
|
||||||
|
|
||||||
CFGTOK_LOAD,
|
CFGTOK_LOAD,
|
||||||
CFGTOK_RUN,
|
CFGTOK_RUN,
|
||||||
|
|||||||
@@ -58,6 +58,12 @@
|
|||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* Linked list of memory area initialization addresses */
|
||||||
|
typedef struct XexInitAd {
|
||||||
|
MemoryArea *InitMem;
|
||||||
|
Import *InitAd;
|
||||||
|
struct XexInitAd *next;
|
||||||
|
} XexInitAd;
|
||||||
|
|
||||||
|
|
||||||
struct XexDesc {
|
struct XexDesc {
|
||||||
@@ -65,13 +71,13 @@ struct XexDesc {
|
|||||||
FILE* F; /* Output file */
|
FILE* F; /* Output file */
|
||||||
const char* Filename; /* Name of output file */
|
const char* Filename; /* Name of output file */
|
||||||
Import* RunAd; /* Run Address */
|
Import* RunAd; /* Run Address */
|
||||||
|
XexInitAd* InitAds; /* List of Init Addresses */
|
||||||
unsigned long HeadPos; /* Position in the file of current header */
|
unsigned long HeadPos; /* Position in the file of current header */
|
||||||
unsigned long HeadEnd; /* End address of current header */
|
unsigned long HeadEnd; /* End address of current header */
|
||||||
unsigned long HeadSize; /* Last header size, can be removed if zero */
|
unsigned long HeadSize; /* Last header size, can be removed if zero */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -89,6 +95,7 @@ XexDesc* NewXexDesc (void)
|
|||||||
D->F = 0;
|
D->F = 0;
|
||||||
D->Filename = 0;
|
D->Filename = 0;
|
||||||
D->RunAd = 0;
|
D->RunAd = 0;
|
||||||
|
D->InitAds = 0;
|
||||||
D->HeadPos = 0;
|
D->HeadPos = 0;
|
||||||
D->HeadEnd = 0;
|
D->HeadEnd = 0;
|
||||||
D->HeadSize = 0;
|
D->HeadSize = 0;
|
||||||
@@ -113,8 +120,35 @@ void XexSetRunAd (XexDesc* D, Import *RunAd)
|
|||||||
D->RunAd = 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,
|
static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size,
|
||||||
unsigned long Offs attribute ((unused)),
|
unsigned long Offs attribute ((unused)),
|
||||||
void* Data)
|
void* Data)
|
||||||
@@ -199,11 +233,14 @@ static void XexFakeSegment (XexDesc *D, unsigned long Addr)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void XexWriteMem (XexDesc* D, MemoryArea* M)
|
static unsigned long XexWriteMem (XexDesc* D, MemoryArea* M)
|
||||||
/* Write the segments of one memory area to a file */
|
/* Write the segments of one memory area to a file */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Store initial position to get total file size */
|
||||||
|
unsigned long StartPos = ftell (D->F);
|
||||||
|
|
||||||
/* Always write a segment header for each memory area */
|
/* Always write a segment header for each memory area */
|
||||||
D->HeadPos = 0;
|
D->HeadPos = 0;
|
||||||
|
|
||||||
@@ -321,6 +358,8 @@ static void XexWriteMem (XexDesc* D, MemoryArea* M)
|
|||||||
if (D->HeadSize == 0 && D->HeadPos) {
|
if (D->HeadSize == 0 && D->HeadPos) {
|
||||||
fseek (D->F, D->HeadPos, SEEK_SET);
|
fseek (D->F, D->HeadPos, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ftell (D->F) - StartPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -369,8 +408,14 @@ void XexWriteTarget (XexDesc* D, struct File* F)
|
|||||||
for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
|
for (I = 0; I < CollCount (&F->MemoryAreas); ++I) {
|
||||||
/* Get this entry */
|
/* Get this entry */
|
||||||
MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I);
|
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));
|
Print (stdout, 1, " ATARI EXE Dumping `%s'\n", GetString (M->Name));
|
||||||
XexWriteMem (D, M);
|
if (XexWriteMem (D, M) && I) {
|
||||||
|
Write16 (D->F, 0x2E2);
|
||||||
|
Write16 (D->F, 0x2E3);
|
||||||
|
Write16 (D->F, GetExportVal (I->InitAd->Exp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write RUNAD at file end */
|
/* Write RUNAD at file end */
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ void XexWriteTarget (XexDesc* D, File* F);
|
|||||||
void XexSetRunAd (XexDesc* D, Import *RunAd);
|
void XexSetRunAd (XexDesc* D, Import *RunAd);
|
||||||
/* Set the RUNAD export */
|
/* Set the RUNAD export */
|
||||||
|
|
||||||
|
int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd);
|
||||||
|
/* Sets and INITAD for the given memory area */
|
||||||
|
|
||||||
/* End of xex.h */
|
/* End of xex.h */
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ FEATURES {
|
|||||||
}
|
}
|
||||||
MEMORY {
|
MEMORY {
|
||||||
ZP: file = "", define = yes, start = $0082, size = $007E;
|
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:
|
# First memory segment in file, load over COLOR registers:
|
||||||
COLOR: file = %O, start = $2C4, size = 5;
|
COLOR: file = %O, start = $2C4, size = 5;
|
||||||
# Second memory segment, load at page 6:
|
# 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:
|
# Third memory segment in file, load over SDLST register:
|
||||||
SDLST: file = %O, start = $230, size = 2;
|
SDLST: file = %O, start = $230, size = 2;
|
||||||
# Main segment, load at "STARTADDRESS"
|
# Main segment, load at "STARTADDRESS"
|
||||||
@@ -16,11 +18,13 @@ FILES {
|
|||||||
%O: format = atari;
|
%O: format = atari;
|
||||||
}
|
}
|
||||||
FORMATS {
|
FORMATS {
|
||||||
atari: runad = start;
|
atari: runad = start,
|
||||||
|
initad = LOADER: show_load;
|
||||||
}
|
}
|
||||||
SEGMENTS {
|
SEGMENTS {
|
||||||
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
ZEROPAGE: load = ZP, type = zp, optional = yes;
|
||||||
# Place segments in memory areas:
|
# Place segments in memory areas:
|
||||||
|
LOADER: load = LOADER, type = rw;
|
||||||
COLOR: load = COLOR, type = rw;
|
COLOR: load = COLOR, type = rw;
|
||||||
PAGE6: load = PAGE6, type = rw;
|
PAGE6: load = PAGE6, type = rw;
|
||||||
SDLST: load = SDLST, type = rw;
|
SDLST: load = SDLST, type = rw;
|
||||||
|
|||||||
@@ -14,8 +14,25 @@
|
|||||||
.macpack atari
|
.macpack atari
|
||||||
|
|
||||||
; Default RUNAD is "start", export that:
|
; 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
|
; We load color values directly into registers
|
||||||
.segment "COLOR"
|
.segment "COLOR"
|
||||||
|
|||||||
BIN
testcode/lib/atari/multi.xex
Normal file
BIN
testcode/lib/atari/multi.xex
Normal file
Binary file not shown.
Reference in New Issue
Block a user