url="mailto:shawnjefferson@24fightingchickens.com"
name="shawnjefferson@24fightingchickens.com"> and
Christian Groessler, <htmlurl url="mailto:cpg@aladdin.de" name="cpg@aladdin.de">
-<date>11-Aug-2005
+<date>03-Jan-2006
<abstract>
An overview over the Atari runtime system as it is implemented for the cc65 C
<tag/Stack/
The C runtime stack is located at MEMTOP and grows downwards,
regardless of how your linker config file is setup. This
- accomodates the different memory configurations of the Atari
+ accommodates the different memory configurations of the Atari
machines, as well as having a cartridge installed. You can override
this behaviour by writing your own crt0.s file and linking it to
your program (see also <ref name="Final note"
Currently there are no graphics drivers available for the Atari platform.
However, the runtime library provides a function named _graphics, with
a mode parameter just like the BASIC GRAPHICS command. This function will
-turn on the requested graphics mode.
+switch to the requested graphics mode.
There are currently no functions available to access the graphics
memory. The access must be implemented manually.
in effect when the program starts up. Therefore the programmer has to
tell the program beforehand the memory requirements of the graphics
modes the program intends to use.
-This can be done with the __RESERVED_MEMORY__ linker config
+This can be done by using the __RESERVED_MEMORY__ linker config
variable. The number specified there describes the number of bytes to
subtract from the top of available memory as seen from the runtime
library. This memory is then used by the screen buffer.
only be seen as a rule of thumb. Since the screen buffer memory needs
to start at specific boundaries, the numbers depend on the current top
of available memory.
-These numbers were determined by a BASIC program.
+The following numbers were determined by a BASIC program.
<table>
<tabular ca="rr">
<descrip>
- <tag><tt/atari-stdjoy.joy/</tag>
+ <tag><tt/ataristd.joy/</tag>
Supports up to four standard joysticks connected to the joystick ports of
the Atari.
for sectors 1 to 3, regardless of the type of diskette.
+<sect>CONIO implementation<label id="conio"><p>
+
+The console I/O is speed optimized therefore support for XEP80 hardware
+or f80.com software is missing. Of course you may use stdio.h functions.
+
+
<sect>Other hints<p>
<sect1>Function keys<p>
the program should go below $4000 and the DATA and RODATA
segments should go above $7FFF.
<p>
-The main problem is that the EXE header generated by the cc65 runtine
+The main problem is that the EXE header generated by the cc65 runtime
lib is wrong. It defines a single load chunk with the sizes/addresses
-of the CODE, RODATA, and DATA segments (the whole user program).
+of the LOWCODE, INIT, CODE, RODATA, and DATA segments (the whole user
+program).
<p>
The contents of the EXE header come from the EXEHDR segment, which is
-defined in crt0.s. This cannot be changed w/o modifiying and
+defined in crt0.s. This cannot be changed w/o modifying and
recompiling the cc65 atari runtime lib. Therefore the original EXE
header must be discarded. It will be replaced by a user created
one.
SECHDR: start = $0000, size = $4, file = %O; # second load chunk
RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F
+ TRAILER: start = $0000, size = $0006, file = %O;
}
SEGMENTS {
- EXEHDR: load = BANK, type = wprot;
+ EXEHDR: load = BANK, type = ro;
- NEXEHDR: load = HEADER, type = wprot; # first load chunk
- CODE: load = RAMLO, type = wprot, define = yes;
+ NEXEHDR: load = HEADER, type = ro; # first load chunk
+ LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes;
+ INIT: load = RAMLO, type = ro, optional = yes;
+ CODE: load = RAMLO, type = ro, define = yes;
- CHKHDR: load = SECHDR, type = wprot; # second load chunk
- RODATA: load = RAM, type = wprot, define = yes;
+ CHKHDR: load = SECHDR, type = ro; # second load chunk
+ RODATA: load = RAM, type = ro, define = yes;
DATA: load = RAM, type = rw, define = yes;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
- AUTOSTRT: load = RAM, type = wprot; # defines program entry point
+ AUTOSTRT: load = TRAILER, type = ro; # defines program entry point
}
FEATURES {
CONDES: segment = RODATA,
}
SYMBOLS {
__STACKSIZE__ = $800; # 2K stack
+ __RESERVED_MEMORY__: value = $0, weak = yes;
}
</verb></tscreen>
<p>
The contents of the new NEXEHDR and CHKHDR segments come from this
file (split.s):
<tscreen><verb>
- .import __CODE_LOAD__, __BSS_LOAD__, __CODE_SIZE__
- .import __DATA_LOAD__, __RODATA_LOAD__
+ .import __LOWCODE_LOAD__, __BSS_LOAD__, __CODE_SIZE__
+ .import __CODE_LOAD__, __DATA_LOAD__, __RODATA_LOAD__
.segment "NEXEHDR"
.word $FFFF ; EXE file magic number
; 1st load chunk
- .word __CODE_LOAD__
+ .word __LOWCODE_LOAD__
.word __CODE_LOAD__ + __CODE_SIZE__ - 1
.segment "CHKHDR"
<sect2>Low data and high code example<p>
-Goal: Put RODATA and DATA into low memory and CODE with BSS into high
-memory (split2.cfg):
+Goal: Put RODATA and DATA into low memory and LOWCODE, INIT, CODE, BSS
+into high memory (split2.cfg):
<tscreen><verb>
MEMORY {
SECHDR: start = $0000, size = $4, file = %O; # second load chunk
RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F
+ TRAILER: start = $0000, size = $0006, file = %O;
}
SEGMENTS {
- EXEHDR: load = BANK, type = wprot; # discarded old EXE header
+ EXEHDR: load = BANK, type = ro; # discarded old EXE header
- NEXEHDR: load = HEADER, type = wprot; # first load chunk
- RODATA: load = RAMLO, type = wprot, define = yes;
+ NEXEHDR: load = HEADER, type = ro; # first load chunk
+ RODATA: load = RAMLO, type = ro, define = yes;
DATA: load = RAMLO, type = rw, define = yes;
- CHKHDR: load = SECHDR, type = wprot; # second load chunk
- CODE: load = RAM, type = wprot, define = yes;
+ CHKHDR: load = SECHDR, type = ro; # second load chunk
+ LOWCODE: load = RAM, type = ro, define = yes, optional = yes;
+ INIT: load = RAM, type = ro, optional = yes;
+ CODE: load = RAM, type = ro, define = yes;
BSS: load = RAM, type = bss, define = yes;
ZEROPAGE: load = ZP, type = zp;
- AUTOSTRT: load = RAM, type = wprot; # defines program entry point
+ AUTOSTRT: load = TRAILER, type = ro; # defines program entry point
}
FEATURES {
CONDES: segment = RODATA,
}
SYMBOLS {
__STACKSIZE__ = $800; # 2K stack
+ __RESERVED_MEMORY__: value = $0, weak = yes;
}
</verb></tscreen>
New contents for NEXEHDR and CHKHDR are needed (split2.s):
<tscreen><verb>
- .import __CODE_LOAD__, __BSS_LOAD__, __DATA_SIZE__
+ .import __LOWCODE_LOAD__, __BSS_LOAD__, __DATA_SIZE__
.import __DATA_LOAD__, __RODATA_LOAD__
.segment "NEXEHDR"
.word __DATA_LOAD__ + __DATA_SIZE__ - 1
.segment "CHKHDR"
- .word __CODE_LOAD__
+ .word __LOWCODE_LOAD__
.word __BSS_LOAD__ - 1
</verb></tscreen>