]> git.sur5r.net Git - cc65/blobdiff - doc/atari.sgml
Adds documentation and a sample config file for the ATARI format.
[cc65] / doc / atari.sgml
index c9e640d9ed13d1aa9e8b8100319b97725e5b62d2..346377b36493519e48a5ff477de9253ae1d818e1 100644 (file)
@@ -1,11 +1,10 @@
 <!doctype linuxdoc system>
 
 <article>
-
 <title>Atari specific information for cc65
-<author>Shawn Jefferson, <htmlurl url="mailto:shawnjefferson@24fightingchickens.com" name="shawnjefferson@24fightingchickens.com">
-Christian Groessler, <htmlurl url="cpg@aladdin.de" name="cpg@aladdin.de">
-<date>16-Oct-2003
+<author>
+<url url="mailto:shawnjefferson@24fightingchickens.com" name="Shawn Jefferson"> and<newline>
+<url url="mailto:chris@groessler.org" name="Christian Groessler">
 
 <abstract>
 An overview over the Atari runtime system as it is implemented for the cc65 C
@@ -24,8 +23,18 @@ with the cc65 C compiler. It describes the memory layout, Atari specific
 header files, available drivers, and any pitfalls specific to that
 platform.
 
+The Atari runtime support comes in two flavors: <tt/atari/ and <tt/atarixl/.
+The <tt/atari/ target supports all Atari 8-bit computers, the <tt/atarixl/ only
+supports XL type or newer machines (excluding the 600XL).
+
+The <tt/atarixl/ runtime makes the whole 64K of memory available, with the
+exception of the I/O area at &dollar;D000 - &dollar;D7FF. Since the
+<tt/atarixl/ runtime has some <ref name="limitations" id="xllimitations">, it is
+recommended to use the <tt/atari/ target unless lack of memory dictates the
+use of the <tt/atarixl/ target.
+
 Please note that Atari specific functions are just mentioned here, they are
-described in detail in the separate <htmlurl url="funcref.html" name="function
+described in detail in the separate <url url="funcref.html" name="function
 reference">. Even functions marked as "platform dependent" may be available on
 more than one platform. Please see the function reference for more
 information.
@@ -33,30 +42,53 @@ information.
 
 <sect>Binary format<p>
 
-The standard binary output format generated by the linker for the
+The Atari DOS executable file format supports more than one load block (<it/chunk/).
+
+The default binary output format generated by the linker for the
 Atari target is a machine language program with a standard executable
-header (FF FF &lt;start address&gt; &lt;end address&gt;). These values are
-calculated in the crt0.s file from the __CODE_LOAD__ and __BSS_LOAD__
-values, so keep this in mind if you create a custom linker config file
-and start moving segments around.  You can override this behaviour by
-creating your own crt0.s file and linking it into your program.  A run
-vector is added to the end of the file (&dollar;02E0 &lt;run vector&gt;)
-and is calculated using __CODE_LOAD__ in crt0.s also.
+header (FF FF &lt;load chunk #1&gt; ... &lt;load chunk #n&gt).
+A load chunk has the format &lsqb;&lt;2 byte start address&gt; &lt;2 bytes end address&gt;
+&lt;chunk data&gt;&rsqb;.
+A run vector is added to the end of the
+file (&dollar;02E0 &dollar;02E1 &lt;run vector&gt;) and is calculated using
+the <tt/start/ label in crt0.s.  (Technically the run vector is also a load chunk,
+but is not regarded as such here.)
+
+An <tt/atari/ program has two load chunks, an <tt/atarixl/ program has three load
+chunks.  The load chunks are defined in the linker configuration files.  For more
+detailed information about the load chunks see the chapter
+<ref name="Technical details" id="techdetail">. For the discussion here it's
+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 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
+<ref name="Reserving a memory area inside the program" id="memhole">).
 
 
 <sect>Memory layout<p>
 
-The default linker script assumes that the BASIC ROM is disabled (or
-the BASIC cartridge unplugged). This gives a unsable memory range from
-&dollar;2E00 - &dollar;BC1F. The library startup code examines the
+<sect1><tt/atari/ target<p>
+
+The default linker config file assumes that the BASIC ROM is disabled (or
+the BASIC cartridge unplugged). This gives a usable memory range of
+&lsqb;&dollar;2000-&dollar;BC1F&rsqb;. The library startup code examines the
 current memory configuration, which depends on the size of the
-installed memory and cartridges present, by inspecting the value in
-the MEMTOP (&dollar;2E5) variable. Then the initial stack pointer,
-which indicates the upper bound of memory used, is adjusted. The load
-address of &dollar;2E00 was chosen to accommodate having a DOS loaded
-and a driver that resides in low memory such as the 850 R: handler.
-You can override this behaviour by creating a custom linker config
-file.
+installed memory and cartridges. It does so by using the value in
+the MEMTOP (&dollar;2E5) variable as highest memory address the program
+can use. The initial stack pointer, which is the upper bound of
+memory used by the program, is set to this value, minus an optionally
+defined __RESERVED_MEMORY__ value.
+
+The default load address of &dollar;2000 can be changed by creating a custom
+linker config file or by using the "--start-addr" cl65 command line
+argument or the "--start-addr" or "-S" ld65 command line arguments.
+
+Please note that the first load chunk (which checks the available memory)
+will always be loaded at &dollar;2E00, regardless of the specified start
+address. This address can only be changed by a custom linker config file.
 
 Special locations:
 
@@ -68,10 +100,11 @@ Special locations:
   <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.
+  your program (see also <ref name="Final note"
+  id="memhole_final_note">).
 
   <tag/Heap/
   The C heap is located at the end of the program and grows towards the C
@@ -79,6 +112,158 @@ Special locations:
 
 </descrip><p>
 
+<sect1><tt/atarixl/ target<p>
+
+The startup code rearranges the memory as follows:
+
+<enum>
+<item>Sceen memory and display list are moved below the program start address.
+<item>The ROM is disabled, making the memory in the areas &lsqb;&dollar;C000-&dollar;CFFF&rsqb;
+and &lsqb;&dollar;D800-&dollar;FFF9&rsqb; available.
+<item>Character generator data is copied from ROM to the CHARGEN location specified in the
+linker config file.  This is (in the default <tt/atarixl.cfg/ file) at the same address as
+where it is in ROM (&dollar;E000, it can be changed, see <ref name="atarixl chargen location"
+id="chargenloc">).  With the character generator at &dollar;E000, there are two upper memory
+areas available, &lsqb;&dollar;D800-&dollar;DFFF&rsqb; and &lsqb;&dollar;E400-&dollar;FFF9&rsqb;.
+</enum>
+
+With the default load address of &dollar;2400 this gives a usable memory range of
+&lsqb;&dollar;2400-&dollar;CFFF&rsqb;.
+
+Please note that the first load chunk (which checks the system
+compatibilty and available memory) will always be loaded at
+&dollar;2E00, regardless of the specified start address. This address
+can only be changed by a custom linker config file.
+
+Special locations:
+
+<descrip>
+  <tag/Text screen/
+  The text screen depends on the selected load address (&dollar;2400
+  by default), and resides directly before that address, rounded to the next
+  lower page boundary.
+  The screen memory's start address can be obtained from the SAVMSC variable
+  (&dollar;58).
+
+  <tag/Stack/
+  The C runtime stack is located at end of the MAIN memory area (&dollar;CFFF)
+  and grows downwards.
+
+  <tag/Heap/
+  The C heap is located at the end of the program (end of BSS segment) and
+  grows towards the C runtime stack.
+
+</descrip><p>
+
+<sect>Linker configurations<p>
+
+The ld65 linker comes with default config files for the Atari. There
+are two targets for the Atari, <tt/atari/ and <tt/atarixl/.
+The default config file for <tt/atari/ is selected with
+<tt/-t atari/, and the default config file for <tt/atarixl/ is selected with
+<tt/-t atarixl/.
+The Atari package comes with additional secondary linker config files which
+can be used via <tt/-t atari -C &lt;configfile&gt;/ (for <tt/atari/ target) or
+<tt/-t atarixl -C &lt;configfile&gt;/ (for <tt/atarixl/ target).
+
+<sect1><tt/atari/ config files<p>
+
+<sect2>default config file (<tt/atari.cfg/)<p>
+
+The default configuration is tailored to C programs. It creates files
+which have a default load address of &dollar;2000.
+
+The files generated by this config file include the
+<ref name="&dquot;system check&dquot;" id="syschk"> load chunk. It can
+optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">.
+
+<sect2><tt/atari-asm.cfg/<p>
+
+This config file aims to give the assembler programmer maximum
+flexibility. All program segments (<tt/CODE/, <tt/DATA/, etc.) are
+optional.
+
+By default it creates regular DOS executable files, which have a default
+load address of &dollar;2E00. It's also possible to generate an image of
+just the program data without EXE header, load address, or (auto-)start address.
+To you so, you have to define the symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/
+when linking the program. Therefore, to generate a "plain" binary file, pass the
+options "<tt/-D__AUTOSTART__=1 -D__EXEHDR__=1/" to the linker.
+It's also possible to create a non auto-starting program file, by defining
+only the <tt/__AUTOSTART__/ symbol. Such a program has to be run manually
+after being loaded by DOS (for example by using the "M" option of DOS 2.5).
+Defining only the <tt/__EXEHDR__/ symbol will create a (useless) file which
+doesn't conform to the DOS executable file format (like a "plain" binary file)
+but still has the "autostart" load chunk appended.
+
+The sections of the file which the defines refer to (<tt/__AUTOSTART__/ for
+the autostart trailer, <tt/__EXEHDR__/ for the EXE header and load address)
+is <it/left out/, keep this in mind.
+
+The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/
+don't matter.
+
+<sect2><tt/atari-xex.cfg/<p>
+
+This config file allows writing multi segment binaries easily, without having to
+write the header explicitly on each segment.
+
+It is similar to the <tt/atari-asm.cfg/ above, but uses the ATARI (xex) file
+format support on LD65 instead of the standard binary output, so it does not
+have the <tt/__AUTOSTART/ nor the <tt/__EXEHDR__/ symbols.
+
+Note that each <tt/MEMORY/ area in the configuration file will have it's own
+segment in the output file with the correct headers.
+
+<sect2><tt/atari-cart.cfg/<p>
+
+This config file can be used to create 8K or 16K cartridges. It's suited both
+for C and assembly language programs.
+
+By default, an 8K cartridge is generated. To create a 16K cartridge, pass the
+size of the cartridge to the linker, like "<tt/-D__CARTSIZE__=0x4000/".
+The only valid values for <tt/__CARTSIZE__/ are 0x2000 and 0x4000.
+
+The option byte of the cartridge can be set with the <tt/__CARTFLAGS__/
+value, passed to the linker. The default value is &dollar;01, which means
+that the cartridge doesn't prevent the booting of DOS.
+
+The option byte will be located at address &dollar;BFFD. For more information
+about its use, see e.g. "Mapping the Atari".
+
+<sect2><tt/atari-cassette.cfg/<p>
+
+This config file can be used to create cassette boot files. It's suited both
+for C and assembly language programs.
+
+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 (<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>
+
+<sect2>default config file (<tt/atarixl.cfg/)<p>
+
+The default configuration is tailored to C programs. It creates files
+which have a default load address of &dollar;2400.
+
+The files generated by this config file include the
+<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">.
+
+<sect2><tt/atarixl-largehimem.cfg/<p>
+
+This is the same as the default config file, but it rearranges the
+high memory beneath the ROM into one large block. In order for this
+config file to work, the runtime library has to be recompiled with a
+special define. See the file <tt/libsrc&sol;atari&sol;Makefile.inc/ in the
+source distribution.
+
+The files generated by this config file include the
+<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">.
 
 
 <sect>Platform specific header files<p>
@@ -89,21 +274,23 @@ header file.
 
 <sect1>Atari specific functions<p>
 
-The functions listed below are special for the Atari. See the <htmlurl
-url="funcref.html" name="function reference"> for declaration and usage.
+The functions and global variable listed below are special for the Atari.
+See the <url url="funcref.html" name="function reference"> for declaration and usage.
 
 <itemize>
-<item>_gtia_mkcolor
 <item>get_ostype
 <item>get_tv
-<item>getcolor
-<item>getdefdev
-<item>graphics
-<item>rest_vecs
-<item>save_vecs
-<item>scroll
-<item>setcolor
-<item>setcolor_low
+<item>_dos_type
+<item>_gtia_mkcolor
+<item>_getcolor
+<item>_getdefdev
+<item>_graphics
+<item>_is_cmdline_dos
+<item>_rest_vecs
+<item>_save_vecs
+<item>_scroll
+<item>_setcolor
+<item>_setcolor_low
 </itemize>
 
 
@@ -140,54 +327,808 @@ chip registers.
 
 </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)&amp;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 &lt;atari_screen_charmap.h&gt;
+char pcScreenMappingString[] = "Hello Atari!";
+
+#include &lt;atari_atascii_charmap.h&gt;
+char pcAtasciiMappingString[] = "Hello Atari!";
+</verb>
+
+delivers correct results, while
+
+<verb>
+#include &lt;atari_screen_charmap.h&gt;
+char* pcScreenMappingString = "Hello Atari!";
+
+#include &lt;atari_atascii_charmap.h&gt;
+char* pcAtasciiMappingString = "Hello Atari!";
+</verb>
+
+does not.
+
+<sect1>Keyboard codes<p>
+
+For direct keyboard scanning in conjunction with e.g. the OS location "CH" (764/$2FC),
+all keyboard codes are available as defined values on C and assembler side.
+
+Example:
+<verb>
+...
+    while (!kbhit());
+    switch (PEEK(764))
+    {
+        case KEY_RETURN:
+        ...
+        case KEY_SPACE:
+        ...
+        case KEY_1:
+        ...
+    }
+...
+</verb>
+
+You can find the C defines in the file "<tt/atari.h/" or "<tt/atari.inc/" for the assembler variant.
 
 
 <sect>Loadable drivers<p>
 
+The names in the parentheses denote the symbols to be used for static linking of the drivers.
+
+
 <sect1>Graphics drivers<p>
 
-Currently there are no graphics drivers available for the Atari platform.
+<table><tabular ca="rrrr">
+<tt/atari/|<tt/atarixl/|screen resolution|display pages@<hline>
+<tt/atr3.tgi (atr3_tgi)/|<tt/atrx3.tgi (atrx3_tgi)/|40x24x4 (CIO mode 3, ANTIC mode 8)|1@
+<tt/atr4.tgi (atr4_tgi)/|<tt/atrx4.tgi (atrx4_tgi)/|80x48x2 (CIO mode 4, ANTIC mode 9)|1@
+<tt/atr5.tgi (atr5_tgi)/|<tt/atrx5.tgi (atrx5_tgi)/|80x48x4 (CIO mode 5, ANTIC mode A)|1@
+<tt/atr6.tgi (atr6_tgi)/|<tt/atrx6.tgi (atrx6_tgi)/|160x96x2 (CIO mode 6, ANTIC mode B)|1@
+<tt/atr7.tgi (atr7_tgi)/|<tt/atrx7.tgi (atrx7_tgi)/|160x96x4 (CIO mode 7, ANTIC mode D)|1@
+<tt/atr8.tgi (atr8_tgi)/|<tt/atrx8.tgi (atrx8_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|1@
+<tt/atr8p2.tgi (atr8p2_tgi)/|<tt/atrx8p2.tgi (atrx8p2_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|2@
+<tt/atr9.tgi (atr9_tgi)/|<tt/atrx9.tgi (atrx9_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode &dollar;40)|1@
+<tt/atr9p2.tgi (atr9p2_tgi)/|<tt/atrx9p2.tgi (atrx9p2_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode &dollar;40)|2@
+<tt/atr10.tgi (atr10_tgi)/|<tt/atrx10.tgi (atrx10_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode &dollar;80)|1@
+<tt/atr10p2.tgi (atr10p2_tgi)/|<tt/atrx10p2.tgi (atrx10p2_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode &dollar;80)|2@
+<tt/atr11.tgi (atr11_tgi)/|<tt/atrx11.tgi (atrx11_tgi)/|80x192x16h (CIO mode 11, ANTIC mode F, GTIA mode &dollar;C0)|1@
+<tt/atr14.tgi (atr14_tgi)/|<tt/atrx14.tgi (atrx14_tgi)/|160x192x2 (CIO mode 14, ANTIC mode C)|1@
+<tt/atr15.tgi (atr15_tgi)/|<tt/atrx15.tgi (atrx15_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|1@
+<tt/atr15p2.tgi (atr15p2_tgi)/|<tt/atrx15p2.tgi (atrx15p2_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|2
+</tabular>
+<!-- <caption>bla bla -->
+</table>
+
+
+Many graphics modes require more memory than the text screen which is
+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.
+
+On the <tt/atari/ target his 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.
+
+On the <tt/atarixl/ target the screen memory resides below the program
+load address.  In order to reserve memory for a graphics mode, one
+simply uses a higher program load address.  There are restrictions on
+selectable load addresses,
+see <ref name="Selecting a good program load address" id="loadaddr">.
+
+The numbers for the different graphics modes presented below should
+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.
+The following numbers were determined by a BASIC program.
+
+<table>
+<tabular ca="rr">
+graphics mode|reserved memory@<hline>
+0|1@
+1|1@
+2|1@
+3|1@
+4|1@
+5|182@
+6|1182@
+7|3198@
+8|7120@
+9|7146@
+10|7146@
+11|7146@
+12|162@
+13|1@
+14|3278@
+15|7120@
+16|1@
+17|1@
+18|1@
+19|1@
+20|1@
+21|184@
+22|1192@
+23|3208@
+24|7146@
+25|7146@
+26|7146@
+27|7146@
+28|162@
+29|1@
+30|3304@
+31|7146
+</tabular>
+<caption>reserved memory required for different graphics modes
+</table>
+
+The values of "1" are needed because the graphics command crashes if
+it doesn't have at least one byte available. This seems to be a bug of
+the Atari ROM code.
+
+Default drivers: <tt/atr8.tgi (atr8_tgi)/ and <tt/atrx8.tgi (atrx8_tgi)/.
 
 <sect1>Extended memory drivers<p>
 
-Currently there are no extended memory drivers available for the Atari
-platform.
+Currently there is only one extended memory driver.  It manages the second 64K of a 130XE.
+
+<table>
+<tabular ca="rr">
+<tt/atari/|<tt/atarixl/@<hline>
+<tt/atr130.emd (atr130_emd)/|<tt/atrx130.emd (atrx130_emd)/
+</tabular>
+</table>
 
 <sect1>Joystick drivers<p>
 
-<descrip>
+Currently there are two joystick drivers available:
 
-  <tag><tt/atari-stdjoy.joy/</tag>
-  Supports up to four standard joysticks connected to the joystick ports of
-  the Atari.
+<table>
+<tabular ca="rrr">
+<tt/atari/|<tt/atarixl/|description@<hline>
+<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>
+</table>
 
-</descrip><p>
+Default drivers: <tt/atrstd.joy (atrstd_joy)/ and <tt/atrxstd.joy (atrxstd_joy)/.
 
+<sect1>Mouse drivers<p>
 
+Currently there are five mouse drivers available:
+
+<table>
+<tabular ca="rrr">
+<tt/atari/|<tt/atarixl/|description@<hline>
+<tt/atrjoy.mou (atrjoy_mou)/|<tt/atrxjoy.mou (atrxjoy_mou)/|Supports a mouse emulated by a standard joystick.@
+<tt/atrst.mou (atrst_mou)/|<tt/atrxst.mou (atrxst_mou)/|Supports an Atari ST mouse.@
+<tt/atrami.mou (atrami_mou)/|<tt/atrxami.mou (atrxami_mou)/|Supports an Amiga mouse.@
+<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>
+</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 (&dollar;600
+ - &dollar;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>Mouse drivers<p>
+<sect1>RS232 device drivers<p>
 
-Currently no drivers available (in fact, the API for loadable mouse drivers
-does not exist). There is a static driver you can use.
+Currently there is one RS232 driver.  It uses the R: device (therefore
+an R: driver needs to be installed) and was tested with the 850
+interface module.
 
+<table>
+<tabular ca="rr">
+<tt/atari/|<tt/atarixl/@<hline>
+<tt/atrrdev.ser (atrrdev_ser)/|<tt/atrxrdev.ser (atrxrdev_ser)/
+</tabular>
+</table>
 
-<sect1>RS232 device drivers<p>
 
-Currently there are no RS232 loadable drivers available for the Atari
-platform. There is a static driver you can use.
+<sect>Limitations<p>
+
+<sect1><tt/Realtime clock/<label id="realtimeclock"<p>
+
+Access to the realtime clock is supported only when running on SpartaDOS-X.
+There needs to be a realtime clock driver installed. This is normally the case
+in the default installation (CONFIG.SYS) of SpartaDOS-X.
+A missing realtime clock driver in SpartaDOS-X is not supported, and the program
+may crash when calling the <tt/clock_settime()/ or <tt/clock_gettime()/
+functions.
+
+The resolution of the realtime clock driver is 1 second.
+
+<sect1><tt/atarixl target/<#if output="info|latex2e"> limitations</#if><label id="xllimitations"<p>
+
+<itemize>
+<item>The display is cleared at program start and at program termination.  This is a side
+effect of relocating the display memory below the program start address.
+<item>Not all possible CIO and SIO functions are handled by the runtime stub code which banks
+the ROM in and out.  All functions used by the runtime library are handled, though.
+<item>The <tt/_sys()/ function is not supported.
+<item>It is not compatible with DOSes or other programs using the memory below the ROM.
+</itemize>
+
+<sect>DIO implementation<label id="dio"><p>
+
+The Atari supports disk drives with either 128 or 256 byte sectors.
+The first three sectors of any disk are always 128 bytes long though. This is
+because the system can only boot from 128 bytes sectors.
+
+Therefore the DIO read and write functions transfer only 128 bytes
+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>Technical details<label id="techdetail"><p>
+
+<sect1><tt/atari/<#if output="info|latex2e"> details</#if><p>
+
+<sect2><#if output="info|latex2e"><tt/atari/ </#if>Load chunks<p>
+
+An <tt/atari/ program contains two load chunks.
+
+<enum>
+<item>"system check"<label id="syschk">&nl;
+This load chunk is always loaded at address &dollar;2E00, and checks if the system has
+enough memory to run the program. It also checks if the program start address is not
+below MEMLO. If any of the checks return false, the loading of the program is aborted.&nl;
+The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file.
+<item>main program&nl;
+This load chunk is loaded at the selected program start address (default &dollar;2000) and
+contains all of the code and data of the program.&nl;
+The contents of this chunk come from the MAIN memory area of the linker config file.
+</enum>
 
 
+<sect1><tt/atarixl/<#if output="info|latex2e"> details</#if><p>
+
+<sect2>General operation<p>
+
+The <tt/atarixl/ target banks out the ROM while the program is running in
+order to make more memory available to the program.
+
+The screen memory is by default located at the top of available memory,
+&dollar;BFFF if BASIC is not enabled, &dollar;9FFF if BASIC is enabled.
+Therefore, in order to create a largest possible continuous memory area,
+the screen memory is moved below the program load address.  This gives
+a memory area from &lt;program load addr&gt; to &dollar;CFFF.
+
+The startup code installs wrappers for interrupt handlers and ROM routines.
+When an interrupt or call to a ROM routine happens, the wrappers enable the
+ROM, call the handler or routine, and disable the ROM again.
+
+The "wrapping" of the ROM routines is done by changing the ROM entry
+point symbols in <tt/atari.inc/ to point to the wrapper functions.
+
+For ROM functions which require input or output buffers, the wrappers
+copy the data as required to buffers in low memory.
+
+<sect2><#if output="info|latex2e"><tt/atarixl/ </#if>Load chunks<label id="xlchunks"><p>
+
+An <tt/atarixl/ program contains three load chunks.
+
+<enum>
+<item>"system check"<label id="syschkxl">&nl;
+This load chunk is always loaded at address &dollar;2E00, and checks if the system is
+suitable for running the program. It also checks if there is enough room between MEMLO
+and the program start address to move the text mode screen buffer there. If any of the
+checks return false, the loading of the program is aborted.&nl;
+The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file.
+<item>"shadow RAM prepare"&nl;
+The second load chunk gets loaded to the selected program load address (default &dollar;2400).
+It moves the screen memory below the program load address, copies the character generator
+from ROM to its new place in RAM, and copies the parts of the program which reside in
+high memory below the ROM to their place. The high memory parts are included in this load chunk.&nl;
+At the beginning of this load chunk there is a .bss area, which is not part of the
+EXE file. Therefore the on-disk start address of this load chunk will be higher than the
+selected start address. This .bss area (segment LOWBSS) contains the buffers for the
+double buffering of ROM input and output data.  If you add contents to this segment be aware
+that the contents won't be zero initialized by the startup code.&nl;
+The contents of this chunk come from the SRPREPCHNK memory area of the linker config file.
+<item>main program&nl;
+This load chunk is loaded just above the LOWBSS segment, replacing the code of
+the previous load chunk. It contains all remaining code and data sections of the program,
+including the startup code.&nl;
+The contents of this chunk come from the RAM memory area of the linker config file.
+</enum>
+
+<sect2>Moving screen memory below the program start address<p>
+
+When setting a graphics mode, the ROM looks at the RAMTOP location. RAMTOP
+describes the amount of installed memory in pages (RAMTOP is only one byte).
+The screen memory and display list are placed immediately below RAMTOP.
+
+Now in order to relocate the screen memory to lower memory, the startup code
+puts a value into RAMTOP which causes the ROM routines to allocate the display
+memory below the program start address and then it issues a ROM call to setup
+the regular text mode.
+
+<sect2>Selecting a good program load address<label id="loadaddr"><p>
+
+Due to the movement of the screen memory below the program start, there are some
+load addresses which are sub-optimal because they waste memory or prevent a
+higher resolution graphics mode from being enabled.
+
+There are restrictions at which addresses screen memory (display buffer and display
+list) can be placed. The display buffer cannot cross a 4K boundary and a display
+list cannot cross a 1K boundary.
+
+The startup code takes this into account when moving the screen memory down.
+If the program start address (aligned to the next lower page boundary) minus
+the screen buffer size would result in a screen buffer which spans a 4K
+boundary, the startup code lowers RAMTOP to this 4K boundary.&nl;
+The size of the screen buffer in text mode is 960 (&dollar;3C0) bytes. So, for
+example, a selected start address of &dollar;2300 would span the 4K boundary
+at &dollar;2000. The startup code would adjust the RAMTOP value in such way that
+the screen memory would be located just below this boundary (at &dollar;1C40).
+This results in the area &lsqb;&dollar;2000-&dollar;22FF&rsqb; being wasted.
+Additionally, the program might fail to load since the lowest address used
+by the screen memory could be below MEMLO. (The lowest address used in this
+example would be at &dollar;1C20, where the display list would allocated.)
+
+These calculations are performed by the startup code (in the first two
+load chunks), but the startup code only takes the default 40x24 text mode
+into account. If the program later wants to load TGI drivers which set
+a more memory consuming graphics mode, the user has to pick a higher
+load address.
+Using higher resolution modes there is a restriction in the ROM that it
+doesn't expect RAMTOP to be at arbitrary values. The Atari memory modules
+came only in 8K or 16K sizes, so the ROM expects RAMTOP to only have
+values in 8K steps. Therefore, when using the highest resolution modes
+the program start address must be at an 8K boundary.
+
+
+<sect2>Character generator location<label id="chargenloc"><p>
+
+The default <tt/atarixl/ linker config file (<tt/atarixl.cfg/) leaves the
+character generator location at the same address where it is in ROM
+(&dollar;E000). This has the disadvatage to split the upper memory into
+two parts (&lsqb;&dollar;D800-&dollar;DFFF&rsqb; and
+&lsqb;&dollar;E400-&dollar;FFF9&rsqb;). For applications which
+require a large continuous upper memory area, an alternative linker
+config file (<tt/atarixl-largehimem.cfg/) is provided. It relocates the
+character generator to &dollar;D800, providing a single big upper
+memory area at &lsqb;&dollar;DC00-&dollar;FFF9&rsqb;.
+
+With the character generator at a different address than in ROM, the routines
+which enable and disable the ROM also have to update the chargen pointer.
+This code is not enabled by default. In order to enable it,
+uncomment the line which sets CHARGEN_RELOC in <tt/libsrc&sol;atari&sol;Makefile.inc/
+and recompile the <tt/atarixl/ runtime library.
+
 <sect>Other hints<p>
 
 
+<sect1>Function keys<p>
+
+Function keys are mapped to Atari + number key.
+
+
+<sect1>Passing arguments to the program<p>
+
+Command line arguments can be passed to <tt/main()/ when the used DOS supports it.
+
+<enum>
+<item>Arguments are separated by spaces.
+<item>Leading and trailing spaces around an argument are ignored.
+<item>The first argument passed to <tt/main/ is the program name.
+<item>A maximum number of 16 arguments (including the program name) are
+      supported.
+</enum>
+
+
+<sect1>Interrupts<p>
+
+The runtime for the Atari uses routines marked as <tt/.INTERRUPTOR/ for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the VBI handler code
+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>
+
+(This section is primarily applicable to the <tt/atari/ target, but the
+principles apply to <tt/atatixl/ as well.)
+
+The Atari 130XE maps its additional memory into CPU memory in 16K
+chunks at address &dollar;4000 to &dollar;7FFF. One might want to
+prevent this memory area from being used by cc65. Other reasons to
+prevent the use of some memory area could be to reserve space for the
+buffers for display lists and screen memory.
+<p>
+The Atari executable format allows holes inside a program, e.g. one
+part loads into &dollar;2E00 to &dollar;3FFF, going below the reserved
+memory area (assuming a reserved area from &dollar;4000 to
+&dollar;7FFF), and another part loads into &dollar;8000 to
+&dollar;BC1F.
+<p>
+Each load chunk of the executable starts with a 4 byte header which
+defines its load address and size. In the following linker config files
+these headers are named HEADER and SECHDR (for the MEMORY layout), and
+accordingly NEXEHDR and CHKHDR (for the SEGMENTS layout).
+<p>
+<sect2>Low code and high data example<p>
+Goal: Create an executable with 2 load chunks which doesn't use the
+memory area from &dollar;4000 to &dollar;7FFF. The CODE segment of
+the program should go below &dollar;4000 and the DATA and RODATA
+segments should go above &dollar;7FFF.
+<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, ONCE, CODE, RODATA, and DATA segments, in
+fact, the whole user program (we're disregarding the "system check"
+load chunk here).
+<p>
+The contents of the EXE header come from the EXEHDR and MAINHDR segments.
+The EXEHDR segment just contains the &dollar;FFFF value which is required
+to be the first bytes of the EXE file.&nl;
+The MAINHDR are defined in in crt0.s. This cannot be changed without
+modifying and recompiling the cc65 atari runtime library. Therefore
+the original contents of this segment must be discarded and be
+replaced by a user created one. This discarding is done by assigning the
+MAINHDR segment to the (new introduced) DISCARD memory area. The DISCARD memory area is
+thrown away in the new linker config file (written to file "").
+We add a new FSTHDR segment for the chunk header of the first chunk.
+<p>
+The user needs to create a customized linker config file which adds
+new memory areas and segments to hold the new header data for the first load
+chunk and the header data for the second load chunk. Also an assembly source file
+needs to be created which defines the contents of the new header data
+for the two load chunks.
+<p>
+<p>
+This is an example of a modified cc65 Atari linker configuration file
+(split.cfg):
+<tscreen><verb>
+SYMBOLS {
+    __STACKSIZE__:       value = $800   type = weak;    # 2K stack
+    __RESERVED_MEMORY__: value = $0000, type = weak;
+}
+FEATURES {
+    STARTADDRESS: default = $2E00;
+}
+MEMORY {
+    ZP: start = $82, size = $7E, type = rw, define = yes;
+
+    HEADER: start = $0000, size = $2, file = %O;        # first load chunk
+
+    FSTHDR: start = $0000, size = $4, file = %O;        # second load chunk
+    RAMLO: start = %S, size = $4000 - %S, file = %O;
+
+    DISCARD: start = $4000, size = $4000, file = "";
+
+    SECHDR: start = $0000, size = $4, file = %O;        # second load chunk
+    RAM: start = $8000, size = $3C20, file = %O;        # $3C20: matches upper bound $BC1F
+}
+SEGMENTS {
+    EXEHDR: load = HEADER, type = ro;
+
+    MAINHDR: load = DISCARD, type = ro;
+
+    NEXEHDR: load = FSTHDR, type = ro;                  # first load chunk
+    STARTUP: load = RAMLO, type = ro, define = yes;
+    LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes;
+    ONCE: load = RAMLO, type = ro, optional = yes;
+    CODE: load = RAMLO, type = ro, 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 = ro;                    # defines program entry point
+}
+FEATURES {
+    CONDES: segment = ONCE,
+            type = constructor,
+            label = __CONSTRUCTOR_TABLE__,
+            count = __CONSTRUCTOR_COUNT__;
+    CONDES: segment = RODATA,
+            type = destructor,
+            label = __DESTRUCTOR_TABLE__,
+            count = __DESTRUCTOR_COUNT__;
+}
+</verb></tscreen>
+<p>
+
+A new memory area DISCARD was added.
+It gets loaded with the contents of the (now unused) MAINHDR segment. But the
+memory area isn't written to the output file. This way the contents of
+the MAINHDR segment get discarded.
+<p>
+The newly added NEXEHDR segment defines the correct chunk header for the
+first intended load chunk. It
+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
+segment. It puts the RODATA, DATA, BSS, and ZPSAVE segments into load
+chunk #2 (RAM memory area).
+<p>
+<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__, __STARTUP_LOAD__
+
+    .segment "NEXEHDR"
+    .word    __STARTUP_LOAD__
+    .word    __CODE_LOAD__ + __CODE_SIZE__ - 1
+
+    .segment "CHKHDR"
+    .word    __RODATA_LOAD__
+    .word    __BSS_LOAD__ - 1
+</verb></tscreen>
+<p>
+Compile with
+<tscreen><verb>
+cl65 -t atari -C split.cfg -o prog.com prog.c split.s
+</verb></tscreen>
+
+<sect2>Low data and high code example<p>
+
+
+Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, ONCE,
+CODE, BSS, ZPSAVE into high memory (split2.cfg):
+
+<tscreen><verb>
+SYMBOLS {
+    __STACKSIZE__:       value = $800   type = weak;    # 2K stack
+    __RESERVED_MEMORY__: value = $0000, type = weak;
+}
+FEATURES {
+    STARTADDRESS: default = $2E00;
+}
+MEMORY {
+    ZP: start = $82, size = $7E, type = rw, define = yes;
+
+    HEADER: start = $0000, size = $2, file = %O;        # first load chunk
+
+    FSTHDR: start = $0000, size = $4, file = %O;        # second load chunk
+    RAMLO: start = %S, size = $4000 - %S, file = %O;
+
+    DISCARD: start = $4000, size = $4000, file = "";
+
+    SECHDR: start = $0000, size = $4, file = %O;        # second load chunk
+    RAM: start = $8000, size = $3C20, file = %O;        # $3C20: matches upper bound $BC1F
+}
+SEGMENTS {
+    EXEHDR: load = HEADER, type = ro;                     # discarded old EXE header
+
+    MAINHDR: load = DISCARD, type = ro;
+
+    NEXEHDR: load = FSTHDR, type = ro;                  # first load chunk
+    RODATA: load = RAMLO, type = ro, define = yes;
+    DATA: load = RAMLO, type = rw, define = yes;
+
+    CHKHDR: load = SECHDR, type = ro;                   # second load chunk
+    STARTUP: load = RAM, type = ro, define = yes;
+    ONCE: 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 = ro;                    # defines program entry point
+}
+FEATURES {
+    CONDES: segment = ONCE,
+            type = constructor,
+            label = __CONSTRUCTOR_TABLE__,
+            count = __CONSTRUCTOR_COUNT__;
+    CONDES: segment = RODATA,
+            type = destructor,
+            label = __DESTRUCTOR_TABLE__,
+            count = __DESTRUCTOR_COUNT__;
+}
+</verb></tscreen>
+
+New contents for NEXEHDR and CHKHDR are needed (split2.s):
+<tscreen><verb>
+    .import __STARTUP_LOAD__, __BSS_LOAD__, __DATA_SIZE__
+    .import __DATA_LOAD__, __RODATA_LOAD__
+
+    .segment "NEXEHDR"
+    .word    __RODATA_LOAD__
+    .word    __DATA_LOAD__ + __DATA_SIZE__ - 1
+
+    .segment "CHKHDR"
+    .word    __STARTUP_LOAD__
+    .word    __BSS_LOAD__ - 1
+</verb></tscreen>
+
+Compile with
+<tscreen><verb>
+cl65 -t atari -C split2.cfg -o prog.com prog.c split2.s
+</verb></tscreen>
+
+<sect2>Final note<label id="memhole_final_note"><p>
+
+There are two other memory areas which don't appear directly in the
+linker config file. They are the stack and the heap.
+
+The cc65 runtime lib places the stack location at the end of available
+memory. This is dynamically set from the MEMTOP system variable at
+startup. The heap is located in the area between the end of the BSS
+segment and the top of the stack as defined by __STACKSIZE__.
+
+If BSS and/or the stack shouldn't stay at the end of the program,
+some parts of the cc65 runtime lib need to be replaced/modified.
+
+common/_heap.s defines the location of the heap and atari/crt0.s
+defines the location of the stack by initializing sp.
+
+
+<sect1>Upgrading from an older cc65 version<p>
+
+If you are using a customized linker config file you might get some errors
+regarding the MAINHDR segment. Like this:
+
+<tscreen><verb>
+ld65: Error: Missing memory area assignment for segment 'MAINHDR'
+</verb></tscreen>
+
+The old "HEADER" memory description contained six bytes: &dollar;FFFF
+and the first and last memory addess of the program. For the "system
+check" load chunk this had to be split into two memory assigments. The
+"HEADER" now only contains the &dollar;FFFF. The main program's first
+and last memory address were moved to a new segment, called "MAINHDR",
+which in the new linker config file goes into its own memory area (also
+called "MAINHDR").&nl;&nl;
+A simple way to adapt your old linker config file is to add the
+following line to the "SEGMENTS" section:
+
+<tscreen><verb>
+MAINHDR: load = HEADER, type = ro;
+</verb></tscreen>
+
+
+
+<sect1>Getting rid of the "system check" load chunk<label id="nosyschk"><p>
+
+If, for some reason, you don't want to include the "system check" load
+chunk, you can do so by defining the symbol <tt/__SYSTEM_CHECK__/ when linking the
+program. The "system check" chunk doesn't include vital parts of the
+program. So if you don't want the system checks, it is save to leave them out.
+This is probably mostly interesting for debugging.
 
-<sect>Bugs/Feedback<p>
+When using cl65, you can leave it out with this command line:
 
-If you have problems using the library, if you find any bugs, or if you're
-doing something interesting with it, I would be glad to hear from you. Feel
-free to contact me by email (<htmlurl url="mailto:uz@cc65.org"
-name="uz@cc65.org">).
+<tscreen><verb>
+cl65 -Wl -D__SYSTEM_CHECK__=1 <arguments>
+</verb></tscreen>
 
+The value you assign to <tt/__SYSTEM_CHECK_/ doesn't matter. If the
+<tt/__SYSTEM_CHECK__/ symbol is defined, the load chunk won't be included.
 
 
 <sect>License<p>
@@ -201,14 +1142,14 @@ including commercial applications, and to alter it and redistribute it
 freely, subject to the following restrictions:
 
 <enum>
-<item> The origin of this software must not be misrepresented; you must not
-       claim that you wrote the original software. If you use this software
-       in a product, an acknowledgment in the product documentation would be
-       appreciated but is not required.
-<item> Altered source versions must be plainly marked as such, and must not
-       be misrepresented as being the original software.
-<item> This notice may not be removed or altered from any source
-       distribution.
+<item>  The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+<item>  Altered source versions must be plainly marked as such, and must not
+    be misrepresented as being the original software.
+<item>  This notice may not be removed or altered from any source
+    distribution.
 </enum>
 
 </article>