]> git.sur5r.net Git - cc65/blobdiff - doc/atari.sgml
Ignore start address in cbm_opendir. Rearrange the code somewhat to make it
[cc65] / doc / atari.sgml
index 324c80e22caa9f56bcc4bf74449b827668f967e1..0424dde627d3a6137961262609bf83a12ac0b12e 100644 (file)
@@ -3,9 +3,11 @@
 <article>
 
 <title>Atari specific information for cc65
-<author>Shawn Jefferson, <htmlurl url="mailto:shawnjefferson@24fightingchickens.com" name="shawnjefferson@24fightingchickens.com">
+<author>Shawn Jefferson, <htmlurl
+url="mailto:shawnjefferson@24fightingchickens.com"
+name="shawnjefferson@24fightingchickens.com"> and
 Christian Groessler, <htmlurl url="mailto:cpg@aladdin.de" name="cpg@aladdin.de">
-<date>16-Oct-2003
+<date>03-Jan-2006
 
 <abstract>
 An overview over the Atari runtime system as it is implemented for the cc65 C
@@ -35,13 +37,15 @@ information.
 
 The standard 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;2 byte start address&gt; &lt;2 bytes end address&gt;
+&lsqb;program bytes&rsqb;). 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 (see section <ref name="Reserving a memory area inside the program" id="memhole">).  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.
 
 
 <sect>Memory layout<p>
@@ -68,10 +72,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
@@ -93,17 +98,17 @@ The functions listed below are special for the Atari. See the <htmlurl
 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>_gtia_mkcolor
+<item>_getcolor
+<item>_getdefdev
+<item>_graphics
+<item>_rest_vecs
+<item>_save_vecs
+<item>_scroll
+<item>_setcolor
+<item>_setcolor_low
 </itemize>
 
 
@@ -147,6 +152,69 @@ chip registers.
 <sect1>Graphics drivers<p>
 
 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
+switch to the requested graphics mode.
+There are currently no functions available to access the graphics
+memory. The access must be implemented manually.
+
+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.
+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.
+
+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|160@
+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.
 
 <sect1>Extended memory drivers<p>
 
@@ -157,10 +225,13 @@ platform.
 
 <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.
 
+  <tag><tt/atarim8.joy/</tag>
+  Supports up to eight standard joysticks connected to a MultiJoy adapter.
+
 </descrip><p>
 
 
@@ -177,8 +248,241 @@ Currently there are no RS232 loadable drivers available for the Atari
 platform. There is a static driver you can use.
 
 
+<sect>Limitations<p>
+
+
+<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>Other hints<p>
 
+<sect1>Function keys<p>
+
+These are defined to be Atari + number key.
+
+<sect1>Reserving a memory area inside a program<label id="memhole"><p>
+
+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 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.
+<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 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 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.
+<p>
+The user needs to create a customized linker config file which adds
+new memory areas and segments to hold the new EXE header 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 EXE header
+and the second load chunk header.
+<p>
+<p>
+This is a modified cc65 Atari linker configuration file (split.cfg):
+<tscreen><verb>
+MEMORY {
+    ZP: start = $82, size = $7E, type = rw, define = yes;
+
+    HEADER: start = $0000, size = $6, file = %O;        # first load chunk
+    RAMLO: start = $2E00, size = $1200, file = %O;
+
+    BANK: 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
+    TRAILER: start = $0000, size = $0006, file = %O;
+}
+SEGMENTS {
+    EXEHDR: load = BANK, type = ro;
+
+    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 = 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 = TRAILER, type = ro;                # defines program entry point
+}
+FEATURES {
+    CONDES: segment = RODATA,
+            type = constructor,
+            label = __CONSTRUCTOR_TABLE__,
+            count = __CONSTRUCTOR_COUNT__;
+    CONDES: segment = RODATA,
+            type = destructor,
+            label = __DESTRUCTOR_TABLE__,
+            count = __DESTRUCTOR_COUNT__;
+}
+SYMBOLS {
+    __STACKSIZE__ = $800;       # 2K stack
+    __RESERVED_MEMORY__: value = $0, weak = yes;
+}
+</verb></tscreen>
+<p>
+
+A new memory area BANK was added which describes the reserved area.
+It gets loaded with the contents of the old EXEHDR segment. But the
+memory area isn't written to the output file. This way the contents of
+the EXEHDR segment get discarded.
+<p>
+The added NEXEHDR segment defines the correct EXE header. It puts only
+the CODE segment 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 and DATA 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 __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    __LOWCODE_LOAD__
+        .word    __CODE_LOAD__ + __CODE_SIZE__ - 1
+
+        .segment "CHKHDR"
+        ; 2nd load chunk (contains with AUTOSTRT in fact a 3rd load chunk)
+        .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 LOWCODE, INIT, CODE, BSS
+into high memory (split2.cfg):
+
+<tscreen><verb>
+MEMORY {
+    ZP: start = $82, size = $7E, type = rw, define = yes;
+
+    HEADER: start = $0000, size = $6, file = %O;        # first load chunk
+    RAMLO: start = $2E00, size = $1200, file = %O;
+
+    BANK: 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
+    TRAILER: start = $0000, size = $0006, file = %O;
+}
+SEGMENTS {
+    EXEHDR: load = BANK, type = ro;                     # discarded old EXE header
+
+    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 = 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 = TRAILER, type = ro;                # defines program entry point
+}
+FEATURES {
+    CONDES: segment = RODATA,
+            type = constructor,
+            label = __CONSTRUCTOR_TABLE__,
+            count = __CONSTRUCTOR_COUNT__;
+    CONDES: segment = RODATA,
+            type = destructor,
+            label = __DESTRUCTOR_TABLE__,
+            count = __DESTRUCTOR_COUNT__;
+}
+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 __LOWCODE_LOAD__, __BSS_LOAD__, __DATA_SIZE__
+        .import __DATA_LOAD__, __RODATA_LOAD__
+
+        .segment "NEXEHDR"
+        .word    $FFFF
+        .word    __RODATA_LOAD__
+        .word    __DATA_LOAD__ + __DATA_SIZE__ - 1
+
+        .segment "CHKHDR"
+        .word    __LOWCODE_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 script. 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.
 
 
 <sect>Bugs/Feedback<p>
@@ -186,7 +490,8 @@ platform. There is a static driver you can use.
 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">).
+name="uz@cc65.org"> or <htmlurl url="mailto:cpg@aladdin.de"
+name="cpg@aladdin.de">).