<author>
<url url="mailto:shawnjefferson@24fightingchickens.com" name="Shawn Jefferson"> and<newline>
<url url="mailto:chris@groessler.org" name="Christian Groessler">
-<date>2014-04-10
+<date>2014-04-24
<abstract>
An overview over the Atari runtime system as it is implemented for the cc65 C
sufficient to know that the first load chunk(s) do preparation work and the
main part of the program is in the last load chunk.
-The values determining the size of the main part of the program (the only load
+The values determining the size of the main part of the program (the second load
chunk for <tt/atari/, the third load chunk for <tt/atarixl/) are calculated in
the crt0.s file from the __STARTUP_LOAD__ and __BSS_LOAD__ values.
Be aware of that if you create a custom linker config file and start moving segments around (see section
</enum>
With the default load address of $2400 this gives a usable memory range of
-[$2400-$CFFF]. Note that the default load address for <tt/atarixl/ is
-different (and lower) that the default load address for <tt/atari/. This is no problem since
-on the <tt/atarixl/ target the first load chunk makes sure that the loaded prgram won't overwrite
-memory below MEMLO. See <ref name="atarixl load chunks" id="xlchunks">.
+[$2400-$CFFF].
+Please note that the first load chunk (which checks the system
+compatibilty and available memory) will always be loaded at
+$2E00, regardless of the specified start address. This address
+can only be changed by a custom linker config file.
Special locations:
($58).
<tag/Stack/
- The C runtime stack is located at end of the RAM memory area ($CFFF)
+ The C runtime stack is located at end of the MAIN memory area ($CFFF)
and grows downwards.
<tag/Heap/
The size of a cassette boot file is restricted to 32K. Larger programs
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 to run
-on an Atari is provided in the <tt/targetutil/ directory (<tt/w2cas.com/).
+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.
<sect1><tt/atarixl/ config files<p>
<item>_getcolor
<item>_getdefdev
<item>_graphics
+<item>_is_cmdline_dos
<item>_rest_vecs
<item>_save_vecs
<item>_scroll
</descrip><p>
+<sect1>Display lists<p>
+
+A major feature of the Atari graphics chip "ANTIC" is to
+process instructions for the display generation.
+cc65 supports constructing these display lists by offering defines
+for the instructions. In conjunction with the "void"-variable extension
+of cc65, display lists can be created quite comfortable:
+
+<verb>
+...
+unsigned char ScreenMemory[100];
+
+void DisplayList =
+{
+ DL_BLK8,
+ DL_BLK8,
+ DL_BLK8,
+ DL_LMS(DL_CHR20x8x2),
+ ScreenMemory,
+ DL_CHR20x8x2,
+ DL_CHR20x8x2,
+ DL_CHR20x8x2,
+ DL_BLK4,
+ DL_CHR20x8x2,
+ DL_JVB
+};
+...
+POKEW(560,(unsigned int)&DisplayList); // SDLSTL
+...
+</verb>
+
+Please inspect the <tt/_antic.h/ header file to detemine the supported
+instruction names. Modifiers on instructions can be nested without need
+for an order:
+
+<tt/DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_MAP80x4x2))))/
+
+Please mind that ANTIC has memory alignment requirements for "player
+missile graphics"-data, font data, display lists and screen memory. Creation
+of a special linker configuration with appropriate aligned segments and
+switching to that segment in the c-code is usually neccessary. A more memory
+hungry solution consists in using the "<tt/posix_memalign()/" function in
+conjunction with copying your data to the allocated memory.
+
+<sect1>Character mapping<p>
+
+The Atari has two representations for characters:
+<enum>
+<item> ATASCII is character mapping which is similar to ASCII and used
+by the CIO system of the OS. This is the default mapping of cc65 when
+producing code for the atari target.
+<item> The internal/screen mapping represents the real value of the
+screen ram when showing a character.
+</enum>
+
+For direct memory access (simplicity and speed) enabling the internal
+mapping can be useful. This can be achieved by including the
+"<tt/atari_screen_charmap.h/" header.
+
+A word of caution: Since the <tt/0x00/ character has to be mapped in an
+incompatible way to the C-standard, the usage of string functions in
+conjunction with internal character mapped strings delivers unexpected
+results regarding the string length. The end of strings are detected where
+you may not expect them (too early or (much) too late). Internal mapped
+strings typically support the "<tt/mem...()/" functions.
+
+<em>For assembler sources the macro "<tt/scrcode/" from the "<tt/atari.mac/"
+package delivers the same feature.</em>
+
+You can switch back to the ATASCII mapping by including
+"<tt/atari_atascii_charmap.h/".
+
+A final note: Since cc65 has currently some difficulties with string merging
+under different mappings, defining remapped strings works only flawlessly
+with static array initialization:
+
+<verb>
+#include <atari_screen_charmap.h>
+char pcScreenMappingString[] = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char pcAtasciiMappingString[] = "Hello Atari!";
+</verb>
+
+delivers correct results, while
+
+<verb>
+#include <atari_screen_charmap.h>
+char* pcScreenMappingString = "Hello Atari!";
+
+#include <atari_atascii_charmap.h>
+char* pcAtasciiMappingString = "Hello Atari!";
+</verb>
+
+does not.
<sect>Loadable drivers<p>
<tt/atrstd.joy (atrstd_joy)/|<tt/atrxstd.joy (atrxstd_joy)/|Supports up to two/four standard joysticks connected to the joystick ports of the Atari. (Four on the pre-XL systems, two on XL or newer.)@
<tt/atrmj8.joy (atrmj8_joy)/|<tt/atrxmj8.joy (atrxmj8_joy)/|Supports up to eight standard joysticks connected to a MultiJoy adapter.
</tabular>
-<caption>
</table>
Default drivers: <tt/atrstd.joy (atrstd_joy)/ and <tt/atrxstd.joy (atrxstd_joy)/.
<tt/atrtrk.mou (atrtrk_mou)/|<tt/atrxtrk.mou (atrxtrk_mou)/|Supports an Atari trakball.@
<tt/atrtt.mou (atrtt_mou)/|<tt/atrxtt.mou (atrxtt_mou)/|Supports an Atari touch tablet.
</tabular>
-<caption>
</table>
All mouse devices connect to joystick port #0.
Default drivers: <tt/atrst.mou (atrst_mou)/ and <tt/atrxst.mou (atrxst_mou)/.
+<sect2>Mouse callbacks<p>
+
+There are two mouse callbacks available.
+<p>
+The "text mode" callbacks (<tt/mouse_txt_callbacks/) display the mouse cursor as a "diamond" character
+on the standard "GRAPHICS 0" text mode screen. The mouse cursor character can be changed by an
+assembly file defining the character by exporting the zeropage symbol <tt/mouse_txt_char/.
+The default file looks like this:
+<tscreen><verb>
+ .export mouse_txt_char : zp = 96 ; 'diamond' screen code
+</verb></tscreen>
+<p>
+The "P/M" callbacks (<tt/mouse_pm_callbacks/) use Player-Missile graphics for the mouse cursor.
+The cursor shape can be changed, too, by an assembly file. Here's the default shape definition:
+<tscreen><verb>
+ .export mouse_pm_bits
+ .export mouse_pm_height : zeropage
+ .export mouse_pm_hotspot_x : zeropage
+ .export mouse_pm_hotspot_y : zeropage
+ .rodata
+mouse_pm_bits:
+ .byte %11110000
+ .byte %11000000
+ .byte %10100000
+ .byte %10010000
+ .byte %10001000
+ .byte %00000100
+ .byte %00000010
+mouse_pm_height = * - mouse_pm_bits
+; hot spot is upper left corner
+mouse_pm_hotspot_x = 0
+mouse_pm_hotspot_y = 0
+</verb></tscreen>
+<p>
+<tt/mouse_pm_bits/ defines the shape of the cursor, <tt/mouse_pm_height/ defines the number of
+bytes in <tt/mouse_pm_bits/. <tt/mouse_pm_hotspot_x/ and <tt/mouse_pm_hotspot_y/ define the
+position in the shape where "the mouse points to". When using this callback page #6 ($600
+ - $6FF) is used for the P/M graphics data and no P/M graphics can otherwise be used
+by the program. The height of the shape (<tt/mouse_pm_height/)
+must not exceed 32 lines since the callback routines cannot handle more than 32 lines.
+<p>
+The default callbacks definition (<tt/mouse_def_callbacks/) is an alias for the "P/M" callbacks.
+
<sect1>RS232 device drivers<p>
Currently there is one RS232 driver. It uses the R: device (therefore
<item>main program&nl;
This load chunk is loaded at the selected program start address (default $2000) and
contains all of the code and data of the program.&nl;
-The contents of this chunk come from the RAM memory area of the linker config file.
+The contents of this chunk come from the MAIN memory area of the linker config file.
</enum>
<sect1>Passing arguments to the program<p>
-Command line arguments can be passed to <tt/main()/ when DOS supports it.
+Command line arguments can be passed to <tt/main()/ when the used DOS supports it.
<enum>
<item>Arguments are separated by spaces.
when they are linked into a program. See the discussion of the <tt/.CONDES/
feature in the <url url="ca65.html" name="assembler manual">.
+Please note that on the Atari targets the <tt/.INTERRUPTOR/s are being
+run in NMI context. The other targets run them in IRQ context.
<sect1>Reserving a memory area inside a program<label id="memhole"><p>
<p>
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 STARTUP, LOWCODE, INIT, CODE, RODATA, and DATA segments, in
+of the STARTUP, LOWCODE, ONCE, CODE, RODATA, and DATA segments, in
fact, the whole user program (we're disregarding the "system check"
load chunk here).
<p>
NEXEHDR: load = FSTHDR, type = ro; # first load chunk
STARTUP: load = RAMLO, type = ro, define = yes;
LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes;
- INIT: load = RAMLO, type = ro, optional = yes;
+ ONCE: load = RAMLO, type = ro, optional = yes;
CODE: load = RAMLO, type = ro, define = yes;
CHKHDR: load = SECHDR, type = ro; # second load chunk
AUTOSTRT: load = RAM, type = ro; # defines program entry point
}
FEATURES {
- CONDES: segment = RODATA,
+ CONDES: segment = ONCE,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
<p>
The newly added NEXEHDR segment defines the correct chunk header for the
first intended load chunk. It
-puts the STARTUP, LOWCODE, INIT, and CODE segments, which are the
+puts the STARTUP, LOWCODE, ONCE, and CODE segments, which are the
segments containing only code, into load chunk #1 (RAMLO memory area).
<p>
The header for the second load chunk comes from the new CHKHDR
<sect2>Low data and high code example<p>
-Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, INIT,
+Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, ONCE,
CODE, BSS, ZPSAVE into high memory (split2.cfg):
<tscreen><verb>
CHKHDR: load = SECHDR, type = ro; # second load chunk
STARTUP: load = RAM, type = ro, define = yes;
- INIT: load = RAM, type = ro, optional = yes;
+ ONCE: load = RAM, type = ro, optional = yes;
CODE: load = RAM, type = ro, define = yes;
BSS: load = RAM, type = bss, define = yes;
AUTOSTRT: load = RAM, type = ro; # defines program entry point
}
FEATURES {
- CONDES: segment = RODATA,
+ CONDES: segment = ONCE,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;