File: atari.sgml

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (1197 lines) | stat: -rw-r--r-- 47,616 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
<!doctype linuxdoc system>

<article>
<title>Atari specific information for cc65
<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
compiler.
</abstract>

<!-- Table of contents -->
<toc>

<!-- Begin the document -->

<sect>Overview<p>

This file contains an overview of the Atari runtime system as it comes
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 <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.


<sect>Binary format<p>

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;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>

<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. 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:

<descrip>
  <tag/Text screen/
  The text screen depends on the installed memory size and cartridges
  and can be obtained from the SAVMSC variable (&dollar;58).

  <tag/Stack/
  The C runtime stack is located at MEMTOP and grows downwards,
  regardless of how your linker config file is setup.  This
  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"
  id="memhole_final_note">).

  <tag/Heap/
  The C heap is located at the end of the program and grows towards the C
  runtime stack.

</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-asm-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, and you can specify and
init address INITAD) for each memory area.

<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.

<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>

<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">.

<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>

Programs containing Atari specific code may use the <tt/atari.h/
header file.

This also includes access to operating system locations (e.g. hardware shadow registers) by a structure called
"<tt/OS/".
The names are the usual ones you can find in system reference manuals. Example:

<tscreen><verb>
...
    OS.savmsc = ScreenMemory;
    OS.color4 = 14;                         // white frame
    if (OS.stick0 != 15 || OS.ch != 255)    // key or stick input?
...
</verb></tscreen>

Please note that memory location 762/$2FA is called "<tt/char_/" while the orignal name "<tt/char/" conflicts with the C keyword.

If you like to use the OS names and locations for the original Atari 800 operating system, please "<tt/#define OSA/" before including the
<tt/atari.h/ header file.
If you like to target the floating point register model of revision 2 machines, put a "<tt/#define OS_REV2/" before including <tt/atari.h/.

Access to the Basic programming language zero page variables is established by the structure "<tt/BASIC/".

<sect1>Atari specific functions<p>

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>get_ostype
<item>get_tv
<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>


<sect1>Hardware access<p>

The following pseudo variables declared in the <tt/atari.h/ header
file do allow access to hardware located in the address space. Some
variables are structures, accessing the struct fields will access the
chip registers.

<descrip>

  <tag><tt/GTIA_READ/ and <tt/GTIA_WRITE/</tag>
  The <tt/GTIA_READ/ structure allows read access to the GTIA. The
  <tt/GTIA_WRITE/ structure allows write access to the GTIA.
  See the <tt/_gtia.h/ header file located in the include directory
  for the declaration of the structure.

  <tag><tt/POKEY_READ/ and <tt/POKEY_WRITE/</tag>
  The <tt/POKEY_READ/ structure allows read access to the POKEY. The
  <tt/POKEY_WRITE/ structure allows write access to the POKEY.
  See the <tt/_pokey.h/ header file located in the include directory
  for the declaration of the structure.

  <tag><tt/ANTIC/</tag>
  The <tt/ANTIC/ structure allows read access to the ANTIC.
  See the <tt/_antic.h/ header file located in the include directory
  for the declaration of the structure.

  <tag><tt/PIA/</tag>
  The <tt/PIA/ structure allows read access to the PIA 6520.
  See the <tt/_pia.h/ header file located in the include directory
  for the declaration of the structure.

</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:

<tscreen><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,
    &amp;DisplayList
};
...
OS.sdlst = &amp;DisplayList;
...
</verb></tscreen>

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:

<tscreen><verb>
#include &lt;atari_screen_charmap.h&gt;
char pcScreenMappingString[] = "Hello Atari!";

#include &lt;atari_atascii_charmap.h&gt;
char pcAtasciiMappingString[] = "Hello Atari!";
</verb></tscreen>

delivers correct results, while

<tscreen><verb>
#include &lt;atari_screen_charmap.h&gt;
char* pcScreenMappingString = "Hello Atari!";

#include &lt;atari_atascii_charmap.h&gt;
char* pcAtasciiMappingString = "Hello Atari!";
</verb></tscreen>

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:
<tscreen><verb>
...
    while (!kbhit());
    switch (OS.ch)
    {
        case KEY_RETURN:
        ...
        case KEY_SPACE:
        ...
        case KEY_1:
        ...
    }
...
</verb></tscreen>

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>

<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 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>

Currently there are two joystick drivers available:

<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>

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>RS232 device drivers<p>

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>


<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.

When using cl65, you can leave it out with this command line:

<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>

This software is provided 'as-is', without any expressed or implied
warranty.  In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
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.
</enum>

</article>