From 223cc6685ebbebc4b2bf693d50b6e03c0331349e Mon Sep 17 00:00:00 2001
From: kueller This file contains an overview of the Apple ][ runtime system
+as it comes with the cc65 C compiler. It describes the memory layout,
+Apple ][ specific header files, available drivers, and any
+pitfalls specific to that platform. Please note that Apple ][ specific functions are just mentioned
+here, they are described in detail in the separate
+function reference. Even functions marked as "platform dependent" may
+be available on more than one platform. Please see the function reference for
+more information. The standard binary output format generated by the linker for the
+Apple ][ target is a machine language program with a 4 byte DOS
+3.3 header. The standard load address is $800. The DOS header is in its own segment named
+
+1. Overview
+
+
+
+Next
+Previous
+Contents
+
+
diff --git a/usr/share/doc/cc65/webdoc/apple2-2.html b/usr/share/doc/cc65/webdoc/apple2-2.html
new file mode 100644
index 0000000..1c9c1e9
--- /dev/null
+++ b/usr/share/doc/cc65/webdoc/apple2-2.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+2. Binary format
+
+
+EXEHDR
. If you don't want the
+header for some reason, you can change
+ HEADER: start = $0000, size = $4, file = %O;
+
+
to
++
+ HEADER: start = $0000, size = $4, file = ""; ++ +
in the linker configuration to have the linker remove it.
+Please note that there is a "Apple ][ ProDOS 8 system program +for loading binary programs" available in the cc65 User Contributions section. +It adds all benefits of a ProDOS 8 system program to the standard binary +program generated by the linker for the Apple ][ target.
+ + + +In the standard setup, cc65 generated programs use the memory from +$800 to $95FF, so 35.5K of memory are available. ROM calls are +possible without further precautions.
+Special locations:
++
The C runtime stack is located at HIMEM and grows downwards, regardless of +how your linker config file is setup.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+Programs containing Apple ][ specific code may use the
+apple2.h
header file.
The functions listed below are special for the Apple ][. See +the +function reference for declaration and +usage.
++
There's currently no support for direct hardware access. This does not mean +you cannot do it, it just means that there's no help.
+ + + +Note: Since the Apple ][ doesn't have working disk I/O +(see +section "Limitations"), the +available drivers cannot be loaded at runtime (so the term "loadable drivers" +is somewhat misleading). Instead, the drivers have to be converted using the +co65 utility and statically linked. While +this may seem overhead, it has two advantages:
++
Note: Since memory for the high resolution graphics has to be allocated,
+programs using graphics drivers will have to be linked using a special linker
+configuration. See the apple2-tgi.cfg
file in the documentation
+directory, and the
+linker documentation on
+how to use it.
+
a2.lo.tgi
This driver was written by Stefan Haubenthal. It features a resolution of +40×40 with 16 colors. At the bottom of the screen, 4 additional text lines +are available.
+ +a2.hi.tgi
This driver was written by Stefan Haubenthal. It features a resolution of +280×192 with 6 colors.
+ ++
a2.lc.emd
Gives access to 12KB RAM (48 pages of 256 bytes each) on the +Apple ][ language card. The driver was contributed by +Stefan Haubenthal. Note: This driver is incompatible with any DOS using +the language card memory!
+ ++
a2.stdjoy.joy
Supports up to two standard analog joysticks connected to the game port of +the Apple ][.
+ +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + +No serial drivers are currently available for the Apple ][.
+ + + +The existing library for the Apple ][ doesn't implement C file
+I/O. There are two hacks for the read()
and write()
routines in
+place, which will make functions work that read from or write to stdout
+(like printf()
). However, these functions have some shortcomings which
+won't be fixed, because they're going to be replaced anyway.
To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others):
++
Command line arguments can be passed to main()
after BLOAD. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+]CALL2048:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.These are defined to be OpenApple + number key.
+ + + +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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
ar65 is a replacement for the libr65 archiver that was part of the cc65 C +compiler suite developed by John R. Dunning. libr65 had some problems and +the copyright does not permit some things which I wanted to be possible, +so I decided to write a completely new assembler/linker/archiver suite +for the cc65 compiler. ar65 is part of this suite.
+ +The archiver is called as follows:
++
+
+ Usage: ar65 <operation> lib file|module ...
+ Operation is one of:
+ a Add modules
+ d Delete modules
+ l List library contents
+ x Extract modules
+ V Print the archiver version
+
+
+
+You may add modules to a library using the `a' command. If the library +does not exist, it is created (and a warning message is printed which you +may ignore if creation of the library was your intention). You may +specify any number of modules on the command line following the library.
+If a module with the same name exists in the library, it is replaced by +the new one. The archiver prints a warning, if the module in the library +has a newer timestamp than the one to add.
+Here's an example:
++
+
+ ar65 a mysubs.lib sub1.o sub2.o
+
+
+
+This will add two modules to the library `mysubs.lib' creating the +library if necessary. If the library contains modules named sub1.o or +sub2.o, they are replaced by the new ones.
+Modules names in the library are stored without the path, so, using
++
+
+ ar65 a mysubs.lib ofiles/sub1.o ofiles/sub2.o
+
+
+
+will add two modules named `sub1.o' and `sub2.o' to the library.
+Deleting modules from a library is done with the `d' command. You may not +give a path when naming the modules.
+Example:
++
+
+ ar65 d mysubs.lib sub1.o
+
+
+
+This will delete the module named `sub1.o' from the library, printing an +error if the library does not contain that module.
+ +The `l' command prints a list of all modules in the library. Any module +names on the command line are ignored.
+Example:
++
+
+ ar65 l mysubs.lib
+
+
+
+
+Using the `x' command, you may extract modules from the library. The +modules named on the command line are extracted from the library and put +into the current directory.
+Note: Because of the indexing done by the archiver, the modules may have +a changed binary layout, that is, a binary compare with the old module +(before importing it into the library) may yield differences. The +extracted modules are accepted by the linker and archiver, however, so +this is not a problem.
+Example for extracting a module from the library:
++
+
+ ar65 x mysubs.lib sub1.o
+
+
+
+
+The `V' command prints the version number of the assembler. If you send +any suggestions or bugfixes, please include your version number.
+In addition to these operations, the archiver will check for, and warn +about duplicate external symbols in the library, every time when an +operation does update the library. This is only a warning, the linker +will ignore one of the duplicate symbols (which one is unspecified).
+ + +If you have problems using the archiver, 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 ( +uz@cc65.org).
+ + + +ar65 (and all cc65 binutils) are (C) Copyright 1998-2000 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following conditions +do apply:
+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:
++
+
+
+
+
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.
+Please note that Atari specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +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:
++
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 <2 byte start address> <2 bytes end address> +[program bytes]). 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 +Reserving a memory area inside the program). 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 +($02E0 <run vector>) and is calculated using +__CODE_LOAD__ in crt0.s.
+ + +The default linker script assumes that the BASIC ROM is disabled (or +the BASIC cartridge unplugged). This gives a usable memory range from +$2E00 - $BC1F. 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 ($2E5) variable. Then the initial stack pointer, +which indicates the upper bound of memory used, is adjusted. The load +address of $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.
+Special locations:
++
The text screen depends on the installed memory size and cartridges +and can be obtained from the SAVMSC variable ($58).
+ +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 +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 +Final note).
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing Atari specific code may use the atari.h
+header file.
The functions listed below are special for the Atari. See the +function reference for declaration and usage.
++
The following pseudo variables declared in the 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.
+
GTIA_READ
and GTIA_WRITE
The GTIA_READ
structure allows read access to the GTIA. The
+GTIA_WRITE
structure allows write access to the GTIA.
+See the _gtia.h
header file located in the include directory
+for the declaration of the structure.
POKEY_READ
and POKEY_WRITE
The POKEY_READ
structure allows read access to the POKEY. The
+POKEY_WRITE
structure allows write access to the POKEY.
+See the _pokey.h
header file located in the include directory
+for the declaration of the structure.
ANTIC
The ANTIC
structure allows read access to the ANTIC.
+See the _antic.h
header file located in the include directory
+for the declaration of the structure.
PIA
The PIA
structure allows read access to the PIA 6520.
+See the _pia.h
header file located in the include directory
+for the declaration of the structure.
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.
+
+
+graphics mode | reserved memory |
+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 + |
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.
+ +Currently there are no extended memory drivers available for the Atari +platform.
+ ++
atari-stdjoy.joy
Supports up to four standard joysticks connected to the joystick ports of +the Atari.
+ +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 are no RS232 loadable drivers available for the Atari +platform. There is a static driver you can use.
+ + +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.
+ + +These are defined to be Atari + number key.
+ +The Atari 130XE maps its additional memory into CPU memory in 16K +chunks at address $4000 to $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.
+The Atari executable format allows holes inside a program, e.g. one +part loads into $2E00 to $3FFF, going below the reserved +memory area (assuming a reserved area from $4000 to +$7FFF), and another part loads into $8000 to +$BC1F.
+Each load chunk of the executable starts with a 4 byte header which +defines its load address and size.
+ +Goal: Create an executable with 2 load chunks which doesn't use the +memory area from $4000 to $7FFF. The CODE segment of +the program should go below $4000 and the DATA and RODATA +segments should go above $7FFF.
+The main problem is that the EXE header generated by the cc65 runtine +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).
+The contents of the EXE header come from the EXEHDR segment, which is +defined in crt0.s. This cannot be changed w/o modifiying and +recompiling the cc65 atari runtime lib. Therefore the original EXE +header must be discarded. It will be replaced by a user created +one.
+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.
+ +This is a modified cc65 Atari linker configuration file (split.cfg): +
+
+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;
+}
+
+
+
+
+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.
+The added NEXEHDR segment defines the correct EXE header. It puts only +the CODE segment into load chunk #1 (RAMLO memory area).
+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).
+ +The contents of the new NEXEHDR and CHKHDR segments come from this +file (split.s): +
+
+ .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
+
+
+
+Compile with +
+
+cl65 -t atari -C split.cfg -o prog.com prog.c split.s
+
+
+
+
+Goal: Put RODATA and DATA into low memory and LOWCODE, INIT, CODE, BSS +into high memory (split2.cfg):
++
+
+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;
+}
+
+
+
+New contents for NEXEHDR and CHKHDR are needed (split2.s): +
+
+ .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
+
+
+
+Compile with +
+
+cl65 -t atari -C split2.cfg -o prog.com prog.c split2.s
+
+
+
+
+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.
+ + +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 ( +uz@cc65.org or +cpg@aladdin.de).
+ + + ++
+
+
+
+
+
+
+
+
+
This file contains an overview of the Atmos runtime system as it comes with the +cc65 C compiler. It describes the memory layout, Atmos specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that Atmos specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the Atmos target +is a machine language program with a 14 byte tape header. The standard load +and autostart address is $500.
+ + +In the standard setup, cc65 generated programs use the memory from +$500 to $9800, so nearly 37K of memory (including the stack) is +available. ROM calls are possible without further precautions.
+Special locations:
++
The C runtime stack is located at $97FF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing Atmos specific code may use the atmos.h
header file.
The following pseudo variables declared in the atmos.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.
+
VIA
Access to the VIA (versatile interface adapter) chip is available via the
+VIA
variable. The structure behind this variable is explained in _6522.h
.
Note: Since the Atmos doesn't have working disk I/O +(see +section "Limitations"), the +available drivers cannot be loaded at runtime (so the term "loadable drivers" +is somewhat misleading). Instead, the drivers have to be converted using the +co65 utility and statically linked. While +this may seem overhead, it has two advantages:
++
+
atmos-240-200-2.tgi
This driver was written by Stefan Haubenthal. It features a resolution of +240×200 with 2 colors.
+ +No extended memory drivers are currently available for the Atmos.
+ + + + + +No mouse drivers are currently available for the Atmos.
+ + +No serial drivers are currently available for the Atmos.
+ + + +The existing library for the Atmos doesn't implement C file
+I/O. There is one hack for the write()
routine in
+place, which will make functions work that write to stdout
+(like printf()
). However, this function has some shortcomings which
+won't be fixed, because it's going to be replaced anyway.
To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others):
++
The runtime for the Atmos uses routines marked as .CONDES
type 2 for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the interrupt handler code
+when they are linked into a program. See the discussion of the .CONDES
+feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the C128 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C128 specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that C128 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the C128 target +is a machine language program with a one line BASIC stub. This means that a +program can be loaded as BASIC program and started with RUN. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ + +cc65 generated programs with the default setup run with the I/O area and the +kernal ROM enabled. Note that this is a non standard memory layout, and that +there is no "memory configuration index" for this layout. This means that +special case has to be taken when changing the configuration, or calling any +code that does this. The memory configuration register at $FF00 should +be saved and restored instead of relying on the memory configuration index +stored in the zero page.
+The setup gives a usable memory range of $1C00 - $CFFF. Having +just the kernal ROM mapped in means, that kernal entry points may be called +directly, but using the BASIC ROM is not possible without additional code.
+Special locations:
++
The text screen is located at $400 (as in the standard setup).
+ +The C runtime stack is located at $CFFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing C128 specific code may use the c128.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes c128.h
and declares several functions
+common to all CBM platforms.
The functions listed below are special for the C128. See the +function reference for declaration and usage.
++
Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the c128.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.
+
VIC
The VIC
structure allows access to the VIC II (the graphics
+controller). See the _vic2.h
header file located in the include
+directory for the declaration of the structure.
SID
The SID
structure allows access to the SID (the sound interface
+device). See the _sid.h
header file located in the include directory
+for the declaration of the structure.
VDC
The VDC
structure allows access to the VDC (the video display
+controller). See the _vdc.h
header file located in the include
+directory for the declaration of the structure.
CIA1, CIA2
Access to the two CIA (complex interface adapter) chips is available via
+the CIA1
and CIA2
variables. The structure behind these variables
+is explained in _6526.h
.
COLOR_RAM
A character array that mirrors the color RAM of the C64 at $D800.
+ +Note: The graphics drivers for the VDC are incompatible with the extended +memory drivers using the VDC memory!
++
c128-vdc.tgi
This driver was written by Maciej Witkowiak. It uses the 80 column display +and features a resolution of 640*200 with two colors and an adjustable +palette (that means that the two colors can be chosen out of the 16 VDC +colors).
+ +c128-vdc2.tgi
This driver was written by Maciej Witkowiak. This driver uses the 80 column +display and features a resolution of 640*480 with two colors and an +adjustable palette (that means that the two colors can be chosen out of the +16 VDC colors). The driver requires 64KB VDC RAM.
+Note: The colors are translated from definitions in headers to correct VDC values
+so please use definitions or VIC color numbers only. Colors GRAY3
and BROWN
are
+missing on VDC and are translated to the two colors missing from VIC palette.
+
c128-georam.emd
A driver for the GeoRam cartridge. The driver will always assume 2048 pages +of 256 bytes each. There are no checks, so if your program knows better, +just go ahead.
+ +c128-ram.emd
An extended memory driver for the RAM in page 1. The common memory area is +excluded, so this driver supports 251 pages of 256 bytes each.
+ +c128-ramcart.emd
A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. +Will test the hardware for the available RAM.
+ +c128-reu.emd
A driver for the CBM REUs. The driver will determine from the connected REU +if it supports 128KB of RAM or more. In the latter case, 256KB are assumed, +but since there are no range checks, the application can use more memory if +it has better knowledge about the hardware than the driver.
+ +c128-vdc.emd
A driver for the VDC memory of the C128 written and contributed by Maciej +Witkowiak. Autodetects the amount of memory available (16 or 64K) and offers +64 or 256 pages of 256 bytes each. Note: This driver is incompatible with +any of the graphics drivers using the VDC!
+ ++
c128-ptvjoy.joy
Driver for the Protovision 4-player adapter originally written by Groepaz +for the C64 and converted for the C128 by me. See +http://www.protovision-online.de/hardw/hardwstart.htm for prices and +building instructions. Up to four joysticks are supported.
+ +c128-stdjoy.joy
Supports up to two joysticks connected to the standard joysticks port of +the C128.
+ +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + ++
c128-swlink.ser
Driver for the SwiftLink cartridge. Supports up to 38400 baud, hardware flow +control (RTS/CTS) and interrupt driven receives. Note that because of the +peculiarities of the 6551 chip together with the use of the NMI, transmits +are not interrupt driven, and the transceiver blocks if the receiver asserts +flow control because of a full buffer.
+The driver uses the RS232 variables and buffers of the kernal (buffers at +$C00 and $D00).
+ +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The runtime for the C128 uses routines marked as .CONDES
type 2 for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the interrupt handler code
+when they are linked into a program. See the discussion of the .CONDES
+feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the C16 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C16/116 specific header +files, available drivers, and any pitfalls specific to that platform.
+Please note that C16 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+Since the C16/C116 and the Commodore Plus/4 are almost identical (the former +don't have the 6551 ACIA and only 16KB of memory), the +Plus/4 documentation is also worth a look. The +difference between both cc65 targets is that the Plus/4 runtime uses banking +to support full 64K RAM, while the C16 does not use banking and supports up to +32K RAM. Because banking is not needed, most C16 programs will be somewhat +smaller than the same program compiled for the Plus/4. However, programs C16 +will always run on the Plus/4, while the reverse is not necessarily true.
+ + +The standard binary output format generated by the linker for the C16/C116 +target is a machine language program with a one line BASIC stub. This means +that a program can be loaded as BASIC program and started with RUN. It is of +course possible to change this behaviour by using a modified startup file and +linker config.
+ + +cc65 generated programs with the default setup run with the kernal and basic +banked out. This gives a usable memory range of $1000 - $4000 +(or $8000 i the machine is equipped with 32K RAM or more). Having the +kernal and basic ROMs banked out means, that no ROM entry points may be called +directly from user code.
+Special locations:
++
The text screen is located at $C00 (as in the standard setup).
+ +The color RAM is located at $800 (standard location).
+ +The C runtime stack is located at $3FFF ($7FFF in case of a +machine with 32K of memory or more) and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing C16 specific code may use the c16.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes c16.h
and declares several functions
+common to all CBM platforms.
Please note that most of the header file declarations from the c16.h
+header file are shared between the C16 and Plus/4 configurations. For this
+reason, most of it is located in a common header file named cbm264.h
.
There are currently no special C16/C116 functions.
+ + +Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the c16.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.
+
TED
The TED
structure allows access to the TED chip. See the
+_ted.h
header file located in the include directory for the
+declaration of the structure.
COLOR_RAM
A character array that mirrors the color RAM of the C16 at $0800.
+ +No graphics drivers are currently available for the C16/C116.
+ + ++
c16-ram.emd
A driver for the hidden RAM below the BASIC and KERNAL ROMs. Supports 125 +pages with 256 bytes each if the machine is equipped with 64K of memory +(a Plus/4 or a memory extended C16/116).
+ ++
c16-stdjoy.joy
Supports up to two joysticks connected to the standard joysticks port of +the Commodore 16/116.
+ +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + +The Commodore 16 does not have a builtin ACIA and no RS232 extensions are +known. For this reason, there are no RS232 drivers available. Please note that +the standard Plus/4 driver will not run together with the C16 +library, because the latter does not support interrupts needed by the driver.
+ + +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the C64 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, C64 specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that C64 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the C64 target +is a machine language program with a one line BASIC stub. This means that a +program can be loaded as BASIC program and started with RUN. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ + +cc65 generated programs with the default setup run with the I/O area and the +kernal ROM enabled (memory under the kernal may be used for graphics or as +extended memory - see the sections about graphics and extended memory +drivers). The BASIC ROM is disabled, which gives a usable memory range of +$0800 - $CFFF. This means that kernal entry points may be called +directly, but using the BASIC ROM is not possible without additional code.
+Special locations:
++
The text screen is located at $400 (as in the standard setup).
+ +The C runtime stack is located at $CFFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing C64 specific code may use the c64.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes c64.h
and declares several functions
+common to all CBM platforms.
The functions listed below are special for the C64. See the +function reference for declaration and usage.
++
Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the c64.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.
+
VIC
The VIC
structure allows access to the VIC II (the graphics
+controller). See the _vic2.h
header file located in the include
+directory for the declaration of the structure.
SID
The SID
structure allows access to the SID (the sound interface
+device). See the _sid.h
header file located in the include directory
+for the declaration of the structure.
CIA1, CIA2
Access to the two CIA (complex interface adapter) chips is available via
+the CIA1
and CIA2
variables. The structure behind these variables
+is explained in _6526.h
.
COLOR_RAM
A character array that mirrors the color RAM of the C64 at $D800.
+ +Note: All available graphics drivers for the TGI interface will use +the space below the I/O area and kernal ROM, so you can have hires graphics in +the standard setup without any memory loss or need for a changed +configuration.
++
c64-hi.tgi
This driver features a resolution of 320*200 with two colors and an +adjustable palette (that means that the two colors can be chosen out of a +palette of the 16 C64 colors).
++
c64-georam.emd
A driver for the GeoRam cartridge. The driver will always assume 2048 pages +of 256 bytes each. There are no checks, so if your program knows better, +just go ahead.
+ +c64-ram.emd
A driver for the hidden RAM below the I/O area and kernal ROM. Supports 48 +256 byte pages. Please note that this driver is incompatible with any of the +graphics drivers!
+ +c64-ramcart.emd
A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. +Will test the hardware for the available RAM.
+ +c64-reu.emd
A driver for the CBM REUs. The driver will determine from the connected REU +if it supports 128KB of RAM or more. In the latter case, 256KB are assumed, +but since there are no range checks, the application can use more memory if +it has better knowledge about the hardware than the driver.
+ +c64-vdc.emd
A driver for the VDC memory of the C128. Written and contributed by Maciej +WitkowiakCan be used if the program is running in C64 mode of the C128. +Autodetects the amount of memory available (16 or 64K) and offers 64 or 256 +pages of 256 bytes each.
+ ++
c64-hitjoy.joy
Driver for the Digital Excess & Hitmen adapter contributed by Groepaz. See +http://www.digitalexcess.de/downloads/productions.php on +instructions how to build one. Up to four joysticks are supported.
+ +c64-ptvjoy.joy
Driver for the Protovision 4-player adapter contributed by Groepaz. See +http://www.protovision-online.de/hardw/hardwstart.htm for prices and +building instructions. Up to four joysticks are supported.
+ +c64-stdjoy.joy
Supports up to two standard joysticks connected to the joysticks port of +the C64.
+ +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + ++
c64-swlink.ser
Driver for the SwiftLink cartridge. Supports up to 38400 baud, hardware flow +control (RTS/CTS) and interrupt driven receives. Note that because of the +peculiarities of the 6551 chip together with the use of the NMI, transmits +are not interrupt driven, and the transceiver blocks if the receiver asserts +flow control because of a full buffer.
+ +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The runtime for the C64 uses routines marked as .CONDES
type 2 for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the interrupt handler code
+when they are linked into a program. See the discussion of the .CONDES
+feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
ca65 is a replacement for the ra65 assembler that was part of the cc65 C +compiler, originally developed by John R. Dunning. I had some problems with +ra65 and the copyright does not permit some things which I wanted to be +possible, so I decided to write a completely new assembler/linker/archiver +suite for the cc65 compiler. ca65 is part of this suite.
+Some parts of the assembler (code generation and some routines for symbol +table handling) are taken from an older crossassembler named a816 written +by me a long time ago.
+ + +Here's a list of the design criteria, that I considered important for the +development:
++
+
+ .import S1, S2
+ .export Special
+ Special = 2*S1 + S2/7
+
+
+
+right.Here's a list of all control commands and a description, what they do:
+ + +.A16
+Valid only in 65816 mode. Switch the accumulator to 16 bit.
+Note: This command will not emit any code, it will tell the assembler to +create 16 bit operands for immediate accumulator addressing mode.
+See also:
+.SMART
.A8
+Valid only in 65816 mode. Switch the accumulator to 8 bit.
+Note: This command will not emit any code, it will tell the assembler to +create 8 bit operands for immediate accu addressing mode.
+See also:
+.SMART
.ADDR
+Define word sized data. In 6502 mode, this is an alias for .WORD
and
+may be used for better readability if the data words are address values. In
+65816 mode, the address is forced to be 16 bit wide to fit into the current
+segment. See also
+.FARADDR
. The command
+must be followed by a sequence of (not necessarily constant) expressions.
Example:
++
+
+ .addr $0D00, $AF13, _Clear
+
+
+
+
+
+
+
+.ALIGN
+Align data to a given boundary. The command expects a constant integer +argument that must be a power of two, plus an optional second argument +in byte range. If there is a second argument, it is used as fill value, +otherwise the value defined in the linker configuration file is used +(the default for this value is zero).
+Since alignment depends on the base address of the module, you must +give the same (or a greater) alignment for the segment when linking. +The linker will give you a warning, if you don't do that.
+Example:
++
+
+ .align 256
+
+
+
+
+
+
+.ASCIIZ
+Define a string with a trailing zero.
+Example:
++
+
+ Msg: .asciiz "Hello world"
+
+
+
+
+This will put the string "Hello world" followed by a binary zero into +the current segment. There may be more strings separated by commas, but +the binary zero is only appended once (after the last one).
+ + +.ASSERT
+Add an assertion. The command is followed by an expression, an action
+specifier, and an optional message that is output in case the assertion
+fails. If no message was given, the string "Assertion failed" is used. The
+action specifier may be one of warning
or error
. The assertion is
+evaluated by the assembler if possible, and also passed to the linker in the
+object file (if one is generated). The linker will then evaluate the
+expression when segment placement has been done.
Example:
++
+
+ .assert * = $8000, error, "Code not at $8000"
+
+
+
+
+The example assertion will check that the current location is at $8000,
+when the output file is written, and abort with an error if this is not
+the case. More complex expressions are possible. The action specifier
+warning
outputs a warning, while the error
specifier outputs
+an error message. In the latter case, generation if the output file is
+suppressed in both the assembler and linker.
.AUTOIMPORT
+Is followed by a plus or a minus character. When switched on (using a ++), undefined symbols are automatically marked as import instead of +giving errors. When switched off (which is the default so this does not +make much sense), this does not happen and an error message is +displayed. The state of the autoimport flag is evaluated when the +complete source was translated, before outputting actual code, so it is +not possible to switch this feature on or off for separate sections +of code. The last setting is used for all symbols.
+You should probably not use this switch because it delays error +messages about undefined symbols until the link stage. The cc65 +compiler (which is supposed to produce correct assembler code in all +circumstances, something which is not true for most assembler +programmers) will insert this command to avoid importing each and every +routine from the runtime library.
+Example:
++
+
+ .autoimport + ; Switch on auto import
+
+
+
+
+
+
+.BSS
+Switch to the BSS segment. The name of the BSS segment is always "BSS", +so this is a shortcut for
++
+
+ .segment "BSS"
+
+
+
+
+See also the
+.SEGMENT
command.
.BYT, .BYTE
+Define byte sized data. Must be followed by a sequence of (byte ranged) +expressions or strings.
+Example:
++
+
+ .byte "Hello "
+ .byt "world", $0D, $00
+
+
+
+
+
+
+.CASE
+Switch on or off case sensitivity on identifiers. The default is off +(that is, identifiers are case sensitive), but may be changed by the +-i switch on the command line. +The command must be followed by a '+' or '-' character to switch the +option on or off respectively.
+Example:
++
+
+ .case - ; Identifiers are not case sensitive
+
+
+
+
+
+
+.CHARMAP
+Apply a custom mapping for characters. The command is followed by two
+numbers in the range 1..255. The first one is the index of the source
+character, the second one is the mapping. The mapping applies to all
+character and string constants when they generate output, and overrides
+a mapping table specified with the
+-t
+command line switch.
Example:
++
+
+ .charmap $41, $61 ; Map 'A' to 'a'
+
+
+
+
+
+
+.CODE
+Switch to the CODE segment. The name of the CODE segment is always +"CODE", so this is a shortcut for
++
+
+ .segment "CODE"
+
+
+
+
+See also the
+.SEGMENT
command.
.CONDES
+Export a symbol and mark it in a special way. The linker is able to build +tables of all such symbols. This may be used to automatically create a list +of functions needed to initialize linked library modules.
+Note: The linker has a feature to build a table of marked routines, but it
+is your code that must call these routines, so just declaring a symbol with
+.CONDES
does nothing by itself.
All symbols are exported as an absolute (16 bit) symbol. You don't need to
+use an additional
+.EXPORT
statement, this
+is implied by .CONDES
.
.CONDES
is followed by the type, which may be constructor
,
+destructor
or a numeric value between 0 and 6 (where 0 is the same as
+specifying constructor
and 1 is equal to specifying destructor
).
+The
+.CONSTRUCTOR
,
+.DESTRUCTOR
and
+.INTERRUPTOR
commands are actually shortcuts for .CONDES
+with a type of constructor
resp. destructor
or interruptor
.
After the type, an optional priority may be specified. Higher numeric values +mean higher priority. If no priority is given, the default priority of 7 is +used. Be careful when assigning priorities to your own module constructors +so they won't interfere with the ones in the cc65 library.
+Example:
++
+
+ .condes ModuleInit, constructor
+ .condes ModInit, 0, 16
+
+
+
+
+See the
+.CONSTRUCTOR
,
+.DESTRUCTOR
and
+.INTERRUPTOR
commands and the separate section
+Module constructors/destructors explaining the feature in more
+detail.
.CONSTRUCTOR
+Export a symbol and mark it as a module constructor. This may be used +together with the linker to build a table of constructor subroutines that +are called by the startup code.
+Note: The linker has a feature to build a table of marked routines, but it +is your code that must call these routines, so just declaring a symbol as +constructor does nothing by itself.
+A constructor is always exported as an absolute (16 bit) symbol. You don't
+need to use an additional .export
statement, this is implied by
+.constructor
. It may have an optional priority that is separated by a
+comma. Higher numeric values mean a higher priority. If no priority is
+given, the default priority of 7 is used. Be careful when assigning
+priorities to your own module constructors so they won't interfere with the
+ones in the cc65 library.
Example:
++
+
+ .constructor ModuleInit
+ .constructor ModInit, 16
+
+
+
+
+See the
+.CONDES
and
+.DESTRUCTOR
commands and the separate section
+Module constructors/destructors explaining the
+feature in more detail.
.DATA
+Switch to the DATA segment. The name of the DATA segment is always +"DATA", so this is a shortcut for
++
+
+ .segment "DATA"
+
+
+
+
+See also the
+.SEGMENT
command.
.DBYT
+Define word sized data with the hi and lo bytes swapped (use .WORD
to
+create word sized data in native 65XX format). Must be followed by a
+sequence of (word ranged) expressions.
Example:
++
+
+ .dbyt $1234, $4512
+
+
+
+
+This will emit the bytes
++
+
+ $12 $34 $45 $12
+
+
+
+
+into the current segment in that order.
+ + +.DEBUGINFO
+Switch on or off debug info generation. The default is off (that is, +the object file will not contain debug infos), but may be changed by the +-g switch on the command line. +The command must be followed by a '+' or '-' character to switch the +option on or off respectively.
+Example:
++
+
+ .debuginfo + ; Generate debug info
+
+
+
+
+
+
+.DEFINE
+Start a define style macro definition. The command is followed by an +identifier (the macro name) and optionally by a list of formal arguments +in braces. +See section +Macros.
+ + +.DEF, .DEFINED
+Builtin function. The function expects an identifier as argument in braces.
+The argument is evaluated, and the function yields "true" if the identifier
+is a symbol that is already defined somewhere in the source file up to the
+current position. Otherwise the function yields false. As an example, the
+
+.IFDEF
statement may be replaced by
+
+
+ .if .defined(a)
+
+
+
+
+
+
+.DESTRUCTOR
+Export a symbol and mark it as a module destructor. This may be used +together with the linker to build a table of destructor subroutines that +are called by the startup code.
+Note: The linker has a feature to build a table of marked routines, but it +is your code that must call these routines, so just declaring a symbol as +constructor does nothing by itself.
+A destructor is always exported as an absolute (16 bit) symbol. You don't
+need to use an additional .export
statement, this is implied by
+.destructor
. It may have an optional priority that is separated by a
+comma. Higher numerical values mean a higher priority. If no priority is
+given, the default priority of 7 is used. Be careful when assigning
+priorities to your own module destructors so they won't interfere with the
+ones in the cc65 library.
Example:
++
+
+ .destructor ModuleDone
+ .destructor ModDone, 16
+
+
+
+
+See the
+.CONDES
and
+.CONSTRUCTOR
commands and the separate
+section
+Module constructors/destructors explaining
+the feature in more detail.
.DWORD
+Define dword sized data (4 bytes) Must be followed by a sequence of +expressions.
+Example:
++
+
+ .dword $12344512, $12FA489
+
+
+
+
+
+
+.ELSE
+Conditional assembly: Reverse the current condition.
+ + +.ELSEIF
+Conditional assembly: Reverse current condition and test a new one.
+ + +.END
+Forced end of assembly. Assembly stops at this point, even if the command +is read from an include file.
+ + +.ENDENUM
+End a
+.ENUM
declaration.
.ENDIF
+Conditional assembly: Close a
+.IF...
or
+
+.ELSE
branch.
.ENDMAC, .ENDMACRO
+End of macro definition (see section +Macros).
+ + +.ENDPROC
+End of local lexical level (see
+.PROC
).
.ENDREP, .ENDREPEAT
+End a
+.REPEAT
block.
.ENDSCOPE
+End of local lexical level (see
+.SCOPE
).
.ENDSTRUCT
+Ends a struct definition. See the
+.STRUCT
+command and the separate section named
+"Structs and unions".
.ENUM
+Start an enumeration. This directive is very similar to the C enum
+keyword. If a name is given, a new scope is created for the enumeration,
+otherwise the enumeration members are placed in the enclosing scope.
In the enumeration body, symbols are declared. The first symbol has a value +of zero, and each following symbol will get the value of the preceding plus +one. This behaviour may be overridden by an explicit assignment. Two symbols +may have the same value.
+Example:
++
+
+ .enum errorcodes
+ no_error
+ file_error
+ parse_error
+ .endenum
+
+
+
+
+Above example will create a new scope named errorcodes
with three
+symbols in it that get the values 0, 1 and 2 respectively. Another way
+to write this would have been:
+
+
+ .scope errorcodes
+ no_error = 0
+ file_error = 1
+ parse_error = 2
+ .endscope
+
+
+
+
+Please note that explicit scoping must be used to access the identifiers:
++
+
+ .word errorcodes::no_error
+
+
+
+
+A more complex example:
++
+
+ .enum
+ EUNKNOWN = -1
+ EOK
+ EFILE
+ EBUSY
+ EAGAIN
+ EWOULDBLOCK = EAGAIN
+ .endenum
+
+
+
+
+In this example, the enumeration does not have a name, which means that the
+members will be visible in the enclosing scope and can be used in this scope
+without explicit scoping. The first member (EUNKNOWN
) has the value -1.
+The value for the following members is incremented by one, so EOK
would
+be zero and so on. EWOULDBLOCK
is an alias for EGAIN
, so it has an
+override for the value using an already defined symbol.
.ERROR
+Force an assembly error. The assembler will output an error message +preceded by "User error" and will not produce an object file.
+This command may be used to check for initial conditions that must be +set before assembling a source file.
+Example:
++
+
+ .if foo = 1
+ ...
+ .elseif bar = 1
+ ...
+ .else
+ .error "Must define foo or bar!"
+ .endif
+
+
+
+
+See also the
+.WARNING
and
+.OUT
directives.
.EXITMAC, .EXITMACRO
+Abort a macro expansion immediately. This command is often useful in +recursive macros. See separate section +Macros.
+ + +.EXPORT
+Make symbols accessible from other modules. Must be followed by a comma +separated list of symbols to export, with each one optionally followed by +an address specification. The default is to export the symbol with the +address size it actually has. The assembler will issue a warning, if the +symbol is exported with an address size smaller than the actual address +size.
+Example:
++
+
+ .export foo
+ .export bar: far
+
+
+
+
+See:
+.EXPORTZP
.EXPORTZP
+Make symbols accessible from other modules. Must be followed by a comma +separated list of symbols to export. The exported symbols are explicitly +marked as zero page symbols.
+Example:
++
+
+ .exportzp foo, bar
+
+
+
+
+See:
+.EXPORT
.FARADDR
+Define far (24 bit) address data. The command must be followed by a +sequence of (not necessarily constant) expressions.
+Example:
++
+
+ .faraddr DrawCircle, DrawRectangle, DrawHexagon
+
+
+
+
+See:
+.ADDR
.FEATURE
+This directive may be used to enable one or more compatibility features
+of the assembler. While the use of .FEATURE
should be avoided when
+possible, it may be useful when porting sources written for other
+assemblers. There is no way to switch a feature off, once you have
+enabled it, so using
+
+
+ .FEATURE xxx
+
+
+
+
+will enable the feature until end of assembly is reached.
+The following features are available:
++
at_in_identifiers
Accept the at character (`@') as a valid character in identifiers. The +at character is not allowed to start an identifier, even with this +feature enabled.
+ +dollar_in_identifiers
Accept the dollar sign (`$') as a valid character in identifiers. The +at character is not allowed to start an identifier, even with this +feature enabled.
+ +dollar_is_pc
The dollar sign may be used as an alias for the star (`*'), which +gives the value of the current PC in expressions. +Note: Assignment to the pseudo variable is not allowed.
+ +labels_without_colons
Allow labels without a trailing colon. These labels are only accepted, +if they start at the beginning of a line (no leading white space).
+ +leading_dot_in_identifiers
Accept the dot (`.') as the first character of an identifier. This may be +used for example to create macro names that start with a dot emulating +control directives of other assemblers. Note however, that none of the +reserved keywords built into the assembler, that starts with a dot, may be +overridden. When using this feature, you may also get into trouble if +later versions of the assembler define new keywords starting with a dot.
+ +loose_char_term
Accept single quotes as well as double quotes as terminators for char +constants.
+ +loose_string_term
Accept single quotes as well as double quotes as terminators for string +constants.
+ +missing_char_term
Accept single quoted character constants where the terminating quote is +missing. +
+
+ lda #'a
+
+
+
+
+Note: This does not work in conjunction with .FEATURE
+loose_string_term
, since in this case the input would be ambiguous.
+
+pc_assignment
Allow assignments to the PC symbol (`*' or `$' if dollar_is_pc
+is enabled). Such an assignment is handled identical to the
+.ORG
command (which is usually not needed, so just
+removing the lines with the assignments may also be an option when porting
+code written for older assemblers).
ubiquitous_idents
Allow the use of instructions names as names for macros and symbols. This +makes it possible to "overload" instructions by defining a macro with the +same name. This does also make it possible to introduce hard to find errors +in your code, so be careful!
+ +It is also possible to specify features on the command line using the
+
+--feature
command line option.
+This is useful when translating sources written for older assemblers, when
+you don't want to change the source code.
As an example, to translate sources written for Andre Fachats xa65 +assembler, the features
++
+ labels_without_colons, pc_assignment, loose_char_term + ++ +
may be helpful. They do not make ca65 completely compatible, so you may not +be able to translate the sources without changes, even when enabling these +features. However, I have found several sources that translate without +problems when enabling these features on the command line.
+ + +.FILEOPT, .FOPT
+Insert an option string into the object file. There are two forms of +this command, one specifies the option by a keyword, the second +specifies it as a number. Since usage of the second one needs knowledge +of the internal encoding, its use is not recommended and I will only +describe the first form here.
+The command is followed by one of the keywords
++
+
+ author
+ comment
+ compiler
+
+
+
+
+a comma and a string. The option is written into the object file +together with the string value. This is currently unidirectional and +there is no way to actually use these options once they are in the +object file.
+Examples:
++
+
+ .fileopt comment, "Code stolen from my brother"
+ .fileopt compiler, "BASIC 2.0"
+ .fopt author, "J. R. User"
+
+
+
+
+
+
+.FORCEIMPORT
+Import an absolute symbol from another module. The command is followed by a
+comma separated list of symbols to import. The command is similar to
+.IMPORT
, but the import reference is always
+written to the generated object file, even if the symbol is never referenced
+(
+.IMPORT
will not generate import
+references for unused symbols).
Example:
++
+
+ .forceimport needthisone, needthistoo
+
+
+
+
+See:
+.IMPORT
.GLOBAL
+Declare symbols as global. Must be followed by a comma separated list of
+symbols to declare. Symbols from the list, that are defined somewhere in the
+source, are exported, all others are imported. Additional
+.IMPORT
or
+.EXPORT
commands for the same symbol are allowed.
Example:
++
+
+ .global foo, bar
+
+
+
+
+
+
+.GLOBALZP
+Declare symbols as global. Must be followed by a comma separated list of
+symbols to declare. Symbols from the list, that are defined somewhere in the
+source, are exported, all others are imported. Additional
+.IMPORTZP
or
+.EXPORTZP
commands for the same symbol are allowed. The symbols
+in the list are explicitly marked as zero page symbols.
Example:
++
+
+ .globalzp foo, bar
+
+
+
+
+
+
+.I16
+Valid only in 65816 mode. Switch the index registers to 16 bit.
+Note: This command will not emit any code, it will tell the assembler to +create 16 bit operands for immediate operands.
+See also the
+.I8
and
+.SMART
commands.
.I8
+Valid only in 65816 mode. Switch the index registers to 8 bit.
+Note: This command will not emit any code, it will tell the assembler to +create 8 bit operands for immediate operands.
+See also the
+.I16
and
+.SMART
commands.
.IF
+Conditional assembly: Evaluate an expression and switch assembler output +on or off depending on the expression. The expression must be a constant +expression, that is, all operands must be defined.
+A expression value of zero evaluates to FALSE, any other value evaluates +to TRUE.
+ + +.IFBLANK
+Conditional assembly: Check if there are any remaining tokens in this line,
+and evaluate to FALSE if this is the case, and to TRUE otherwise. If the
+condition is not true, further lines are not assembled until an
+.ESLE
,
+.ELSEIF
or
+
+.ENDIF
directive.
This command is often used to check if a macro parameter was given. Since an +empty macro parameter will evaluate to nothing, the condition will evaluate +to FALSE if an empty parameter was given.
+Example:
++
+
+ .macro arg1, arg2
+ .ifblank arg2
+ lda #arg1
+ .else
+ lda #arg2
+ .endif
+ .endmacro
+
+
+
+
+See also:
+.BLANK
.IFCONST
+Conditional assembly: Evaluate an expression and switch assembler output +on or off depending on the constness of the expression.
+A const expression evaluates to to TRUE, a non const expression (one +containing an imported or currently undefined symbol) evaluates to +FALSE.
+See also:
+.CONST
.IFDEF
+Conditional assembly: Check if a symbol is defined. Must be followed by +a symbol name. The condition is true if the the given symbol is already +defined, and false otherwise.
+See also:
+.DEFINED
.IFNBLANK
+Conditional assembly: Check if there are any remaining tokens in this line,
+and evaluate to TRUE if this is the case, and to FALSE otherwise. If the
+condition is not true, further lines are not assembled until an
+.ELSE
,
+.ELSEIF
or
+
+.ENDIF
directive.
This command is often used to check if a macro parameter was given. +Since an empty macro parameter will evaluate to nothing, the condition +will evaluate to FALSE if an empty parameter was given.
+Example:
++
+
+ .macro arg1, arg2
+ lda #arg1
+ .ifnblank arg2
+ lda #arg2
+ .endif
+ .endmacro
+
+
+
+
+See also:
+.BLANK
.IFNDEF
+Conditional assembly: Check if a symbol is defined. Must be followed by +a symbol name. The condition is true if the the given symbol is not +defined, and false otherwise.
+See also:
+.DEFINED
.IFNREF
+Conditional assembly: Check if a symbol is referenced. Must be followed +by a symbol name. The condition is true if if the the given symbol was +not referenced before, and false otherwise.
+See also:
+.REFERENCED
.IFP02
+Conditional assembly: Check if the assembler is currently in 6502 mode
+(see
+.P02
command).
.IFP816
+Conditional assembly: Check if the assembler is currently in 65816 mode
+(see
+.P816
command).
.IFPC02
+Conditional assembly: Check if the assembler is currently in 65C02 mode
+(see
+.PC02
command).
.IFPSC02
+Conditional assembly: Check if the assembler is currently in 65SC02 mode
+(see
+.PSC02
command).
.IFREF
+Conditional assembly: Check if a symbol is referenced. Must be followed +by a symbol name. The condition is true if if the the given symbol was +referenced before, and false otherwise.
+This command may be used to build subroutine libraries in include files +(you may use separate object modules for this purpose too).
+Example:
++
+
+ .ifref ToHex ; If someone used this subroutine
+ ToHex: tay ; Define subroutine
+ lda HexTab,y
+ rts
+ .endif
+
+
+
+
+See also:
+.REFERENCED
.IMPORT
+Import a symbol from another module. The command is followed by a comma +separated list of symbols to import, with each one optionally followed by +an address specification.
+Example:
++
+
+ .import foo
+ .import bar: zeropage
+
+
+
+
+See:
+.IMPORTZP
.IMPORTZP
+Import a symbol from another module. The command is followed by a comma +separated list of symbols to import. The symbols are explicitly imported +as zero page symbols (that is, symbols with values in byte range).
+Example:
++
+
+ .importzp foo, bar
+
+
+
+
+See:
+.IMPORT
.INCBIN
+Include a file as binary data. The command expects a string argument +that is the name of a file to include literally in the current segment. +In addition to that, a start offset and a size value may be specified, +separated by commas. If no size is specified, all of the file from the +start offset to end-of-file is used. If no start position is specified +either, zero is assumed (which means that the whole file is inserted).
+Example:
++
+
+ ; Include whole file
+ .incbin "sprites.dat"
+
+ ; Include file starting at offset 256
+ .incbin "music.dat", $100
+
+ ; Read 100 bytes starting at offset 200
+ .incbin "graphics.dat", 200, 100
+
+
+
+
+
+
+.INCLUDE
+Include another file. Include files may be nested up to a depth of 16.
+Example:
++
+
+ .include "subs.inc"
+
+
+
+
+
+
+.INTERRUPTOR
+Export a symbol and mark it as an interruptor. This may be used together +with the linker to build a table of interruptor subroutines that are called +in an interrupt.
+Note: The linker has a feature to build a table of marked routines, but it +is your code that must call these routines, so just declaring a symbol as +interruptor does nothing by itself.
+An interruptor is always exported as an absolute (16 bit) symbol. You don't
+need to use an additional .export
statement, this is implied by
+.interruptor
. It may have an optional priority that is separated by a
+comma. Higher numeric values mean a higher priority. If no priority is
+given, the default priority of 7 is used. Be careful when assigning
+priorities to your own module constructors so they won't interfere with the
+ones in the cc65 library.
Example:
++
+
+ .interruptor IrqHandler
+ .interruptor Handler, 16
+
+
+
+
+See the
+.CONDES
command and the separate
+section
+Module constructors/destructors explaining
+the feature in more detail.
.LINECONT
+Switch on or off line continuations using the backslash character +before a newline. The option is off by default. +Note: Line continuations do not work in a comment. A backslash at the +end of a comment is treated as part of the comment and does not trigger +line continuation. +The command must be followed by a '+' or '-' character to switch the +option on or off respectively.
+Example:
++
+
+ .linecont + ; Allow line continuations
+
+ lda \
+ #$20 ; This is legal now
+
+
+
+
+
+
+.LIST
+Enable output to the listing. The command must be followed by a boolean
+switch ("on", "off", "+" or "-") and will enable or disable listing
+output.
+The option has no effect if the listing is not enabled by the command line
+switch -l. If -l is used, an internal counter is set to 1. Lines are output
+to the listing file, if the counter is greater than zero, and suppressed if
+the counter is zero. Each use of .LIST
will increment or decrement the
+counter.
Example:
++
+
+ .list on ; Enable listing output
+
+
+
+
+
+
+.LISTBYTES
+Set, how many bytes are shown in the listing for one source line. The +default is 12, so the listing will show only the first 12 bytes for any +source line that generates more than 12 bytes of code or data. +The directive needs an argument, which is either "unlimited", or an +integer constant in the range 4..255.
+Examples:
++
+
+ .listbytes unlimited ; List all bytes
+ .listbytes 12 ; List the first 12 bytes
+ .incbin "data.bin" ; Include large binary file
+
+
+
+
+
+
+.LOCAL
+This command may only be used inside a macro definition. It declares a +list of identifiers as local to the macro expansion.
+A problem when using macros are labels: Since they don't change their name,
+you get a "duplicate symbol" error if the macro is expanded the second time.
+Labels declared with
+.LOCAL
have their
+name mapped to an internal unique name (___ABCD__
) with each macro
+invocation.
Some other assemblers start a new lexical block inside a macro expansion.
+This has some drawbacks however, since that will not allow any symbol
+to be visible outside a macro, a feature that is sometimes useful. The
+
+.LOCAL
command is in my eyes a better way
+to address the problem.
You get an error when using
+.LOCAL
outside
+a macro.
.LOCALCHAR
+Defines the character that start "cheap" local labels. You may use one +of '@' and '?' as start character. The default is '@'.
+Cheap local labels are labels that are visible only between two non
+cheap labels. This way you can reuse identifiers like "loop
" without
+using explicit lexical nesting.
Example:
++
+
+ .localchar '?'
+
+ Clear: lda #$00 ; Global label
+ ?Loop: sta Mem,y ; Local label
+ dey
+ bne ?Loop ; Ok
+ rts
+ Sub: ... ; New global label
+ bne ?Loop ; ERROR: Unknown identifier!
+
+
+
+
+
+
+.MACPACK
+Insert a predefined macro package. The command is followed by an +identifier specifying the macro package to insert. Available macro +packages are:
++
+
+ atari Defines the scrcode macro.
+ cbm Defines the scrcode macro.
+ cpu Defines constants for the .CPU variable.
+ generic Defines generic macros like add and sub.
+ longbranch Defines conditional long jump macros.
+
+
+
+
+Including a macro package twice, or including a macro package that +redefines already existing macros will lead to an error.
+Example:
++
+
+ .macpack longbranch ; Include macro package
+
+ cmp #$20 ; Set condition codes
+ jne Label ; Jump long on condition
+
+
+
+
+Macro packages are explained in more detail in section +Macro packages.
+ + +.MAC, .MACRO
+Start a classic macro definition. The command is followed by an identifier +(the macro name) and optionally by a comma separated list of identifiers +that are macro parameters.
+See section +Macros.
+ + +.ORG
+Start a section of absolute code. The command is followed by a constant
+expression that gives the new PC counter location for which the code is
+assembled. Use
+.RELOC
to switch back to
+relocatable code.
Please note that you do not need this command in most cases. Placing +code at a specific address is the job of the linker, not the assembler, so +there is usually no reason to assemble code to a specific address.
+You may not switch segments while inside a section of absolute code.
+Example:
++
+
+ .org $7FF ; Emit code starting at $7FF
+
+
+
+
+
+
+.OUT
+Output a string to the console without producing an error. This command
+is similar to .ERROR
, however, it does not force an assembler error
+that prevents the creation of an object file.
Example:
++
+
+ .out "This code was written by the codebuster(tm)"
+
+
+
+
+See also the
+.WARNING
and
+.ERROR
directives.
.P02
+Enable the 6502 instruction set, disable 65SC02, 65C02 and 65816
+instructions. This is the default if not overridden by the
+
+--cpu
command line option.
See:
+.PC02
,
+.PSC02
and
+.P816
.P816
+Enable the 65816 instruction set. This is a superset of the 65SC02 and +6502 instruction sets.
+See:
+.P02
,
+.PSC02
and
+.PC02
.PAGELEN, .PAGELENGTH
+Set the page length for the listing. Must be followed by an integer
+constant. The value may be "unlimited", or in the range 32 to 127. The
+statement has no effect if no listing is generated. The default value is -1
+(unlimited) but may be overridden by the --pagelength
command line
+option. Beware: Since ca65 is a one pass assembler, the listing is generated
+after assembly is complete, you cannot use multiple line lengths with one
+source. Instead, the value set with the last .PAGELENGTH
is used.
Examples:
++
+
+ .pagelength 66 ; Use 66 lines per listing page
+
+ .pagelength unlimited ; Unlimited page length
+
+
+
+
+
+
+.PC02
+Enable the 65C02 instructions set. This instruction set includes all +6502 and 65SC02 instructions.
+See:
+.P02
,
+.PSC02
and
+.P816
.POPSEG
+Pop the last pushed segment from the stack, and set it.
+This command will switch back to the segment that was last pushed onto the
+segment stack using the
+.PUSHSEG
+command, and remove this entry from the stack.
The assembler will print an error message if the segment stack is empty +when this command is issued.
+See:
+.PUSHSEG
.PROC
+Start a nested lexical level with the given name and adds a symbol with this
+name to the enclosing scope. All new symbols from now on are in the local
+lexical level and are accessible from outside only via
+explicit scope specification. Symbols defined outside this local
+level may be accessed as long as their names are not used for new symbols
+inside the level. Symbols names in other lexical levels do not clash, so you
+may use the same names for identifiers. The lexical level ends when the
+
+.ENDPROC
command is read. Lexical levels
+may be nested up to a depth of 16 (this is an artificial limit to protect
+against errors in the source).
Note: Macro names are always in the global level and in a separate name +space. There is no special reason for this, it's just that I've never +had any need for local macro definitions.
+Example:
++
+
+ .proc Clear ; Define Clear subroutine, start new level
+ lda #$00
+ L1: sta Mem,y ; L1 is local and does not cause a
+ ; duplicate symbol error if used in other
+ ; places
+ dey
+ bne L1 ; Reference local symbol
+ rts
+ .endproc ; Leave lexical level
+
+
+
+
+
+
+
+.PSC02
+Enable the 65SC02 instructions set. This instruction set includes all +6502 instructions.
+ + + +.PUSHSEG
+Push the currently active segment onto a stack. The entries on the stack +include the name of the segment and the segment type. The stack has a size +of 16 entries.
+.PUSHSEG
allows together with
+.POPSEG
+to switch to another segment and to restore the old segment later, without
+even knowing the name and type of the current segment.
The assembler will print an error message if the segment stack is already +full, when this command is issued.
+See:
+.POPSEG
.RELOC
+Switch back to relocatable mode. See the
+.ORG
command.
.REPEAT
+Repeat all commands between .REPEAT
and
+.ENDREPEAT
constant number of times. The command is followed by
+a constant expression that tells how many times the commands in the body
+should get repeated. Optionally, a comma and an identifier may be specified.
+If this identifier is found in the body of the repeat statement, it is
+replaced by the current repeat count (starting with zero for the first time
+the body is repeated).
.REPEAT
statements may be nested. If you use the same repeat count
+identifier for a nested .REPEAT
statement, the one from the inner
+level will be used, not the one from the outer level.
Example:
+The following macro will emit a string that is "encrypted" in that all +characters of the string are XORed by the value $55.
++
+
+ .macro Crypt Arg
+ .repeat .strlen(Arg), I
+ .byte .strat(Arg, I) ^ $55
+ .endrep
+ .endmacro
+
+
+
+
+See:
+.ENDREPEAT
.RES
+Reserve storage. The command is followed by one or two constant +expressions. The first one is mandatory and defines, how many bytes of +storage should be defined. The second, optional expression must by a +constant byte value that will be used as value of the data. If there +is no fill value given, the linker will use the value defined in the +linker configuration file (default: zero).
+Example:
++
+
+ ; Reserve 12 bytes of memory with value $AA
+ .res 12, $AA
+
+
+
+
+
+
+.RODATA
+Switch to the RODATA segment. The name of the RODATA segment is always +"RODATA", so this is a shortcut for
++
+
+ .segment "RODATA"
+
+
+
+
+The RODATA segment is a segment that is used by the compiler for +readonly data like string constants.
+See also the
+.SEGMENT
command.
.SCOPE
+Start a nested lexical level with the given name. All new symbols from now
+on are in the local lexical level and are accessible from outside only via
+explicit scope specification. Symbols defined
+outside this local level may be accessed as long as their names are not used
+for new symbols inside the level. Symbols names in other lexical levels do
+not clash, so you may use the same names for identifiers. The lexical level
+ends when the
+.ENDSCOPE
command is
+read. Lexical levels may be nested up to a depth of 16 (this is an
+artificial limit to protect against errors in the source).
Note: Macro names are always in the global level and in a separate name +space. There is no special reason for this, it's just that I've never +had any need for local macro definitions.
+Example:
++
+
+ .scope Error ; Start new scope named Error
+ None = 0 ; No error
+ File = 1 ; File error
+ Parse = 2 ; Parse error
+ .endproc ; Close lexical level
+
+ ...
+ lda #Error::File ; Use symbol from scope Error
+
+
+
+
+
+
+
+.SEGMENT
+Switch to another segment. Code and data is always emitted into a +segment, that is, a named section of data. The default segment is +"CODE". There may be up to 254 different segments per object file +(and up to 65534 per executable). There are shortcut commands for +the most common segments ("CODE", "DATA" and "BSS").
+The command is followed by a string containing the segment name (there are
+some constraints for the name - as a rule of thumb use only those segment
+names that would also be valid identifiers). There may also be an optional
+address size separated by a colon. See the section covering
+address sizes
for more information.
The default address size for a segment depends on the memory model specified +on the command line. The default is "absolute", which means that you don't +have to use an address size modifier in most cases.
+"absolute" means that the is a segment with 16 bit (absolute) addressing. +That is, the segment will reside somewhere in core memory outside the zero +page. "zeropage" (8 bit) means that the segment will be placed in the zero +page and direct (short) addressing is possible for data in this segment.
+Beware: Only labels in a segment with the zeropage attribute are marked +as reachable by short addressing. The `*' (PC counter) operator will +work as in other segments and will create absolute variable values.
+Please note that a segment cannot have two different address sizes. A +segment specified as zeropage cannot be declared as being absolute later.
+Examples:
++
+
+ .segment "ROM2" ; Switch to ROM2 segment
+ .segment "ZP2": zeropage ; New direct segment
+ .segment "ZP2" ; Ok, will use last attribute
+ .segment "ZP2": absolute ; Error, redecl mismatch
+
+
+
+
+See:
+.BSS
,
+.CODE
,
+.DATA
and
+.RODATA
.SETCPU
+Switch the CPU instruction set. The command is followed by a string that
+specifies the CPU. Possible values are those that can also be supplied to
+the
+--cpu
command line option,
+namely: 6502, 6502X, 65SC02, 65C02, 65816, sunplus and HuC6280. Please
+note that support for the sunplus CPU is not available in the freeware
+version, because the instruction set of the sunplus CPU is "proprietary
+and confidential".
See:
+.CPU
,
+
+.IFP02
,
+
+.IFP816
,
+
+.IFPC02
,
+
+.IFPSC02
,
+
+.P02
,
+
+.P816
,
+
+.PC02
,
+
+.PSC02
.SMART
+Switch on or off smart mode. The command must be followed by a '+' or '-' +character to switch the option on or off respectively. The default is off +(that is, the assembler doesn't try to be smart), but this default may be +changed by the -s switch on the command line.
+In smart mode the assembler will do the following:
++
REP
and SEP
instructions in 65816 mode
+and update the operand sizes accordingly. If the operand of such an
+instruction cannot be evaluated by the assembler (for example, because
+the operand is an imported symbol), a warning is issued. Beware: Since
+the assembler cannot trace the execution flow this may lead to false
+results in some cases. If in doubt, use the .Inn
and .Ann
+instructions to tell the assembler about the current settings.RTS
instruction by RTL
if it is
+used within a procedure declared as far
, or if the procedure has
+no explicit address specification, but it is far
because of the
+memory model used.Example:
++
+
+ .smart ; Be smart
+ .smart - ; Stop being smart
+
+
+
+
+See:
+.A16
,
+
+.A8
,
+
+.I16
,
+
+.I8
.STRUCT
+Starts a struct definition. Structs are covered in a separate section named +"Structs and unions".
+See:
+.ENDSTRUCT
.SUNPLUS
+Enable the SunPlus instructions set. This command will not work in the +freeware version of the assembler, because the instruction set is +"proprietary and confidential".
+See:
+.P02
,
+.PSC02
,
+.PC02
, and
+
+.P816
.TAG
+Allocate space for a struct or union.
+Example:
++
+
+ .struct Point
+ xcoord .word
+ ycoord .word
+ .endstruct
+
+ .bss
+ .tag Point ; Allocate 4 bytes
+
+
+
+
+
+
+.WARNING
+Force an assembly warning. The assembler will output a warning message
+preceded by "User warning". This warning will always be output, even if
+other warnings are disabled with the
+-W0
+command line option.
This command may be used to output possible problems when assembling +the source file.
+Example:
++
+
+ .macro jne target
+ .local L1
+ .ifndef target
+ .warning "Forward jump in jne, cannot optimize!"
+ beq L1
+ jmp target
+ L1:
+ .else
+ ...
+ .endif
+ .endmacro
+
+
+
+
+See also the
+.ERROR
and
+.OUT
directives.
.WORD
+Define word sized data. Must be followed by a sequence of (word ranged, +but not necessarily constant) expressions.
+Example:
++
+
+ .word $0D00, $AF13, _Clear
+
+
+
+
+
+
+.ZEROPAGE
+Switch to the ZEROPAGE segment and mark it as direct (zeropage) segment. +The name of the ZEROPAGE segment is always "ZEROPAGE", so this is a +shortcut for
++
+
+ .segment "ZEROPAGE", zeropage
+
+
+
+
+Because of the "zeropage" attribute, labels declared in this segment are +addressed using direct addressing mode if possible. You must instruct +the linker to place this segment somewhere in the address range 0..$FF +otherwise you will get errors.
+See:
+.SEGMENT
Macros may be thought of as "parametrized super instructions". Macros are +sequences of tokens that have a name. If that name is used in the source +file, the macro is "expanded", that is, it is replaced by the tokens that +were specified when the macro was defined.
+ + +In it's simplest form, a macro does not have parameters. Here's an +example:
++
+
+ .macro asr ; Arithmetic shift right
+ cmp #$80 ; Put bit 7 into carry
+ ror ; Rotate right with carry
+ .endmacro
+
+
+
+The macro above consists of two real instructions, that are inserted into +the code, whenever the macro is expanded. Macro expansion is simply done +by using the name, like this:
++
+
+ lda $2010
+ asr
+ sta $2010
+
+
+
+
+
+When using macro parameters, macros can be even more useful:
++
+
+ .macro inc16 addr
+ clc
+ lda addr
+ adc #$01
+ sta addr
+ lda addr+1
+ adc #$00
+ sta addr+1
+ .endmacro
+
+
+
+When calling the macro, you may give a parameter, and each occurrence of +the name "addr" in the macro definition will be replaced by the given +parameter. So
++
+
+ inc16 $1000
+
+
+
+will be expanded to
++
+
+ clc
+ lda $1000
+ adc #$01
+ sta $1000
+ lda $1000+1
+ adc #$00
+ sta $1000+1
+
+
+
+A macro may have more than one parameter, in this case, the parameters +are separated by commas. You are free to give less parameters than the +macro actually takes in the definition. You may also leave intermediate +parameters empty. Empty parameters are replaced by empty space (that is, +they are removed when the macro is expanded). If you have a look at our +macro definition above, you will see, that replacing the "addr" parameter +by nothing will lead to wrong code in most lines. To help you, writing +macros with a variable parameter list, there are some control commands:
+
+.IFBLANK
tests the rest of the line and
+returns true, if there are any tokens on the remainder of the line. Since
+empty parameters are replaced by nothing, this may be used to test if a given
+parameter is empty.
+.IFNBLANK
tests the
+opposite.
Look at this example:
++
+
+ .macro ldaxy a, x, y
+ .ifnblank a
+ lda #a
+ .endif
+ .ifnblank x
+ ldx #x
+ .endif
+ .ifnblank y
+ ldy #y
+ .endif
+ .endmacro
+
+
+
+This macro may be called as follows:
++
+
+ ldaxy 1, 2, 3 ; Load all three registers
+
+ ldaxy 1, , 3 ; Load only a and y
+
+ ldaxy , , 3 ; Load y only
+
+
+
+There's another helper command for determining, which macro parameters are
+valid:
+.PARAMCOUNT
This command is
+replaced by the parameter count given, including intermediate empty macro
+parameters:
+
+
+ ldaxy 1 ; .PARAMCOUNT = 1
+ ldaxy 1,,3 ; .PARAMCOUNT = 3
+ ldaxy 1,2 ; .PARAMCOUNT = 2
+ ldaxy 1, ; .PARAMCOUNT = 2
+ ldaxy 1,2,3 ; .PARAMCOUNT = 3
+
+
+
+Macro parameters may optionally be enclosed into curly braces. This allows the +inclusion of tokens that would otherwise terminate the parameter (the comma in +case of a macro parameter).
++
+
+ .macro foo arg1, arg2
+ ...
+ .endmacro
+
+ foo ($00,x) ; Two parameters passed
+ foo {($00,x)} ; One parameter passed
+
+
+
+In the first case, the macro is called with two parameters: '($00
'
+and 'x)'. The comma is not passed to the macro, since it is part of the
+calling sequence, not the parameters.
In the second case, '($00,x)' is passed to the macro, this time +including the comma.
+ + +Sometimes it is nice to write a macro that acts differently depending on the
+type of the argument supplied. An example would be a macro that loads a 16 bit
+value from either an immediate operand, or from memory. The
+.MATCH
and
+.XMATCH
+functions will allow you to do exactly this:
+
+
+ .macro ldax arg
+ .if (.match (.left (1, {arg}), #))
+ ; immediate mode
+ lda #<(.right (.tcount ({arg})-1, {arg}))
+ ldx #>(.right (.tcount ({arg})-1, {arg}))
+ .else
+ ; assume absolute or zero page
+ lda arg
+ ldx 1+(arg)
+ .endif
+ .endmacro
+
+
+
+Using the
+.MATCH
function, the macro is able to
+check if its argument begins with a hash mark. If so, two immediate loads are
+emitted, Otherwise a load from an absolute zero page memory location is
+assumed. Please note how the curly braces are used to enclose parameters to
+pseudo functions handling token lists. This is necessary, because the token
+lists may include commas or parens, which would be treated by the assembler
+as end-of-list.
The macro can be used as
++
+
+ foo: .word $5678
+ ...
+ ldax #$1234 ; X=$12, A=$34
+ ...
+ ldax foo ; X=$56, A=$78
+
+
+
+
+
+Macros may be used recursively:
++
+
+ .macro push r1, r2, r3
+ lda r1
+ pha
+ .if .paramcount > 1
+ push r2, r3
+ .endif
+ .endmacro
+
+
+
+There's also a special macro to help writing recursive macros:
+.EXITMACRO
This command will stop macro expansion
+immediately:
+
+
+ .macro push r1, r2, r3, r4, r5, r6, r7
+ .ifblank r1
+ ; First parameter is empty
+ .exitmacro
+ .else
+ lda r1
+ pha
+ .endif
+ push r2, r3, r4, r5, r6, r7
+ .endmacro
+
+
+
+When expanding this macro, the expansion will push all given parameters +until an empty one is encountered. The macro may be called like this:
++
+
+ push $20, $21, $32 ; Push 3 ZP locations
+ push $21 ; Push one ZP location
+
+
+
+
+
+Now, with recursive macros,
+.IFBLANK
and
+
+.PARAMCOUNT
, what else do you need?
+Have a look at the inc16 macro above. Here is it again:
+
+
+ .macro inc16 addr
+ clc
+ lda addr
+ adc #$01
+ sta addr
+ lda addr+1
+ adc #$00
+ sta addr+1
+ .endmacro
+
+
+
+If you have a closer look at the code, you will notice, that it could be +written more efficiently, like this:
++
+
+ .macro inc16 addr
+ inc addr
+ bne Skip
+ inc addr+1
+ Skip:
+ .endmacro
+
+
+
+But imagine what happens, if you use this macro twice? Since the label +"Skip" has the same name both times, you get a "duplicate symbol" error. +Without a way to circumvent this problem, macros are not as useful, as +they could be. One solution is, to start a new lexical block inside the +macro:
++
+
+ .macro inc16 addr
+ .proc
+ inc addr
+ bne Skip
+ inc addr+1
+ Skip:
+ .endproc
+ .endmacro
+
+
+
+Now the label is local to the block and not visible outside. However,
+sometimes you want a label inside the macro to be visible outside. To make
+that possible, there's a new command that's only usable inside a macro
+definition:
+.LOCAL
. .LOCAL
declares one
+or more symbols as local to the macro expansion. The names of local variables
+are replaced by a unique name in each separate macro expansion. So we could
+also solve the problem above by using .LOCAL
:
+
+
+ .macro inc16 addr
+ .local Skip ; Make Skip a local symbol
+ clc
+ lda addr
+ adc #$01
+ sta addr
+ bcc Skip
+ inc addr+1
+ Skip: ; Not visible outside
+ .endmacro
+
+
+
+
+
+Starting with version 2.5 of the assembler, there is a second macro type
+available: C style macros using the .DEFINE
directive. These macros are
+similar to the classic macro type described above, but behaviour is sometimes
+different:
+
+.DEFINE
may not
+span more than a line. You may use line continuation (see
+.LINECONT
) to spread the definition over
+more than one line for increased readability, but the macro itself
+may not contain an end-of-line token.
+
+.DEFINE
share
+the name space with classic macros, but they are detected and replaced
+at the scanner level. While classic macros may be used in every place,
+where a mnemonic or other directive is allowed,
+.DEFINE
style macros are allowed anywhere in a line. So
+they are more versatile in some situations.
+
+.DEFINE
style macros may take
+parameters. While classic macros may have empty parameters, this is
+not true for
+.DEFINE
style macros.
+For this macro type, the number of actual parameters must match
+exactly the number of formal parameters.
+
+To make this possible, formal parameters are enclosed in braces when
+defining the macro. If there are no parameters, the empty braces may
+be omitted.
+
+.DEFINE
style macros may not
+contain end-of-line tokens, there are things that cannot be done. They
+may not contain several processor instructions for example. So, while
+some things may be done with both macro types, each type has special
+usages. The types complement each other.
+Let's look at a few examples to make the advantages and disadvantages +clear.
+To emulate assemblers that use "EQU
" instead of "=
" you may use the
+following .DEFINE
:
+
+
+ .define EQU =
+
+ foo EQU $1234 ; This is accepted now
+
+
+
+You may use the directive to define string constants used elsewhere:
++
+
+ ; Define the version number
+ .define VERSION "12.3a"
+
+ ; ... and use it
+ .asciiz VERSION
+
+
+
+Macros with parameters may also be useful:
++
+
+ .define DEBUG(message) .out message
+
+ DEBUG "Assembling include file #3"
+
+
+
+Note that, while formal parameters have to be placed in braces, this is +not true for the actual parameters. Beware: Since the assembler cannot +detect the end of one parameter, only the first token is used. If you +don't like that, use classic macros instead:
++
+
+ .macro message
+ .out message
+ .endmacro
+
+
+
+(This is an example where a problem can be solved with both macro types).
+ + +When using the
+-t option, characters are translated
+into the target character set of the specific machine. However, this happens
+as late as possible. This means that strings are translated if they are part
+of a
+.BYTE
or
+.ASCIIZ
command. Characters are translated as soon as they are
+used as part of an expression.
This behaviour is very intuitive outside of macros but may be confusing when +doing more complex macros. If you compare characters against numeric values, +be sure to take the translation into account.
+ + + + +Using the
+.MACPACK
directive, predefined
+macro packages may be included with just one command. Available macro packages
+are:
.MACPACK generic
+This macro package defines macros that are useful in almost any program. +Currently, two macros are defined:
++
+
+ .macro add Arg
+ clc
+ adc Arg
+ .endmacro
+
+ .macro sub Arg
+ sec
+ sbc Arg
+ .endmacro
+
+
+
+
+
+.MACPACK longbranch
+This macro package defines long conditional jumps. They are named like the
+short counterpart but with the 'b' replaced by a 'j'. Here is a sample
+definition for the "jeq
" macro, the other macros are built using the same
+scheme:
+
+
+ .macro jeq Target
+ .if .def(Target) .and ((*+2)-(Target) <= 127)
+ beq Target
+ .else
+ bne *+5
+ jmp Target
+ .endif
+ .endmacro
+
+
+
+All macros expand to a short branch, if the label is already defined (back +jump) and is reachable with a short jump. Otherwise the macro expands to a +conditional branch with the branch condition inverted, followed by an absolute +jump to the actual branch target.
+The package defines the following macros:
++
+
+ jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc
+
+
+
+
+
+
+.MACPACK cbm
+The cbm macro package will define a macro named scrcode
. It takes a
+string as argument and places this string into memory translated into screen
+codes.
.MACPACK cpu
+This macro package does not define any macros but constants used to examine
+the value read from the
+.CPU
pseudo variable. For
+each supported CPU a constant similar to
+
+
+ CPU_6502
+ CPU_65SC02
+ CPU_65C02
+ CPU_65816
+ CPU_SUNPLUS
+ CPU_SWEET16
+ CPU_HUC6280
+
+
+
+is defined. These constants may be used to determine the exact type of the +currently enabled CPU. In addition to that, for each CPU instruction set, +another constant is defined:
++
+
+ CPU_ISET_6502
+ CPU_ISET_65SC02
+ CPU_ISET_65C02
+ CPU_ISET_65816
+ CPU_ISET_SUNPLUS
+ CPU_ISET_SWEET16
+ CPU_ISET_HUC6280
+
+
+
+The value read from the
+.CPU
pseudo variable may
+be checked with
+.BITAND
to determine if the
+currently enabled CPU supports a specific instruction set. For example the
+65C02 supports all instructions of the 65SC02 CPU, so it has the
+CPU_ISET_65SC02
bit set in addition to its native CPU_ISET_65C02
+bit. Using
+
+
+ .if (.cpu .bitand CPU_ISET_65SC02)
+ lda (sp)
+ .else
+ ldy #$00
+ lda (sp),y
+ .endif
+
+
+
+it is possible to determine if the
++
+
+ lda (sp)
+
+
+
+instruction is supported, which is the case for the 65SC02, 65C02 and 65816 +CPUs (the latter two are upwards compatible to the 65SC02).
+ + + +For better orthogonality, the assembler defines similar symbols as the +compiler, depending on the target system selected:
++
__ACE__
- Target system is ace
__APPLE2__",
- Target system is apple2
__APPLE2ENH__",
- Target system is apple2enh
__ATARI__
- Target system is atari
__ATMOS__",
- Target system is atmos
__BBC__",
- Target system is bbc
__C128__
- Target system is c128
__C16__
- Target system is c16
__C64__
- Target system is c64
__CBM__
- Target is a Commodore system__CBM510__
- Target system is cbm510
__CBM610__
- Target system is cbm610
__GEOS__",
- Target system is geos
__LUNIX__",
- Target system is lunix
__NES__",
- Target system is nes
__PET__
- Target system is pet
__PLUS4__
- Target system is plus4
__SUPERVISION__",
- Target system is supervision
__VIC20__
- Target system is vic20
Structs and unions are special forms of +scopes. They +are to some degree comparable to their C counterparts. Both have a list of +members. Each member allocates storage and may optionally have a name, which, +in case of a struct, is the offset from the beginning and, in case of a union, +is always zero.
+ + +Here is an example for a very simple struct with two members and a total size +of 4 bytes:
++
+
+ .struct Point
+ xcoord .word
+ ycoord .word
+ .endstruct
+
+
+
+A union shares the total space between all its members, its size is the same +as that of the largest member.
+A struct or union must not necessarily have a name. If it is anonymous, no +local scope is opened, the identifiers used to name the members are placed +into the current scope instead.
+A struct may contain unnamed members and definitions of local structs. The +storage allocators may contain a multiplier, as in the example below:
++
+
+ .struct Circle
+ .struct Point
+ .word 2 ; Allocate two words
+ .endstruct
+ Radius .word
+ .endstruct
+
+
+
+
+
+.TAG
keyword
+Using the +.TAG keyword, it is possible to reserve space +for an already defined struct or unions within another struct:
++
+
+ .struct Point
+ xcoord .word
+ ycoord .word
+ .endstruct
+
+ .struct Circle
+ Origin .tag Point
+ Radius .byte
+ .endstruct
+
+
+
+Space for a struct or union may be allocated using the +.TAG directive.
++
+
+ C: .tag Circle
+
+
+
+Currently, members are just offsets from the start of the struct or union. To +access a field of a struct, the member offset has to be added to the address +of the struct itself:
++
+
+ lda C+Circle::Radius ; Load circle radius into A
+
+
+
+This may change in a future version of the assembler.
+ + +Structs and unions are currently implemented as nested symbol tables (in fact, +they were a by-product of the improved scoping rules). Currently, the +assembler has no idea of types. This means that the +.TAG keyword will only allocate space. You won't be able to initialize +variables declared with +.TAG, and adding an embedded +structure to another structure with +.TAG will not make +this structure accessible by using the '::' operator.
+ + + +Note: This section applies mostly to C programs, so the explanation +below uses examples from the C libraries. However, the feature may also be +useful for assembler programs.
+ + +Using the
+.CONSTRUCTOR
,
+.DESTRUCTOR
and
+.INTERRUPTOR
keywords it it possible to export functions in a
+special way. The linker is able to generate tables with all functions of a
+specific type. Such a table will only include symbols from object
+files that are linked into a specific executable. This may be used to add
+initialization and cleanup code for library modules, or a table of interrupt
+handler functions.
The C heap functions are an example where module initialization code is used.
+All heap functions (malloc
, free
, ...) work with a few
+variables that contain the start and the end of the heap, pointers to the free
+list and so on. Since the end of the heap depends on the size and start of the
+stack, it must be initialized at runtime. However, initializing these
+variables for programs that do not use the heap are a waste of time and
+memory.
So the central module defines a function that contains initialization code and
+exports this function using the .CONSTRUCTOR
statement. If (and only if)
+this module is added to an executable by the linker, the initialization
+function will be placed into the table of constructors by the linker. The C
+startup code will call all constructors before main
and all destructors
+after main
, so without any further work, the heap initialization code is
+called once the module is linked in.
While it would be possible to add explicit calls to initialization functions +in the startup code, the new approach has several advantages:
++
The symbols are sorted in increasing priority order by the linker when using +one of the builtin linker configurations, so the functions with lower +priorities come first and are followed by those with higher priorities. The C +library runtime subroutine that walks over the function tables calls the +functions starting from the top of the table - which means that functions with +a high priority are called first.
+So when using the C runtime, functions are called with high priority functions +first, followed by low priority functions.
+ + +When using these special symbols, please take care of the following:
++
condes
and callirq
modules
+in the C runtime for an example on how to do this.
+FEATURE CONDES
statement in the linker config file. Each table has to
+be requested separately.
+
+.CONSTRUCTOR
,
+.DESTRUCTOR
and
+.INTERRUPTOR
statements, there is also a more generic command:
+
+.CONDES
. This allows to specify an
+additional type. Predefined types are 0 (constructor), 1 (destructor) and 2
+(interruptor). The linker generates a separate table for each type on request.
+Sometimes it is necessary to port code written for older assemblers to ca65.
+In some cases, this can be done without any changes to the source code by
+using the emulation features of ca65 (see
+.FEATURE
). In other cases, it is necessary to make changes to the
+source code.
Probably the biggest difference is the handling of the
+.ORG
directive. ca65 generates relocatable code, and placement is
+done by the linker. Most other assemblers generate absolute code, placement is
+done within the assembler and there is no external linker.
In general it is not a good idea to write new code using the emulation +features of the assembler, but there may be situations where even this rule is +not valid.
+ +You need to use some of the ca65 emulation features to simulate the behaviour +of such simple assemblers.
++
+
+ ; if you want TASS style labels without colons
+ .feature labels_without_colons
+
+ ; if you want TASS style character constants
+ ; ("a" instead of the default 'a')
+ .feature loose_char_term
+
+ .word *+2 ; the cbm load address
+
+ [yourcode here]
+
+
+
+
+notice that the two emulation features are mostly useful for porting
+sources originally written in/for TASS, they are not needed for the
+actual "simple assembler operation" and are not recommended if you are
+writing new code from scratch.
+
+.RES
directive.
+
+
+
+ ; *=$2000
+ .res $2000-* ; reserve memory up to $2000
+
+
+
+
+Please note that other than the original TASS, ca65 can never move the program
+counter backwards - think of it as if you are assembling to disk with TASS.
+.ifeq
/.endif
/.goto
etc.) must be
+rewritten to match ca65 syntax. Most importantly notice that due to the lack
+of .goto
, everything involving loops must be replaced by
+
+.REPEAT
.
+
+.ORG
directive instead of
+.offs
-constructs.
+
+
+
+ .org $1800
+
+ [floppy code here]
+
+ .reloc ; back to normal
+
+
+
+
+
+ cl65 --start-addr 0x0ffe -t none myprog.s -o myprog.prg
+
+
+
+
+Note that you need to use the actual start address minus two, since two bytes
+are used for the cbm load address.
+If you have problems using the assembler, if you find any bugs, or if +you're doing something interesting with the assembler, I would be glad to +hear from you. Feel free to contact me by email +( +uz@cc65.org).
+ + + +ca65 (and all cc65 binutils) are (C) Copyright 1998-2003 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply:
+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:
++
The assembler accepts the following options:
++
+
+---------------------------------------------------------------------------
+Usage: ca65 [options] file
+Short options:
+ -D name[=value] Define a symbol
+ -I dir Set an include directory search path
+ -U Mark unresolved symbols as import
+ -V Print the assembler version
+ -W n Set warning level n
+ -g Add debug info to object file
+ -h Help (this text)
+ -i Ignore case of symbols
+ -l Create a listing if assembly was ok
+ -mm model Set the memory model
+ -o name Name the output file
+ -s Enable smart mode
+ -t sys Set the target system
+ -v Increase verbosity
+
+Long options:
+ --auto-import Mark unresolved symbols as import
+ --cpu type Set cpu type
+ --debug-info Add debug info to object file
+ --feature name Set an emulation feature
+ --help Help (this text)
+ --ignore-case Ignore case of symbols
+ --include-dir dir Set an include directory search path
+ --listing Create a listing if assembly was ok
+ --list-bytes n Maximum number of bytes per listing line
+ --macpack-dir dir Set a macro package directory
+ --memory-model model Set the memory model
+ --pagelength n Set the page length for the listing
+ --smart Enable smart mode
+ --target sys Set the target system
+ --verbose Increase verbosity
+ --version Print the assembler version
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
--cpu type
Set the default for the CPU type. The option takes a parameter, which +may be one of
+6502, 65SC02, 65C02, 65816, sunplus, sweet16, HuC6280
+The sunplus cpu is not available in the freeware version, because the +instruction set is "proprietary and confidential".
+ + +--feature name
Enable an emulation feature. This is identical as using .FEATURE
+in the source with two exceptions: Feature names must be lower case, and
+each feature must be specified by using an extra --feature
option,
+comma separated lists are not allowed.
See the discussion of the
+.FEATURE
+command for a list of emulation features.
-g, --debug-info
When this option (or the equivalent control command .DEBUGINFO
) is
+used, the assembler will add a section to the object file that contains
+all symbols (including local ones) together with the symbol values and
+source file positions. The linker will put these additional symbols into
+the VICE label file, so even local symbols can be seen in the VICE
+monitor.
-h, --help
Print the short option summary shown above.
+ + +-i, --ignore-case
This option makes the assembler case insensitive on identifiers and labels.
+This option will override the default, but may itself be overridden by the
+
+.CASE
control command.
-l, --listing
Generate an assembler listing. The listing file will always have the +name of the main input file with the extension replaced by ".lst". This +may change in future versions.
+ + +--list-bytes n
Set the maximum number of bytes printed in the listing for one line of
+input. See the
+.LISTBYTES
directive
+for more information. The value zero can be used to encode an unlimited
+number of printed bytes.
--macpack-dir dir
This options allows to specify a directory containing macro files that are
+used instead of the builtin images when a
+.MACPACK
directive is encountered. If --macpack-dir
+was specified, a .mac
extension is added to the package name and
+the resulting file is loaded from the given directory. This is most useful
+when debugging the builtin macro packages.
-mm model, --memory-model model
Define the default memory model. Possible model specifiers are near, far and +huge.
+ + +-o name
The default output name is the name of the input file with the extension +replaced by ".o". If you don't like that, you may give another name with +the -o option. The output file will be placed in the same directory as +the source file, or, if -o is given, the full path in this name is used.
+ + +--pagelength n
sets the length of a listing page in lines. See the
+.PAGELENGTH
directive for more information.
-s, --smart-mode
In smart mode (enabled by -s or the
+.SMART
+pseudo instruction) the assembler will track usage of the REP
and
+SEP
instructions in 65816 mode and update the operand sizes
+accordingly. If the operand of such an instruction cannot be evaluated by
+the assembler (for example, because the operand is an imported symbol), a
+warning is issued.
Beware: Since the assembler cannot trace the execution flow this may +lead to false results in some cases. If in doubt, use the .ixx and .axx +instructions to tell the assembler about the current settings. Smart +mode is off by default.
+ + +-t sys, --target sys
Set the target system. This will enable translation of character strings +and character constants into the character set of the target platform. +The default for the target system is "none", which means that no translation +will take place. The assembler supports the same target systems as the +compiler, see there for a list.
+ + +-v, --verbose
Increase the assembler verbosity. Usually only needed for debugging +purposes. You may use this option more than one time for even more +verbose output.
+ + +-D
This option allows you to define symbols on the command line. Without a +value, the symbol is defined with the value zero. When giving a value, +you may use the '$' prefix for hexadecimal symbols. Please note +that for some operating systems, '$' has a special meaning, so +you may have to quote the expression.
+ + +-I dir, --include-dir dir
Name a directory which is searched for include files. The option may be +used more than once to specify more than one directory to search. The +current directory is always searched first before considering any +additional directories.
+ + +-U, --auto-import
Mark symbols that are not defined in the sources as imported symbols. This
+should be used with care since it delays error messages about typos and such
+until the linker is run. The compiler uses the equivalent of this switch
+(
+.AUTOIMPORT
) to enable auto imported
+symbols for the runtime library. However, the compiler is supposed to
+generate code that runs through the assembler without problems, something
+which is not always true for assembler programmers.
-V, --version
Print the version number of the assembler. If you send any suggestions +or bugfixes, please include the version number.
+ + +-Wn
Set the warning level for the assembler. Using -W2 the assembler will +even warn about such things like unused imported symbols. The default +warning level is 1, and it would probably be silly to set it to +something lower.
+ +The assembler accepts the standard 6502/65816 assembler syntax. One line may +contain a label (which is identified by a colon), and, in addition to the +label, an assembler mnemonic, a macro, or a control command (see section +Control Commands for supported control +commands). Alternatively, the line may contain a symbol definition using +the '=' token. Everything after a semicolon is handled as a comment (that is, +it is ignored).
+Here are some examples for valid input lines:
++
+
+ Label: ; A label and a comment
+ lda #$20 ; A 6502 instruction plus comment
+ L1: ldx #$20 ; Same with label
+ L2: .byte "Hello world" ; Label plus control command
+ mymac $20 ; Macro expansion
+ MySym = 3*L1 ; Symbol definition
+ MaSym = Label ; Another symbol
+
+
+
+The assembler accepts
++
+.P02
command was given).
+.PSC02
command was given).
+.PC02
command was given).
+.P816
command was given).
+.SUNPLUS
command was given).In 65816 mode several aliases are accepted in addition to the official +mnemonics:
++
+
+ BGE is an alias for BCS
+ BLT is an alias for BCC
+ CPA is an alias for CMP
+ DEA is an alias for DEC A
+ INA is an alias for INC A
+ SWA is an alias for XBA
+ TAD is an alias for TCD
+ TAS is an alias for TCS
+ TDA is an alias for TDC
+ TSA is an alias for TSC
+
+
+
+
+
+
+6502X mode is an extension to the normal 6502 mode. In this mode, several +mnemonics for illegal instructions of the NMOS 6502 CPUs are accepted. Since +these instructions are illegal, there are no official mnemonics for them. The +unofficial ones are taken from +http://oxyron.net/graham/opcodes02.html. Please note that only the +ones marked as "stable" are supported. The following table uses information +from the mentioned web page, for more information, see there.
++
ALR: A:=(A and #{imm})*2;
ANC: A:=A and #{imm};
Generates opcode $0B.ARR: A:=(A and #{imm})/2;
AXS: X:=A and X-#{imm};
DCP: {adr}:={adr}-1; A-{adr};
ISC: {adr}:={adr}+1; A:=A-{adr};
LAS: A,X,S:={adr} and S;
LAX: A,X:={adr};
RLA: {adr}:={adr}rol; A:=A and {adr};
RRA: {adr}:={adr}ror; A:=A adc {adr};
SAX: {adr}:=A and X;
SLO: {adr}:={adr}*2; A:=A or {adr};
SRE: {adr}:={adr}/2; A:=A xor {adr};
SWEET 16 is an interpreter for a pseudo 16 bit CPU written by Steve Wozniak +for the Apple ][ machines. It is available in the Apple ][ ROM. ca65 can +generate code for this pseudo CPU when switched into sweet16 mode. The +following is special in sweet16 mode:
++
+.LOCALCHAR
command.
+R0
.. R15
. In sweet16 mode,
+these identifiers are reserved words.
+Please note that the assembler does neither supply the interpreter needed for +SWEET 16 code, nor the zero page locations needed for the SWEET 16 registers, +nor does it call the interpreter. All this must be done by your program. Apple +][ programmers do probably know how to use sweet16 mode.
+For more information about SWEET 16, see +http://www.6502.org/source/interpreters/sweet16.htm.
+ + +For literal values, the assembler accepts the widely used number formats: A +preceding '$' or a trailing 'h' denotes a hex value, a preceding '%' +denotes a binary value, and a bare number is interpreted as a decimal. There +are currently no octal values and no floats.
+ + +Please note that when using the conditional directives (.IF
and friends),
+the input must consist of valid assembler tokens, even in .IF
branches
+that are not assembled. The reason for this behaviour is that the assembler
+must still be able to detect the ending tokens (like .ENDIF
), so
+conversion of the input stream into tokens still takes place. As a consequence
+conditional assembly directives may not be used to prevent normal text
+(used as a comment or similar) from being assembled.
All expressions are evaluated with (at least) 32 bit precision. An +expression may contain constant values and any combination of internal and +external symbols. Expressions that cannot be evaluated at assembly time +are stored inside the object file for evaluation by the linker. +Expressions referencing imported symbols must always be evaluated by the +linker.
+ + +Sometimes, the assembler must know about the size of the value that is the +result of an expression. This is usually the case, if a decision has to be +made, to generate a zero page or an absolute memory references. In this +case, the assembler has to make some assumptions about the result of an +expression:
++
Note: If the assembler is not able to evaluate the expression at assembly +time, the linker will evaluate it and check for range errors as soon as +the result is known.
+ + +In the context of a boolean expression, any non zero value is evaluated as
+true, any other value to false. The result of a boolean expression is 1 if
+it's true, and zero if it's false. There are boolean operators with extreme
+low precedence with version 2.x (where x > 0). The .AND
and .OR
+operators are shortcut operators. That is, if the result of the expression is
+already known, after evaluating the left hand side, the right hand side is
+not evaluated.
Sometimes an expression must evaluate to a constant without looking at any
+further input. One such example is the
+.IF
command
+that decides if parts of the code are assembled or not. An expression used in
+the .IF
command cannot reference a symbol defined later, because the
+decision about the .IF
must be made at the point when it is read. If the
+expression used in such a context contains only constant numerical values,
+there is no problem. When unresolvable symbols are involved it may get harder
+for the assembler to determine if the expression is actually constant, and it
+is even possible to create expressions that aren't recognized as constant.
+Simplifying the expressions will often help.
In cases where the result of the expression is not needed immediately, the +assembler will delay evaluation until all input is read, at which point all +symbols are known. So using arbitrary complex constant expressions is no +problem in most cases.
+ + + +Available operators sorted by precedence:
+
+
+Op | Description | Precedence |
+ | Builtin string functions | 0 |
+ | Builtin pseudo variables | 1 |
+ | Builtin pseudo functions | 1 |
++ | Unary plus | 1 |
+- | Unary minus | 1 |
+~ | Unary bitwise not | 1 |
+.BITNOT | Unary bitwise not | 1 |
+< | Low byte operator | 1 |
+> | High byte operator | 1 |
+^ | Bank byte operator | 1 |
+* | Multiplication | 2 |
+/ | Division | 2 |
+.MOD | Modulo operation | 2 |
+& | Bitwise and | 2 |
+.BITAND | Bitwise and | 2 |
+^ | Bitwise xor | 2 |
+.BITXOR | Bitwise xor | 2 |
+<< | Shift left operator | 2 |
+.SHL | Shift left operator | 2 |
+>> | Shift right operato | r |
+.SHR | Shift right operator | 2 |
++ | Binary plus | 3 |
+- | Binary minus | 3 |
+| | Binary or | 3 |
+.BITOR | Binary or | 3 |
+= | Compare operation (equal) | 4 |
+<> | Compare operation (not equal) | 4 |
+< | Compare operation (less) | 4 |
+> | Compare operation (greater) | 4 |
+<= | Compare operation (less or equal) | 4 |
+>= | Compare operation (greater or equal) | 4 |
+&& | Boolean and | 5 |
+.AND | Boolean and | 5 |
+.XOR | Boolean xor | 5 |
+|| | Boolean or | 6 |
+.OR | Boolean or | 6 |
+! | Boolean not | 7 |
+.NOT | Boolean not | 7 |
+ |
To force a specific order of evaluation, braces may be used as usual.
+ + + + +The assembler allows you to use symbols instead of naked values to make +the source more readable. There are a lot of different ways to define and +use symbols and labels, giving a lot of flexibility.
+ + +Numeric constants are defined using the equal sign or the label assignment +operator. After doing
++
+
+ two = 2
+
+
+
+may use the symbol "two" in every place where a number is expected, and it is +evaluated to the value 2 in this context. The label assignment operator causes +the same, but causes the symbol to be marked as a label, which may cause a +different handling in the debugger:
++
+
+ io := $d000
+
+
+
+The right side can of course be an expression:
++
+
+ four = two * two
+
+
+
+
+
+A label is defined by writing the name of the label at the start of the line +(before any instruction mnemonic, macro or pseudo directive), followed by a +colon. This will declare a symbol with the given name and the value of the +current program counter.
+ + +Using the
+.PROC
directive, it is possible to
+create regions of code where the names of labels and symbols are local to this
+region. They are not known outside of this region and cannot be accessed from
+there. Such regions may be nested like PROCEDUREs in Pascal.
See the description of the
+.PROC
+directive for more information.
Cheap local labels are defined like standard labels, but the name of the
+label must begin with a special symbol (usually '@', but this can be
+changed by the
+.LOCALCHAR
+directive).
Cheap local labels are visible only between two non cheap labels. As soon as a
+standard symbol is encountered (this may also be a local symbol if inside a
+region defined with the
+.PROC
directive), the
+cheap local symbol goes out of scope.
You may use cheap local labels as an easy way to reuse common label +names like "Loop". Here is an example:
++
+
+ Clear: lda #$00 ; Global label
+ ldy #$20
+ @Loop: sta Mem,y ; Local label
+ dey
+ bne @Loop ; Ok
+ rts
+ Sub: ... ; New global label
+ bne @Loop ; ERROR: Unknown identifier!
+
+
+
+
+If you really want to write messy code, there are also unnamed labels. These +labels do not have a name (you guessed that already, didn't you?). A colon is +used to mark the absence of the name.
+Unnamed labels may be accessed by using the colon plus several minus or plus +characters as a label designator. Using the '-' characters will create a back +reference (use the n'th label backwards), using '+' will create a forward +reference (use the n'th label in forward direction). An example will help to +understand this:
++
+
+ : lda (ptr1),y ; #1
+ cmp (ptr2),y
+ bne :+ ; -> #2
+ tax
+ beq :+++ ; -> #4
+ iny
+ bne :- ; -> #1
+ inc ptr1+1
+ inc ptr2+1
+ bne :- ; -> #1
+
+ : bcs :+ ; #2 -> #3
+ ldx #$FF
+ rts
+
+ : ldx #$01 ; #3
+ : rts ; #4
+
+
+
+As you can see from the example, unnamed labels will make even short +sections of code hard to understand, because you have to count labels +to find branch targets (this is the reason why I for my part do +prefer the "cheap" local labels). Nevertheless, unnamed labels are +convenient in some situations, so it's your decision.
+ + +While there are drawbacks with this approach, it may be handy in some
+situations. Using
+.DEFINE
, it is
+possible to define symbols or constants that may be used elsewhere. Since
+the macro facility works on a very low level, there is no scoping. On the
+other side, you may also define string constants this way (this is not
+possible with the other symbol types).
Example:
++
+
+ .DEFINE two 2
+ .DEFINE version "SOS V2.3"
+
+ four = two * two ; Ok
+ .byte version ; Ok
+
+ .PROC ; Start local scope
+ two = 3 ; Will give "2 = 3" - invalid!
+ .ENDPROC
+
+
+
+
+
+.DEBUGINFO
+If
+.DEBUGINFO
is enabled (or
+-g is given on the command line), global, local and
+cheap local labels are written to the object file and will be available in the
+symbol file via the linker. Unnamed labels are not written to the object file,
+because they don't have a name which would allow to access them.
ca65 implements several sorts of scopes for symbols.
+ +All (non cheap local) symbols that are declared outside of any nested scopes +are in global scope.
+ + +A special scope is the scope for cheap local symbols. It lasts from one non +local symbol to the next one, without any provisions made by the programmer. +All other scopes differ in usage but use the same concept internally.
+ + +A nested scoped for generic use is started with
+.SCOPE
and closed with
+.ENDSCOPE
.
+The scope can have a name, in which case it is accessible from the outside by
+using
+explicit scopes. If the scope does not
+have a name, all symbols created within the scope are local to the scope, and
+aren't accessible from the outside.
A nested scope can access symbols from the local or from enclosing scopes by +name without using explicit scope names. In some cases there may be +ambiguities, for example if there is a reference to a local symbol that is not +yet defined, but a symbol with the same name exists in outer scopes:
++
+
+ .scope outer
+ foo = 2
+ .scope inner
+ lda #foo
+ foo = 3
+ .endscope
+ .endscope
+
+
+
+In the example above, the lda
instruction will load the value 3 into the
+accumulator, because foo
is redefined in the scope. However:
+
+
+ .scope outer
+ foo = $1234
+ .scope inner
+ lda foo,x
+ foo = $12
+ .endscope
+ .endscope
+
+
+
+Here, lda
will still load from $12,x
, but since it is unknown to the
+assembler that foo
is a zeropage symbol when translating the instruction,
+absolute mode is used instead. In fact, the assembler will not use absolute
+mode by default, but it will search through the enclosing scopes for a symbol
+with the given name. If one is found, the address size of this symbol is used.
+This may lead to errors:
+
+
+ .scope outer
+ foo = $12
+ .scope inner
+ lda foo,x
+ foo = $1234
+ .endscope
+ .endscope
+
+
+
+In this case, when the assembler sees the symbol foo
in the lda
+instruction, it will search for an already defined symbol foo
. It will
+find foo
in scope outer
, and a close look reveals that it is a
+zeropage symbol. So the assembler will use zeropage addressing mode. If
+foo
is redefined later in scope inner
, the assembler tries to change
+the address in the lda
instruction already translated, but since the new
+value needs absolute addressing mode, this fails, and an error message "Range
+error" is output.
Of course the most simple solution for the problem is to move the definition
+of foo
in scope inner
upwards, so it precedes its use. There may be
+rare cases when this cannot be done. In these cases, you can use one of the
+address size override operators:
+
+
+ .scope outer
+ foo = $12
+ .scope inner
+ lda a:foo,x
+ foo = $1234
+ .endscope
+ .endscope
+
+
+
+This will cause the lda
instruction to be translated using absolute
+addressing mode, which means changing the symbol reference later does not
+cause any errors.
A nested procedure is created by use of
+.PROC
. It
+differs from a
+.SCOPE
in that it must have a
+name, and a it will introduce a symbol with this name in the enclosing scope.
+So
+
+
+ .proc foo
+ ...
+ .endscope
+
+
+
+is actually the same as
++
+
+ foo:
+ .scope foo
+ ...
+ .endscope
+
+
+
+This is the reason why a procedure must have a name. If you want a scope
+without a name, use
+.SCOPE
.
Note: As you can see from the example above, scopes and symbols live in
+different namespaces. There can be a symbol named foo
and a scope named
+foo
without any conflicts (but see the section titled
+"Scope search order").
Structs, unions and enums are explained in a
+separate section, I do only cover them here, because if they are declared with a
+name, they open a nested scope, similar to
+.SCOPE
. However, when no name is specified, the behaviour is
+different: In this case, no new scope will be opened, symbols declared within
+a struct, union, or enum declaration will then be added to the enclosing scope
+instead.
Accessing symbols from other scopes is possible by using an explicit scope
+specification, provided that the scope where the symbol lives in has a name.
+The namespace token (::
) is used to access other scopes:
+
+
+ .scope foo
+ bar: .word 0
+ .endscope
+
+ ...
+ lda foo::bar ; Access foo in scope bar
+
+
+
+The only way to deny access to a scope from the outside is to declare a scope
+without a name (using the
+.SCOPE
command).
A special syntax is used to specify the global scope: If a symbol or scope is +preceded by the namespace token, the global scope is searched:
++
+
+ bar = 3
+
+ .scope foo
+ bar = 2
+ lda #::bar ; Access the global bar (which is 3)
+ .endscope
+
+
+
+
+
+The assembler searches for a scope in a similar way as for a symbol. First, it +looks in the current scope, and then it walks up the enclosing scopes until +the scope is found.
+However, one important thing to note when using explicit scope syntax is, that +a symbol may be accessed before it is defined, but a scope may not be +used without a preceding definition. This means that in the following +example:
++
+
+ .scope foo
+ bar = 3
+ .endscope
+
+ .scope outer
+ lda #foo::bar ; Will load 3, not 2!
+ .scope foo
+ bar = 2
+ .endscope
+ .endscope
+
+
+
+the reference to the scope foo
will use the global scope, and not the
+local one, because the local one is not visible at the point where it is
+referenced.
Things get more complex if a complete chain of scopes is specified:
++
+
+ .scope foo
+ .scope outer
+ .scope inner
+ bar = 1
+ .endscope
+ .endscope
+ .scope another
+ .scope nested
+ lda #outer::inner::bar ; 1
+ .endscope
+ .endscope
+ .endscope
+
+ .scope outer
+ .scope inner
+ bar = 2
+ .endscope
+ .endscope
+
+
+
+When outer::inner::bar
is referenced in the lda
instruction, the
+assembler will first search in the local scope for a scope named outer
.
+Since none is found, the enclosing scope (another
) is checked. There is
+still no scope named outer
, so scope foo
is checked, and finally
+scope outer
is found. Within this scope, inner
is searched, and in
+this scope, the assembler looks for a symbol named bar
.
Please note that once the anchor scope is found, all following scopes
+(inner
in this case) are expected to be found exactly in this scope. The
+assembler will search the scope tree only for the first scope (if it is not
+anchored in the root scope). Starting from there on, there is no flexibility,
+so if the scope named outer
found by the assembler does not contain a
+scope named inner
, this would be an error, even if such a pair does exist
+(one level up in global scope).
Ambiguities that may be introduced by this search algorithm may be removed by
+anchoring the scope specification in the global scope. In the example above,
+if you want to access the "other" symbol bar
, you would have to write:
+
+
+ .scope foo
+ .scope outer
+ .scope inner
+ bar = 1
+ .endscope
+ .endscope
+ .scope another
+ .scope nested
+ lda #::outer::inner::bar ; 2
+ .endscope
+ .endscope
+ .endscope
+
+ .scope outer
+ .scope inner
+ bar = 2
+ .endscope
+ .endscope
+
+
+
+
+
+ca65 assigns each segment and each symbol an address size. This is true, even +if the symbol is not used as an address. You may also think of a value range +of the symbol instead of an address size.
+Possible address sizes are:
++
Since the assembler uses default address sizes for the segments and symbols, +it is usually not necessary to override the default behaviour. In cases, where +it is necessary, the following keywords may be used to specify address sizes:
++
The assembler assigns an address size to each segment. Since the +representation of a label within this segment is "segment start + offset", +labels will inherit the address size of the segment they are declared in.
+The address size of a segment may be changed, by using an optional address
+size modifier. See the
+segment directive
for
+an explanation on how this is done.
The default address size of a segment depends on the memory model used. Since +labels inherit the address size from the segment they are declared in, +changing the memory model is an easy way to change the address size of many +symbols at once.
+ + + + +Pseudo variables are readable in all cases, and in some special cases also +writable.
+ +*
+Reading this pseudo variable will return the program counter at the start +of the current input line.
+Assignment to this variable is possible when
+.FEATURE pc_assignment
is used. Note: You should not use
+assignments to *
, use
+.ORG
instead.
.CPU
+Reading this pseudo variable will give a constant integer value that
+tells which CPU is currently enabled. It can also tell which instruction
+set the CPU is able to translate. The value read from the pseudo variable
+should be further examined by using one of the constants defined by the
+"cpu" macro package (see
+.MACPACK
).
It may be used to replace the .IFPxx pseudo instructions or to construct +even more complex expressions.
+Example:
++
+
+ .macpack cpu
+ .if (.cpu .bitand CPU_ISET_65816)
+ phx
+ phy
+ .else
+ txa
+ pha
+ tya
+ pha
+ .endif
+
+
+
+
+
+
+.PARAMCOUNT
+This builtin pseudo variable is only available in macros. It is replaced by +the actual number of parameters that were given in the macro invocation.
+Example:
++
+
+ .macro foo arg1, arg2, arg3
+ .if .paramcount <> 3
+ .error "Too few parameters for macro foo"
+ .endif
+ ...
+ .endmacro
+
+
+
+
+See section +Macros.
+ + +.TIME
+Reading this pseudo variable will give a constant integer value that +represents the current time in POSIX standard (as seconds since the +Epoch).
+It may be used to encode the time of translation somewhere in the created +code.
+Example:
++
+
+ .dword .time ; Place time here
+
+
+
+
+
+
+.VERSION
+Reading this pseudo variable will give the assembler version according to +the following formula:
+VER_MAJOR*$100 + VER_MINOR*$10 + VER_PATCH
+It may be used to encode the assembler version or check the assembler for +special features not available with older versions.
+Example:
+Version 2.11.1 of the assembler will return $2B1 as numerical constant when
+reading the pseudo variable .VERSION
.
Pseudo functions expect their arguments in parenthesis, and they have a result, +either a string or an expression.
+ + +.BANKBYTE
+The function returns the bank byte (that is, bits 16-23) of its argument. +It works identical to the '^' operator.
+ + + +.BLANK
+Builtin function. The function evaluates its argument in braces and yields +"false" if the argument is non blank (there is an argument), and "true" if +there is no argument. The token list that makes up the function argument +may optionally be enclosed in curly braces. This allows the inclusion of +tokens that would otherwise terminate the list (the closing right +parenthesis). The curly braces are not considered part of the list, a list +just consisting of curly braces is considered to be empty.
+As an example, the .IFBLANK
statement may be replaced by
+
+
+ .if .blank({arg})
+
+
+
+
+
+
+
+.CONCAT
+Builtin string function. The function allows to concatenate a list of string
+constants separated by commas. The result is a string constant that is the
+concatenation of all arguments. This function is most useful in macros and
+when used together with the .STRING
builtin function. The function may
+be used in any case where a string constant is expected.
Example:
++
+
+ .include .concat ("myheader", ".", "inc")
+
+
+
+
+This is the same as the command
++
+
+ .include "myheader.inc"
+
+
+
+
+
+
+.CONST
+Builtin function. The function evaluates its argument in braces and +yields "true" if the argument is a constant expression (that is, an +expression that yields a constant value at assembly time) and "false" +otherwise. As an example, the .IFCONST statement may be replaced by
++
+
+ .if .const(a + 3)
+
+
+
+
+
+
+.HIBYTE
+The function returns the high byte (that is, bits 8-15) of its argument. +It works identical to the '>' operator.
+ + + +.HIWORD
+The function returns the high word (that is, bits 16-31) of its argument.
+See:
+.LOWORD
.IDENT
+The function expects a string as its argument, and converts this argument
+into an identifier. If the string starts with the current
+.LOCALCHAR
, it will be converted into a cheap local
+identifier, otherwise it will be converted into a normal identifier.
Example:
++
+
+ .macro makelabel arg1, arg2
+ .ident (.concat (arg1, arg2)):
+ .endmacro
+
+ makelabel "foo", "bar"
+
+ .word foobar ; Valid label
+
+
+
+
+
+
+.LEFT
+Builtin function. Extracts the left part of a given token list.
+Syntax:
++
+
+ .LEFT (<int expr>, <token list>)
+
+
+
+
+The first integer expression gives the number of tokens to extract from +the token list. The second argument is the token list itself. The token +list may optionally be enclosed into curly braces. This allows the +inclusion of tokens that would otherwise terminate the list (the closing +right paren in the given case).
+Example:
+To check in a macro if the given argument has a '#' as first token +(immediate addressing mode), use something like this:
++
+
+ .macro ldax arg
+ ...
+ .if (.match (.left (1, {arg}), #))
+
+ ; ldax called with immediate operand
+ ...
+
+ .endif
+ ...
+ .endmacro
+
+
+
+
+See also the
+.MID
and
+.RIGHT
builtin functions.
.LOBYTE
+The function returns the low byte (that is, bits 0-7) of its argument. +It works identical to the '<' operator.
+ + + +.LOWORD
+The function returns the low word (that is, bits 0-15) of its argument.
+See:
+.HIWORD
.MATCH
+Builtin function. Matches two token lists against each other. This is +most useful within macros, since macros are not stored as strings, but +as lists of tokens.
+The syntax is
++
+
+ .MATCH(<token list #1>, <token list #2>)
+
+
+
+
+Both token list may contain arbitrary tokens with the exception of the +terminator token (comma resp. right parenthesis) and
++
The token lists may optionally be enclosed into curly braces. This allows +the inclusion of tokens that would otherwise terminate the list (the closing +right paren in the given case). Often a macro parameter is used for any of +the token lists.
+Please note that the function does only compare tokens, not token
+attributes. So any number is equal to any other number, regardless of the
+actual value. The same is true for strings. If you need to compare tokens
+and token attributes, use the
+.XMATCH
function.
Example:
+Assume the macro ASR
, that will shift right the accumulator by one,
+while honoring the sign bit. The builtin processor instructions will allow
+an optional "A" for accu addressing for instructions like ROL
and
+ROR
. We will use the
+.MATCH
function
+to check for this and print and error for invalid calls.
+
+
+ .macro asr arg
+
+ .if (.not .blank(arg)) .and (.not .match ({arg}, a))
+ .error "Syntax error"
+ .endif
+
+ cmp #$80 ; Bit 7 into carry
+ lsr a ; Shift carry into bit 7
+
+ .endmacro
+
+
+
+
+The macro will only accept no arguments, or one argument that must be the +reserved keyword "A".
+See:
+.XMATCH
.MID
+Builtin function. Takes a starting index, a count and a token list as +arguments. Will return part of the token list.
+Syntax:
++
+
+ .MID (<int expr>, <int expr>, <token list>)
+
+
+
+
+The first integer expression gives the starting token in the list (the first +token has index 0). The second integer expression gives the number of tokens +to extract from the token list. The third argument is the token list itself. +The token list may optionally be enclosed into curly braces. This allows the +inclusion of tokens that would otherwise terminate the list (the closing +right paren in the given case).
+Example:
+To check in a macro if the given argument has a '#
' as first token
+(immediate addressing mode), use something like this:
+
+
+ .macro ldax arg
+ ...
+ .if (.match (.mid (0, 1, {arg}), #))
+
+ ; ldax called with immediate operand
+ ...
+
+ .endif
+ ...
+ .endmacro
+
+
+
+
+See also the
+.LEFT
and
+.RIGHT
builtin functions.
.REF, .REFERENCED
+Builtin function. The function expects an identifier as argument in braces.
+The argument is evaluated, and the function yields "true" if the identifier
+is a symbol that has already been referenced somewhere in the source file up
+to the current position. Otherwise the function yields false. As an example,
+the
+.IFREF
statement may be replaced by
+
+
+ .if .referenced(a)
+
+
+
+
+See:
+.DEFINED
.RIGHT
+Builtin function. Extracts the right part of a given token list.
+Syntax:
++
+
+ .RIGHT (<int expr>, <token list>)
+
+
+
+
+The first integer expression gives the number of tokens to extract from the +token list. The second argument is the token list itself. The token list +may optionally be enclosed into curly braces. This allows the inclusion of +tokens that would otherwise terminate the list (the closing right paren in +the given case).
+See also the
+.LEFT
and
+.MID
builtin functions.
.SIZEOF
+.SIZEOF
is a pseudo function that returns the size of its argument. The
+argument can be a struct/union, a struct member, a procedure, or a label. In
+case of a procedure or label, its size is defined by the amount of data
+placed in the segment where the label is relative to. If a line of code
+switches segments (for example in a macro) data placed in other segments
+does not count for the size.
Please note that a symbol or scope must exist, before it is used together with
+.SIZEOF
(this may get relaxed later, but will always be true for scopes).
+A scope has preference over a symbol with the same name, so if the last part
+of a name represents both, a scope and a symbol, the scope is chosen over the
+symbol.
After the following code:
++
+
+ .struct Point ; Struct size = 4
+ xcoord .word
+ xcoord .word
+ .endstruct
+
+ P: .tag Point ; Declare a point
+ @P: .tag Point ; Declare another point
+
+ .code
+ .proc Code
+ nop
+ .proc Inner
+ nop
+ .endproc
+ nop
+ .endproc
+
+ .proc Data
+ .data ; Segment switch!!!
+ .res 4
+ .endproc
+
+
+
+
++
.sizeof(Point)
will have the value 4, because this is the size of struct Point
.
.sizeof(Point::xcoord)
will have the value 2, because this is the size of the member xcoord
+in struct Point
.
.sizeof(P)
will have the value 4, this is the size of the data declared on the same
+source line as the label P
, which is in the same segment that P
+is relative to.
.sizeof(@P)
will have the value 4, see above. The example demonstrates that .SIZEOF
+does also work for cheap local symbols.
.sizeof(Code)
will have the value 3, since this is amount of data emitted into the code
+segment, the segment that was active when Code
was entered. Note that
+this value includes the amount of data emitted in child scopes (in this
+case Code::Inner
).
.sizeof(Code::Inner)
will have the value 1 as expected.
+ +.sizeof(Data)
will have the value 0. Data is emitted within the scope Data
, but since
+the segment is switched after entry, this data is emitted into another
+segment.
.STRAT
+Builtin function. The function accepts a string and an index as +arguments and returns the value of the character at the given position +as an integer value. The index is zero based.
+Example:
++
+
+ .macro M Arg
+ ; Check if the argument string starts with '#'
+ .if (.strat (Arg, 0) = '#')
+ ...
+ .endif
+ .endmacro
+
+
+
+
+
+
+.SPRINTF
+Builtin function. It expects a format string as first argument. The number
+and type of the following arguments depend on the format string. The format
+string is similar to the one of the C printf
function. Missing things
+are: Length modifiers, variable width.
The result of the function is a string.
+Example:
++
+
+ num = 3
+
+ ; Generate an identifier:
+ .ident (.sprintf ("%s%03d", "label", num)):
+
+
+
+
+
+
+.STRING
+Builtin function. The function accepts an argument in braces and converts +this argument into a string constant. The argument may be an identifier, or +a constant numeric value.
+Since you can use a string in the first place, the use of the function may +not be obvious. However, it is useful in macros, or more complex setups.
+Example:
++
+
+ ; Emulate other assemblers:
+ .macro section name
+ .segment .string(name)
+ .endmacro
+
+
+
+
+
+
+.STRLEN
+Builtin function. The function accepts a string argument in braces and +evaluates to the length of the string.
+Example:
+The following macro encodes a string as a pascal style string with +a leading length byte.
++
+
+ .macro PString Arg
+ .byte .strlen(Arg), Arg
+ .endmacro
+
+
+
+
+
+
+.TCOUNT
+Builtin function. The function accepts a token list in braces. The function +result is the number of tokens given as argument. The token list may +optionally be enclosed into curly braces which are not considered part of +the list and not counted. Enclosement in curly braces allows the inclusion +of tokens that would otherwise terminate the list (the closing right paren +in the given case).
+Example:
+The ldax
macro accepts the '#' token to denote immediate addressing (as
+with the normal 6502 instructions). To translate it into two separate 8 bit
+load instructions, the '#' token has to get stripped from the argument:
+
+
+ .macro ldax arg
+ .if (.match (.mid (0, 1, {arg}), #))
+ ; ldax called with immediate operand
+ lda #<(.right (.tcount ({arg})-1, {arg}))
+ ldx #>(.right (.tcount ({arg})-1, {arg}))
+ .else
+ ...
+ .endif
+ .endmacro
+
+
+
+
+
+
+.XMATCH
+Builtin function. Matches two token lists against each other. This is +most useful within macros, since macros are not stored as strings, but +as lists of tokens.
+The syntax is
++
+
+ .XMATCH(<token list #1>, <token list #2>)
+
+
+
+
+Both token list may contain arbitrary tokens with the exception of the +terminator token (comma resp. right parenthesis) and
++
The token lists may optionally be enclosed into curly braces. This allows +the inclusion of tokens that would otherwise terminate the list (the closing +right paren in the given case). Often a macro parameter is used for any of +the token lists.
+The function compares tokens and token values. If you need a function
+that just compares the type of tokens, have a look at the
+.MATCH
function.
See:
+.MATCH
+
+
+
+
+
.DEBUGINFO
++
+
+
+
.BANKBYTE
+.BLANK
+.CONCAT
+.CONST
+.HIBYTE
+.HIWORD
+.IDENT
+.LEFT
+.LOBYTE
+.LOWORD
+.MATCH
+.MID
+.REF, .REFERENCED
+.RIGHT
+.SIZEOF
+.STRAT
+.SPRINTF
+.STRING
+.STRLEN
+.TCOUNT
+.XMATCH
++
.A16
+.A8
+.ADDR
+.ALIGN
+.ASCIIZ
+.ASSERT
+.AUTOIMPORT
+.BSS
+.BYT, .BYTE
+.CASE
+.CHARMAP
+.CODE
+.CONDES
+.CONSTRUCTOR
+.DATA
+.DBYT
+.DEBUGINFO
+.DEFINE
+.DEF, .DEFINED
+.DESTRUCTOR
+.DWORD
+.ELSE
+.ELSEIF
+.END
+.ENDENUM
+.ENDIF
+.ENDMAC, .ENDMACRO
+.ENDPROC
+.ENDREP, .ENDREPEAT
+.ENDSCOPE
+.ENDSTRUCT
+.ENUM
+.ERROR
+.EXITMAC, .EXITMACRO
+.EXPORT
+.EXPORTZP
+.FARADDR
+.FEATURE
+.FILEOPT, .FOPT
+.FORCEIMPORT
+.GLOBAL
+.GLOBALZP
+.I16
+.I8
+.IF
+.IFBLANK
+.IFCONST
+.IFDEF
+.IFNBLANK
+.IFNDEF
+.IFNREF
+.IFP02
+.IFP816
+.IFPC02
+.IFPSC02
+.IFREF
+.IMPORT
+.IMPORTZP
+.INCBIN
+.INCLUDE
+.INTERRUPTOR
+.LINECONT
+.LIST
+.LISTBYTES
+.LOCAL
+.LOCALCHAR
+.MACPACK
+.MAC, .MACRO
+.ORG
+.OUT
+.P02
+.P816
+.PAGELEN, .PAGELENGTH
+.PC02
+.POPSEG
+.PROC
+.PSC02
+.PUSHSEG
+.RELOC
+.REPEAT
+.RES
+.RODATA
+.SCOPE
+.SEGMENT
+.SETCPU
+.SMART
+.STRUCT
+.SUNPLUS
+.TAG
+.WARNING
+.WORD
+.ZEROPAGE
++
+
+
+
+
+
+
+
ca65html converts assembler source files written for use with the
+ca65
crossassembler into HTML. It is a standalone
+tool written in Perl, and as such it does not understand the structure of
+assembler sources in the same depth as ca65 does, so it may fail in very rare
+cases. In all other cases it generates very nice output.
The HTML converter accepts the following options:
++
+
+---------------------------------------------------------------------------
+Usage: ca65html [options] file ...
+Options:
+ --bgcolor c Use background color c instead of #FFFFFF
+ --colorize Colorize the output (generates non standard HTML)
+ --commentcolor c Use color c for comments instead of #B22222
+ --crefs Generate references to the C source file(s)
+ --ctrlcolor c Use color c for directives instead of #228B22
+ --cvttabs Convert tabs to spaces in the output
+ --help This text
+ --htmldir dir Specify directory for HTML files
+ --indexcols n Use n columns on index page (default 6)
+ --indexname file Use file for the index file instead of index.html
+ --indexpage Create an index page
+ --indextitle title Use title as the index title instead of Index
+ --keywordcolor c Use color c for keywords instead of #A020F0
+ --linelabels Generate a linexxx HTML label for each line
+ --linenumbers Add line numbers to the output
+ --linkstyle style Use the given link style
+ --replaceext Replace source extension instead of appending .html
+ --textcolor c Use text color c instead of #000000
+ --verbose Be more verbose
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
--bgcolor c
Set the background color. The argument c must be a valid HTML color, usually
+given as RGB triplet in the form #rrggbb
, where r, g and b are the
+respective red, green and blue parts as two digit hex values. The default is
+#FFFFFF
(white). This color is used in the <body>
tag of the
+generated HTML output.
--colorize
Colorize the output. The converter outputs processor instructions, assembler +control commands and comments in different colors.
+While this make the output look very nice, it generates invalid HTML,
+because using colors in a <pre>
environment is not allowed.
+However, most browsers display it well, and it is used by several other
+tools, so it's up to you.
--commentcolor c
Set the color used for comments. The argument c must be a valid HTML color,
+usually given as RGB triplet in the form #rrggbb
, where r, g and b are
+the respective red, green and blue parts as two digit hex values. The
+default is #B22222
(red).
Note that this option has no effect if --colorize
is not also given.
--crefs
Generate references to the C file, when a .dbg
command is found with a
+file name. The converter assumes that the C source was also converted into
+HTML (for example by use of c2html
), has the name file.c.html
, and
+lives in the same directory as the assembler file. If the .dbg
+directive specifies a line, a link to the correct line in the C file is
+generated, using a label in the form linexxx
, as it is created by
+c2html
by use of the -n
option.
--commentcolor c
Set the color used for assembler control commands. The argument c must be a
+valid HTML color, usually given as RGB triplet in the form #rrggbb
,
+where r, g and b are the respective red, green and blue parts as two digit
+hex values. The default is #228B22
(green).
Note that this option has no effect if --colorize
is not also given.
--cvttabs
Convert tabs in the input into spaces in the output, assuming the standard
+tab width of 8. This is useful if the --linenumbers
option is used to
+retain the indentation.
--help
Print the command line option summary shown above.
+ + +--htmldir dir
Specify an output directory for the generated HTML files.
+ + +--indexcols n
Use n columns on the index page. This option has no effect if used without
+--indexpage
.
--indexname name
Use another index file name instead of index.html
. This option has no
+effect if used without --indexpage
.
--indexpage
Causes the converter to generate an index page listing all label names and +exports found in the converted files.
+ + +--indextitle title
Use "title" as the title of the index page. This option has no effect if
+used without --indexpage
.
--keywordcolor c
Set the color used for processor instructions. The argument c must be a
+valid HTML color, usually given as RGB triplet in the form #rrggbb
,
+where r, g and b are the respective red, green and blue parts as two digit
+hex values. The default is #A020F0
(purple).
Note that this option has no effect if --colorize
is not also given.
--linelabels
Generate a label for each line using the name linexxx
where xxx is the
+number of the line.
Note: The converter will not make use of this label. Use this option if you +have other HTML pages referencing the converted assembler file.
+ + +--linenumbers
Generate line numbers on the left side of the output.
+ + +--linkstyle n
Influences the style used when generating links for imports. If n is zero
+(the default), the converter creates a link to the actual symbol if it is
+defined somewhere in the input files. If not, it creates a link to the
+.import
statement. If n is one, the converter will always generate a
+HTML link to .import
statement.
--replaceext
Replace the file extension of the input file instead of appending .html
+when generating the output file name.
--textcolor c
Set the color for normal text. The argument c must be a valid HTML color,
+usually given as RGB triplet in the form #rrggbb
, where r, g and b are
+the respective red, green and blue parts as two digit hex values. The
+default is #000000
(black). This color is used in the <body>
+tag of the generated HTML output.
--verbose
Increase the converter verbosity. Without this option, ca65html is quiet +when working. If you have a slow machine and lots of files to convert, you +may like a little bit more progress information.
+ +Since ca65html is able to generate links between modules, the best way to use +it is to supply all modules to it in one run, instead of running each file +separately through it.
+ + +For now, ca65html will not read files included with .include
. Specifying
+the include files as normal input files on the command line works in many
+cases.
Since ca65html does not really parse the input, but does most of its work +applying text patterns, it doesn't know anything about scoping and advanced +features of the assembler. This means that it may miss a label may choose the +wrong color for an item in rare cases. Since it's just a tool for displaying +sources in a nice form, I think that's ok. Anyway, if you find a conversion +problem, you can send me a short piece of example input code. If possible, I +will fix it.
+ + +While having colors in the output looks really nice, it has two drawbacks:
++
<font>
+tags are use in a <pre>
environment. This works with all browsers
+I've tested, but it may not work with the one you're using.
+<font>
tags are created in the output, the size
+of the output file will literally explode. This seems to be the price, you
+have to pay for color...
+If you have problems using the converter, if you find any bugs, or if you're +doing something interesting with the assembler, I would be glad to hear from +you. Feel free to contact me by email ( +uz@cc65.org).
+ + + +ca65html is (C) Copyright 2000-2003 Ullrich von Bassewitz. For its use the +following conditions apply:
+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:
++
+
+
+
+
+
This file contains an overview of the CBM 610 runtime system as it comes with +the cc65 C compiler. It describes the memory layout, CBM 610 specific header +files, available drivers, and any pitfalls specific to that platform.
+Please note that CBM 610 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+In addition to the Commodore 610 (named B40 in the U.S.), several other +machines are supported by this cc65 target, since they have identical +hardware: The Commodore 620 and 630 (more memory, additional coprocessor +card), and the Commodore 710, 720 and 730 (same hardware in another case with +a builtin monitor).
+ + + +The standard binary output format generated by the linker for the CBM610 +target is a machine language program with a short BASIC stub. This means that +a program can be loaded as BASIC program and started with RUN. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ + +cc65 generated programs for the Commodore 610 run in bank 1, the memory bank +reserved for BASIC programs. Since there are no ROMs in this memory bank, the +program has almost full 64K for its own. A disadvantage is that kernal +subroutines cannot be called (at least not in a fast and effective manner), so +the runtime has replace kernal functionality.
+The default memory configuration for the CBM 610 allocates all memory between +$0002 and $FFF0 in bank 1 for the compiled program. Some space +in low memory is lost, because a separate hardware stack is set up in page 1, +and the kernal replacement functions need some more memory locations. A few +more bytes are lost in high memory, because the runtime sets up a CBM +compatible jump table at $FF81. The main startup code is located at +$0400, so about 63K of the complete bank are actually usable for +applications.
+Special locations:
++
The C runtime stack is located at $FF81 and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+Programs containing CBM 610 specific code may use the cbm610.h
or
+cbm.h
header files. Using the later may be an option when writing code
+for more than one CBM platform, since it includes cbm610.h
and declares
+several functions common to all CBM platforms.
The functions listed below are special for the CBM 610. See the +function reference for declaration and usage.
++
Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
+ ++
The following pseudo variables declared in the cbm610.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.
Note: All I/O chips are located in the system bank (bank 15) and can
+therefore not be accessed like on other platforms. Please use one of the
+peekbsys
, peekwsys
, pokebsys
and pokewsys
functions to
+access the I/O chips. Direct reads and writes to the structures named below
+will not work!
+
CRTC
The CRTC
structure allows access to the CRTC (the video controller).
+See the _6545.h
header file located in the include directory for the
+declaration of the structure.
SID
The SID
structure allows access to the SID (the
+sound interface device). See the _sid.h
header file located in the
+include directory for the declaration of the structure.
ACIA
Access to the ACIA (the RS232 chip) is available via the ACIA
variable.
+See the _6551.h
header file located in the include directory for the
+declaration of the structure.
CIA
Access to the CIA chip is available via the CIA
variable. See the
+_6526.h
header file located in the include directory for the
+declaration of the structure.
TPI1, TPI2
The two 6525 triport chips may be accessed by using this variable. See the
+_6525.h
header file located in the include directory for the
+declaration of the structure.
No graphics drivers are currently available for the Commodore 610 (and since +the machine has no graphics capabilities, chances for a graphics driver aren't +really good:-).
+ + ++
cbm610-ram.emd
A driver for the RAM in bank 2. Supports up to 255 pages with 256 bytes +each.
+The Commodore 610 is a business machine and doesn't have joystick ports. There +are no drivers for the non existing ports available.
+ + + +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + ++
cbm610-std.ser
Driver for the 6551 ACIA chip built into the Commodore 610. Supports up to +19200 baud, hardware flow control (RTS/CTS) and interrupt driven receives. +Note that because of the peculiarities of the 6551 chip transmits are not +interrupt driven, and the transceiver blocks if the receiver asserts flow +control because of a full buffer.
+ +Since the program runs in bank 1, and the kernal and all I/O chips are located +in bank 15, calling ROM routines or accessing hardware needs special code. The +cc65 runtime implements wrappers for all functions in the kernal jump table. +While this simplifies things, it should be noted that the wrappers do have +quite an impact on performance: A cross bank call has an extra 300µs +penalty added by the wrapper.
+ +Compiled programs contain an interrupt handler that runs in the program bank. +This has several advantages, one of them being performance (see cross bank +call overhead mentioned above). However, this introduces one problem: +Interrupts are lost while the CPU executes code in the kernal bank. As a +result, the clock may go wrong and (worse) serial interrupts may get lost.
+Since the cc65 runtime does only call the kernal for disk I/O, this means that +a program should not do file I/O while it depends on interrupts.
+ + +Command line argument passing is currently not supported for the Commodore +610.
+ + +The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The runtime for the Commodore 610 uses routines marked as .CONDES
type 2
+for interrupt handlers. Such routines must be written as simple machine
+language subroutines and will be called automatically by the interrupt handler
+code when they are linked into a program. See the discussion of the
+.CONDES
feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
cc65 was originally a C compiler for the Atari 8-bit machines written by +John R. Dunning. In prior releases I've described the compiler by listing +up the changes made by me. I have made many more changes in the meantime +(and rewritten major parts of the compiler), so I will no longer do that, +since the list would be too large and of no use to anyone. Instead I will +describe the compiler in respect to the ANSI/ISO C standard. In fact, I'm +planning a complete rewrite (that is, a complete new compiler) for the +next release, since there are too many limitations in the current code, +and removing these limitations would mean a rewrite of many more parts of +the compiler.
+There are separate documents named +library.html and +funcref.html that cover the library that is available for the compiler. +If you know C, and are interested in doing actual programming, the library +documentation is probably of much more use than this document.
+If you need some hints for getting the best code out of the compiler, you +may have a look at +coding.html which covers some code generation +issues.
+ + + +If you have problems using the compiler, 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 ( +uz@cc65.org).
+ + + +This is the original compiler copyright:
++
+
+--------------------------------------------------------------------------
+ -*- Mode: Text -*-
+
+ This is the copyright notice for RA65, LINK65, LIBR65, and other
+ Atari 8-bit programs. Said programs are Copyright 1989, by John R.
+ Dunning. All rights reserved, with the following exceptions:
+
+ Anyone may copy or redistribute these programs, provided that:
+
+ 1: You don't charge anything for the copy. It is permissable to
+ charge a nominal fee for media, etc.
+
+ 2: All source code and documentation for the programs is made
+ available as part of the distribution.
+
+ 3: This copyright notice is preserved verbatim, and included in
+ the distribution.
+
+ You are allowed to modify these programs, and redistribute the
+ modified versions, provided that the modifications are clearly noted.
+
+ There is NO WARRANTY with this software, it comes as is, and is
+ distributed in the hope that it may be useful.
+
+ This copyright notice applies to any program which contains
+ this text, or the refers to this file.
+
+ This copyright notice is based on the one published by the Free
+ Software Foundation, sometimes known as the GNU project. The idea
+ is the same as theirs, ie the software is free, and is intended to
+ stay that way. Everybody has the right to copy, modify, and re-
+ distribute this software. Nobody has the right to prevent anyone
+ else from copying, modifying or redistributing it.
+
+--------------------------------------------------------------------------
+
+
+
+Small parts of the compiler (parts of the preprocessor and main parser) are +still covered by this copyright. The main portion is covered by the usual +cc65 license, which reads:
+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:
++
The compiler translates C files into files containing assembly code that +may be translated by the ca65 macroassembler (for more information about +the assembler, have a look at +ca65.html).
+ + +The compiler may be called as follows:
++
+
+---------------------------------------------------------------------------
+Usage: cc65 [options] file
+Short options:
+ -Cl Make local variables static
+ -Dsym[=defn] Define a symbol
+ -I dir Set an include directory search path
+ -O Optimize code
+ -Oi Optimize code, inline more code
+ -Or Enable register variables
+ -Os Inline some known functions
+ -T Include source as comment
+ -V Print the compiler version number
+ -W Suppress warnings
+ -d Debug mode
+ -g Add debug info to object file
+ -h Help (this text)
+ -j Default characters are signed
+ -o name Name the output file
+ -r Enable register variables
+ -t sys Set the target system
+ -v Increase verbosity
+
+Long options:
+ --add-source Include source as comment
+ --bss-name seg Set the name of the BSS segment
+ --check-stack Generate stack overflow checks
+ --code-name seg Set the name of the CODE segment
+ --codesize x Accept larger code by factor x
+ --cpu type Set cpu type
+ --create-dep Create a make dependency file
+ --data-name seg Set the name of the DATA segment
+ --debug Debug mode
+ --debug-info Add debug info to object file
+ --forget-inc-paths Forget include search paths
+ --help Help (this text)
+ --include-dir dir Set an include directory search path
+ --register-space b Set space available for register variables
+ --register-vars Enable register variables
+ --rodata-name seg Set the name of the RODATA segment
+ --signed-chars Default characters are signed
+ --standard std Language standard (c89, c99, cc65)
+ --static-locals Make local variables static
+ --target sys Set the target system
+ --verbose Increase verbosity
+ --version Print the compiler version number
+ --writable-strings Make string literals writable
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
--bss-name seg
Set the name of the bss segment.
+ + +--check-stack
Tells the compiler to generate code that checks for stack overflows. See
+
+#pragma checkstack
for an
+explanation of this feature.
--code-name seg
Set the name of the code segment.
+ + +--codesize x
This options allows finer control about speed vs. size decisions in the code
+generation and optimization phases. It gives the allowed size increase
+factor (in percent). The default is 100 when not using -Oi
and 200 when
+using -Oi
(-Oi
is the same as --codesize 200
).
--cpu CPU
A new, still experimental option. You may specify "6502" or "65C02" as +the CPU. 6502 is the default, so this will not change anything. +Specifying 65C02 will use a few 65C02 instructions when generating code. +Don't expect too much from this option: It is still new (and may have +bugs), and the additional instructions for the 65C02 are not that +overwhelming.
+ + +--create-dep
Tells the compiler to generate a file containing the dependency list for
+the compiled module in makefile syntax. The file is named as the C input
+file with the extension replaced by .u
.
-d, --debug
Enables debug mode, something that should not be needed for mere +mortals:-)
+ + +-D sym[=definition]
Define a macro on the command line. If no definition is given, the macro +is defined to the value "1".
+ + +--forget-inc-paths
Forget the builtin include paths. This is most useful when building +customized C or runtime libraries, in which case the standard header +files should be ignored.
+ + +-g, --debug-info
This will cause the compiler to insert a .DEBUGINFO
command into the
+generated assembler code. This will cause the assembler to include all
+symbols in a special section in the object file.
-h, --help
Print the short option summary shown above.
+ + +-o name
Specify the name of the output file. If you don't specify a name, the +name of the C input file is used, with the extension replaced by ".s".
+ + +-r, --register-vars
-r
will make the compiler honor the register
keyword. Local
+variables may be placed in registers (which are actually zero page
+locations). There is some overhead involved with register variables, since
+the old contents of the registers must be saved and restored. Since register
+variables are of limited use without the optimizer, there is also a combined
+switch: -Or
will enable both, the optimizer and register variables.
For more information about register variables see +register variables.
+The compiler setting can also be changed within the source file by using
+
+#pragma regvars
.
--register-space
This option takes a numeric parameter and is used to specify, how much +zero page register space is available. Please note that just giving this +option will not increase or decrease by itself, it will just tell the +compiler about the available space. You will have to allocate that space +yourself using an assembler module with the necessary allocations, and a +linker configuration that matches the assembler module. The default value +for this option is 6 (bytes).
+If you don't know what all this means, please don't use this option.
+ + +--rodata-name seg
Set the name of the rodata segment (the segment used for readonly data).
+ + +-j, --signed-chars
Using this option, you can make the default characters signed. Since the
+6502 has no provisions for sign extending characters (which is needed on
+almost any load operation), this will make the code larger and slower. A
+better way is to declare characters explicitly as "signed" if needed. You
+can also use
+#pragma signedchars
for better control of this option.
--standard std
This option allows to set the language standard supported. The argument is +one of +
-t target, --target target
This option is used to set the target system. The target system +determines things like the character set that is used for strings and +character constants. The following target systems are supported:
++
-v, --verbose
Using this option, the compiler will be somewhat more verbose if errors +or warnings are encountered.
+ + +--writable-strings
Make string literals writable by placing them into the data segment instead +of the rodata segment.
+ + +-Cl, --static-locals
Use static storage for local variables instead of storage on the stack.
+Since the stack is emulated in software, this gives shorter and usually
+faster code, but the code is no longer reentrant. The difference between
+-Cl
and declaring local variables as static yourself is, that
+initializer code is executed each time, the function is entered. So when
+using
+
+
+ void f (void)
+ {
+ unsigned a = 1;
+ ...
+ }
+
+
+
+
+the variable a
will always have the value 1
when entering the
+function and using -Cl
, while in
+
+
+ void f (void)
+ {
+ static unsigned a = 1;
+ ....
+ }
+
+
+
+
+the variable a
will have the value 1
only the first time that the
+function is entered, and will keep the old value from one call of the
+function to the next.
You may also use
+#pragma staticlocals
to change this setting in your
+sources.
-I dir, --include-dir dir
Set a directory where the compiler searches for include files. You may +use this option multiple times to add more than one directory to the +search list.
+ + +-O, -Oi, -Or, -Os
Enable an optimizer run over the produced code.
+Using -Oi
, the code generator will inline some code where otherwise a
+runtime functions would have been called, even if the generated code is
+larger. This will not only remove the overhead for a function call, but will
+make the code visible for the optimizer. -Oi
is an alias for
+--codesize 200
.
-Or
will make the compiler honor the register
keyword. Local
+variables may be placed in registers (which are actually zero page
+locations). There is some overhead involved with register variables, since
+the old contents of the registers must be saved and restored. In addition,
+the current implementation does not make good use of register variables, so
+using -Or
may make your program even slower and larger. Use with care!
Using -Os
will force the compiler to inline some known functions from
+the C library like strlen. Note: This has two consequences:
+
-Os
will actually break things.
+
+is..()
+functions will not work with values outside the char. range (such as
+EOF
).
+
+It is possible to concatenate the modifiers for -O
. For example, to
+enable register variables and inlining of known functions, you may use
+-Ors
.
-T, --add-source
This include the source code as comments in the generated code. This is +normally not needed.
+ + +-V, --version
Print the version number of the compiler. When submitting a bug report, +please include the operating system you're using, and the compiler +version.
+ + +-W
This option will suppress any warnings generated by the compiler. Since +any source file may be written in a manner that it will not produce +compiler warnings, using this option is usually not a good idea.
+ +The compiler will accept one C file per invocation and create a file with +the same base name, but with the extension replaced by ".s". The output +file contains assembler code suitable for the use with the ca65 macro +assembler.
+In addition to the paths named in the -I
option on the command line, the
+directory named in the environment variable CC65_INC
is added to the
+search path for include files on startup.
Here is a list of differences between the language, the compiler accepts, +and the one defined by the ISO standard:
++
+--standard
command line option.
+
++
asm
__asm__
fastcall
__fastcall__
__AX__
__EAX__
__func__
__attribute__
The keywords without the underlines can be disabled with the
+
+--standard
command line
+option.
There may be some more minor differences I'm currently not aware of. The +biggest problem is the missing float data type. With this limitation in +mind, you should be able to write fairly portable code.
+ + + +This cc65 version has some extensions to the ISO C standard.
++
+
+ asm (<string literal>[, optional parameters]) ;
+
+
+
+
+or
+
+
+ __asm__ (<string literal>[, optional parameters]) ;
+
+
+
+
+
+The first form is in the user namespace and is disabled if the -A
+switch is given.
+
+There is a whole section covering inline assembler statements,
+see there.
+
+
+
+
+ <return type> fastcall <function name> (<parameter list>)
+
+
+
+
+or
+
+
+ <return type> __fastcall__ <function name> (<parameter list>)
+
+
+
+
+An example would be
+
+
+ void __fastcall__ f (unsigned char c)
+
+
+
+
+The first form of the fastcall keyword is in the user namespace and can
+therefore be disabled with the
+--standard
command line option.
+
+For functions declared as fastcall
, the rightmost parameter is not
+pushed on the stack but left in the primary register when the function
+is called. This will reduce the cost when calling assembler functions
+significantly, especially when the function itself is rather small.
+
+
+__AX__
and __EAX__
.
+Both refer to the primary register that is used by the compiler to
+evaluate expressions or return function results. __AX__
is of
+type unsigned int
and __EAX__
of type long unsigned int
+respectively. The pseudo variables may be used as lvalue and rvalue as
+every other variable. They are most useful together with short
+sequences of assembler code. For example, the macro
+
+
+
+ #define hi(x) \
+ (__AX__ = (x), \
+ asm ("txa"), \
+ asm ("ldx #$00"), \
+ __AX__)
+
+
+
+
+
+will give the high byte of any unsigned value.
+
+
+__func__
gives the name of the
+current function as a string. Outside of functions, __func__
is
+undefined.
+Example:
+
+
+
+ #define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s);
+
+
+
+
+
+The macro will print the name of the current function plus a given
+string.
+
+
+void
variables. This may be
+used to create variable structures that are more compatible with
+interfaces written for assembler languages. Here is an example:
+
+
+
+ void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 };
+
+
+
+
+
+This will be translated as follows:
+
+
+
+ _GCmd:
+ .byte 3
+ .word $2000
+ .word $3000
+
+
+
+
+
+Since the variable is of type void
you may not use it as is.
+However, taking the address of the variable results in a void*
+which may be passed to any function expecting a pointer.
+
+See the
+GEOS library document for examples
+on how to use this feature.
+
+
+register
, and the size and compiler settings
+do allow the compiler actually to place the struct into the
+register bank in the zero page.sizeof
+operator returns the struct size with the flexible array member having
+size zero, even if it is initialized.
+
+
+The compiler defines several macros at startup:
++
__CC65__
This macro is always defined. Its value is the version number of the
+compiler in hex. For example, version 2.10.1 of the compiler has this macro
+defined as 0x02A1
.
__APPLE2__
This macro is defined if the target is the Apple ][ (-t apple2).
+ +__APPLE2ENH__
This macro is defined if the target is the enhanced Apple // (-t apple2enh).
+ +__ATARI__
This macro is defined if the target is one of the Atari computers +(400/800/130XL/800XL).
+ +__ATMOS__
This macro is defined if the target is the Oric Atmos (-t atmos).
+ +__CBM__
This macro is defined if the target system is one of the CBM targets.
+ +__C16__
This macro is defined if the target is the c16 (-t c16).
+ +__C64__
This macro is defined if the target is the c64 (-t c64).
+ +__C128__
This macro is defined if the target is the c128 (-t c128).
+ +__CBM510__
This macro is defined if the target is the CBM 500 series of computers.
+ +__CBM610__
This macro is defined if the target is one of the CBM 600/700 family of +computers (called B series in the US).
+ +__GEOS__
This macro is defined if you are compiling for the GEOS system (-t geos).
+ +__LUNIX__
This macro is defined if you are compiling for the LUnix system (-t lunix).
+ +__LYNX__
This macro is defined if the target is the Atari Lynx (-t lynx).
+ +__NES__
This macro is defined if the target is the NES (-t nes).
+ +__PET__
This macro is defined if the target is the PET family of computers (-t pet).
+ +__PLUS4__
This macro is defined if the target is the plus/4 (-t plus4).
+ +__SUPERVISION__
This macro is defined if the target is the supervision (-t supervision).
+ +__VIC20__
This macro is defined if the target is the vic20 (-t vic20).
+ +__FILE__
This macro expands to a string containing the name of the C source file.
+ +__LINE__
This macro expands to the current line number.
+ +__CC65_STD__
This macro is defined to one of the following depending on the
+--standard
command line option:
+
__CC65_STD_C89__
__CC65_STD_C99__
__CC65_STD_CC65__
__OPT__
Is defined if the compiler was called with the -O
command line option.
__OPT_i__
Is defined if the compiler was called with the -Oi
command line option.
__OPT_r__
Is defined if the compiler was called with the -Or
command line option.
__OPT_s__
Is defined if the compiler was called with the -Os
command line option.
The compiler understands some pragmas that may be used to change code
+generation and other stuff. Some of these pragmas understand a special form:
+If the first parameter is push
, the old value is saved onto a stack
+before changing it. The value may later be restored by using the pop
+parameter with the #pragma
.
#pragma bssseg ([push,]<name>)
+This pragma changes the name used for the BSS segment (the BSS segment +is used to store uninitialized data). The argument is a string enclosed +in double quotes.
+Note: The default linker configuration file does only map the standard +segments. If you use other segments, you have to create a new linker +configuration file.
+Beware: The startup code will zero only the default BSS segment. If you +use another BSS segment, you have to do that yourself, otherwise +uninitialized variables do not have the value zero.
+The #pragma
understands the push and pop parameters as explained above.
Example: +
+
+ #pragma bssseg ("MyBSS")
+
+
+
+
+
+
+#pragma charmap (<index>, <code>)
+Each literal string and each literal character in the source is translated +by use of a translation table. This translation table is preset when the +compiler is started depending on the target system, for example to map +ISO-8859-1 characters into PETSCII if the target is a commodore machine.
+This pragma allows to change entries in the translation table, so the +translation for individual characters, or even the complete table may be +adjusted.
+Both arguments are assumed to be unsigned characters with a valid range of +1-255.
+Beware of two pitfalls:
++
#pragma charmap
is not
+portable -- it depends on the build environment.Example: +
+
+ /* Use a space wherever an 'a' occurs in ISO-8859-1 source */
+ #pragma charmap (0x61, 0x20);
+
+
+
+
+
+
+#pragma checkstack ([push,]on|off)
+Tells the compiler to insert calls to a stack checking subroutine to detect +stack overflows. The stack checking code will lead to somewhat larger and +slower programs, so you may want to use this pragma when debugging your +program and switch it off for the release version. If a stack overflow is +detected, the program is aborted.
+If the argument is "off", stack checks are disabled (the default), otherwise +they're enabled.
+The #pragma
understands the push and pop parameters as explained above.
#pragma codeseg ([push,]<name>)
+This pragma changes the name used for the CODE segment (the CODE segment +is used to store executable code). The argument is a string enclosed in +double quotes.
+Note: The default linker configuration file does only map the standard +segments. If you use other segments, you have to create a new linker +configuration file.
+The #pragma
understands the push and pop parameters as explained above.
Example: +
+
+ #pragma codeseg ("MyCODE")
+
+
+
+
+
+
+#pragma codesize ([push,]<int>)
+This pragma allows finer control about speed vs. size decisions in the code
+generation and optimization phase. It gives the allowed size increase factor
+(in percent). The default is can be changed by use of the
+--codesize
compiler option.
The #pragma
understands the push and pop parameters as explained above.
#pragma dataseg ([push,]<name>)
+This pragma changes the name used for the DATA segment (the DATA segment +is used to store initialized data). The argument is a string enclosed in +double quotes.
+Note: The default linker configuration file does only map the standard +segments. If you use other segments, you have to create a new linker +configuration file.
+The #pragma
understands the push and pop parameters as explained above.
Example: +
+
+ #pragma dataseg ("MyDATA")
+
+
+
+
+
+
+#pragma optimize ([push,]on|off)
+Switch optimization on or off. If the argument is "off", optimization is +disabled, otherwise it is enabled. Please note that this pragma only effects +whole functions. The setting in effect when the function is encountered will +determine if the generated code is optimized or not.
+Optimization and code generation is also controlled by the +codesize pragma.
+The default is "off", but may be changed with the
+-O
compiler option.
The #pragma
understands the push and pop parameters as explained above.
#pragma rodataseg ([push,]<name>)
+This pragma changes the name used for the RODATA segment (the RODATA +segment is used to store readonly data). The argument is a string +enclosed in double quotes.
+Note: The default linker configuration file does only map the standard +segments. If you use other segments, you have to create a new linker +configuration file.
+The #pragma
understands the push and pop parameters as explained above.
Example: +
+
+ #pragma rodataseg ("MyRODATA")
+
+
+
+
+
+
+#pragma regvaraddr ([push,]on|off)
+The compiler does not allow to take the address of register variables. +The regvaraddr pragma changes this. Taking the address of a register +variable is allowed after using this pragma with "on" as argument. +Using "off" as an argument switches back to the default behaviour.
+Beware: The C standard does not allow taking the address of a variable +declared as register. So your programs become non-portable if you use +this pragma. In addition, your program may not work. This is usually the +case if a subroutine is called with the address of a register variable, +and this subroutine (or a subroutine called from there) uses +register variables. So be careful with this #pragma.
+The #pragma
understands the push and pop parameters as explained above.
Example: +
+
+ #pragma regvaraddr(on) /* Allow taking the address
+ * of register variables
+ */
+
+
+
+
+
+
+#pragma regvars ([push,]on|off)
+Enables or disables use of register variables. If register variables are
+disabled (the default), the register
keyword is ignored. Register
+variables are explained in more detail in
+a separate chapter.
The #pragma
understands the push and pop parameters as explained above.
#pragma signedchars ([push,]on|off)
+Changes the signedness of the default character type. If the argument is
+"on", default characters are signed, otherwise characters are unsigned.
+The compiler default is to make characters unsigned since this creates a
+lot better code. This default may be overridden by the --signed-chars
+command line option.
The #pragma
understands the push and pop parameters as explained above.
#pragma staticlocals ([push,]on|off)
+Use variables in the bss segment instead of variables on the stack. This
+pragma changes the default set by the compiler option -Cl
. If the
+argument is "on", local variables are allocated in the BSS segment,
+leading to shorter and in most cases faster, but non-reentrant code.
The #pragma
understands the push and pop parameters as explained above.
#pragma warn ([push,]on|off)
+Switch compiler warnings on or off. If the argument is "off", warnings are
+disabled, otherwise they're enabled. The default is "on", but may be changed
+with the
+-W
compiler option.
The #pragma
understands the push and pop parameters as explained above.
#pragma zpsym (<name>)
+Tell the compiler that the -- previously as external declared -- symbol with +the given name is a zero page symbol (usually from an assembler file). +The compiler will create a matching import declaration for the assembler.
+Example: +
+
+ extern int foo;
+ #pragma zpsym ("foo"); /* foo is in the zeropage */
+
+
+
+
+
+
+
+
+The runtime for all supported platforms has 6 bytes of zero page space
+available for register variables (this could be increased, but I think it's a
+good value). So you can declare register variables up to a total size of 6 per
+function. The compiler will allocate register space on a "first come, first
+served" base and convert any register
declarations that exceed the
+available register space silently to auto
. Parameters can also be
+declared as register
, this will in fact give slightly shorter code than
+using a register variable.
Since a function must save the current values of the registers on entry and
+restore them on exit, there is an overhead associated with register variables,
+and this overhead is quite high (about 20 bytes per variable). This means that
+just declaring anything as register
is not a good idea.
The best use for register variables are pointers, especially those that point +to structures. The magic number here is about 3 uses of a struct field: If the +function contains this number or even more, the generated code will be usually +shorter and faster when using a register variable for the struct pointer. The +reason for this is that the register variable can in many cases be used as a +pointer directly. Having a pointer in an auto variable means that this pointer +must first be copied into a zero page location, before it can be dereferenced.
+Second best use for register variables are counters. However, there is not +much difference in the code generated for counters, so you will need at least +100 operations on this variable (for example in a loop) to make it worth the +trouble. The only savings you get here are by the use of a zero page variable +instead of one on the stack or in the data segment.
+Register variables must be explicitly enabled by using -Or
or -r
on
+the command line. Register variables are only accepted on function top level,
+register variables declared in interior blocks are silently converted to
+auto
. With register variables disabled, all variables declared as
+register
are actually auto variables.
Please take care when using register variables: While they are helpful and can +lead to a tremendous speedup when used correctly, improper usage will cause +bloated code and a slowdown.
+ + + +The compiler allows to insert assembler statements into the output file. The +syntax is
++
+
+ asm (<string literal>[, optional parameters]) ;
+
+
+
+or
+
+
+ __asm__ (<string literal>[, optional parameters]) ;
+
+
+
+
+The first form is in the user namespace and is disabled by
+--standard
if the argument is not cc65
.
The asm statement may be used inside a function and on global file level. An
+inline assembler statement is a primary expression, so it may also be used as
+part of an expression. Please note however that the result of an expression
+containing just an inline assembler statement is always of type void
.
The contents of the string literal are preparsed by the compiler and inserted
+into the generated assembly output, so that the can be further processed by
+the backend and especially the optimizer. For this reason, the compiler does
+only allow regular 6502 opcodes to be used with the inline assembler. Pseudo
+instructions (like .import
, .byte
and so on) are not allowed,
+even if the ca65 assembler (which is used to translate the generated assembler
+code) would accept them. The builtin inline assembler is not a replacement for
+the full blown macro assembler which comes with the compiler.
Note: Inline assembler statements are subject to all optimizations done by the +compiler. There is currently no way to protect an inline assembler statement +from being moved or removed completely by the optimizer. If in doubt, check +the generated assembler output, or disable optimizations.
+The string literal may contain format specifiers from the following list. For +each format specifier, an argument is expected which is inserted instead of +the format specifier before passing the assembly code line to the backend.
++
%b
- Numerical 8-bit value%w
- Numerical 16-bit value%l
- Numerical 32-bit value%v
- Assembler name of a (global) variable or function%o
- Stack offset of a (local) variable%g
- Assembler name of a C label%s
- The argument is converted to a string%%
- The % sign itselfUsing these format specifiers, you can access C #defines
, variables or
+similar stuff from the inline assembler. For example, to load the value of
+a C #define
into the Y register, one would use
+
+
+ #define OFFS 23
+ __asm__ ("ldy #%b", OFFS);
+
+
+
+Or, to access a struct member of a static variable:
++
+
+ typedef struct {
+ unsigned char x;
+ unsigned char y;
+ unsigned char color;
+ } pixel_t;
+ static pixel_t pixel;
+ __asm__ ("ldy #%b", offsetof(pixel_t, color));
+ __asm__ ("lda %v,y", pixel);
+
+
+
+
+Note: Do not embed the assembler labels that are used as names of global +variables or functions into your asm statements. Code like this
++
+
+ int foo;
+ int bar () { return 1; }
+ __asm__ ("lda _foo"); /* DON'T DO THAT! */
+ ...
+ __asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */
+
+
+
+
+may stop working if the way, the compiler generates these names is changed in +a future version. Instead use the format specifiers from the table above:
++
+
+ __asm__ ("lda %v", foo); /* OK */
+ ...
+ __asm__ ("jsr %v", bar); /* OK */
+
+
+
+
+
+
++
+
+
+
+
+
+
#pragma bssseg ([push,]<name>)
+#pragma charmap (<index>, <code>)
+#pragma checkstack ([push,]on|off)
+#pragma codeseg ([push,]<name>)
+#pragma codesize ([push,]<int>)
+#pragma dataseg ([push,]<name>)
+#pragma optimize ([push,]on|off)
+#pragma rodataseg ([push,]<name>)
+#pragma regvaraddr ([push,]on|off)
+#pragma regvars ([push,]on|off)
+#pragma signedchars ([push,]on|off)
+#pragma staticlocals ([push,]on|off)
+#pragma warn ([push,]on|off)
+#pragma zpsym (<name>)
++
+
+
+
cl65 is a frontend for cc65, ca65, co65 and ld65. While you may not use the +full power of the tools when calling them through cl65, most features are +available, and the use of cl65 is much simpler.
+ + +The cl65 compile and link utility may be used to convert, compile, assemble +and link files. While the separate tools do just one step, cl65 knows how to +build object files from C files (by calling the compiler, then the assembler) +and other things.
++
+
+---------------------------------------------------------------------------
+Usage: cl65 [options] file [...]
+Short options:
+ -c Compile and assemble but don't link
+ -d Debug mode
+ -g Add debug info
+ -h Help (this text)
+ -l Create an assembler listing
+ -m name Create a map file
+ -mm model Set the memory model
+ -o name Name the output file
+ -r Enable register variables
+ -t sys Set the target system
+ -v Verbose mode
+ -vm Verbose map file
+ -C name Use linker config file
+ -Cl Make local variables static
+ -D sym[=defn] Define a preprocessor symbol
+ -I dir Set a compiler include directory path
+ -L path Specify a library search path
+ -Ln name Create a VICE label file
+ -O Optimize code
+ -Oi Optimize code, inline functions
+ -Or Optimize code, honour the register keyword
+ -Os Optimize code, inline known C funtions
+ -S Compile but don't assemble and link
+ -T Include source as comment
+ -V Print the version number
+ -W Suppress warnings
+ -Wa options Pass options to the assembler
+ -Wl options Pass options to the linker
+
+Long options:
+ --add-source Include source as comment
+ --asm-args options Pass options to the assembler
+ --asm-define sym[=v] Define an assembler symbol
+ --asm-include-dir dir Set an assembler include directory
+ --bss-label name Define and export a BSS segment label
+ --bss-name seg Set the name of the BSS segment
+ --cfg-path path Specify a config file search path
+ --check-stack Generate stack overflow checks
+ --code-label name Define and export a CODE segment label
+ --code-name seg Set the name of the CODE segment
+ --codesize x Accept larger code by factor x
+ --config name Use linker config file
+ --cpu type Set cpu type
+ --create-dep Create a make dependency file
+ --data-label name Define and export a DATA segment label
+ --data-name seg Set the name of the DATA segment
+ --debug Debug mode
+ --debug-info Add debug info
+ --feature name Set an emulation feature
+ --forget-inc-paths Forget include search paths (compiler)
+ --help Help (this text)
+ --include-dir dir Set a compiler include directory path
+ --ld-args options Pass options to the linker
+ --lib file Link this library
+ --lib-path path Specify a library search path
+ --list-targets List all available targets
+ --listing Create an assembler listing
+ --list-bytes n Number of bytes per assembler listing line
+ --mapfile name Create a map file
+ --memory-model model Set the memory model
+ --module Link as a module
+ --module-id id Specify a module id for the linker
+ --o65-model model Override the o65 model
+ --obj file Link this object file
+ --obj-path path Specify an object file search path
+ --register-space b Set space available for register variables
+ --register-vars Enable register variables
+ --rodata-name seg Set the name of the RODATA segment
+ --signed-chars Default characters are signed
+ --standard std Language standard (c89, c99, cc65)
+ --start-addr addr Set the default start address
+ --static-locals Make local variables static
+ --target sys Set the target system
+ --version Print the version number
+ --verbose Verbose mode
+ --zeropage-label name Define and export a ZEROPAGE segment label
+ --zeropage-name seg Set the name of the ZEROPAGE segment
+---------------------------------------------------------------------------
+
+
+
+Most of the options have the same meaning than the corresponding compiler,
+assembler or linker option. See the documentation for these tools for an
+explanation. If an option is available for more than one of the tools, it
+is set for all tools, where it is available. One example for this is -v
:
+The compiler, the assembler and the linker are all called with the -v
+switch.
There are a few remaining options that control the behaviour of cl65:
++
-S
This option forces cl65 to stop after the assembly step. This means that +C files are translated into assembler files, but nothing more is done. +Assembler files, object files and libraries given on the command line +are ignored.
+ + +-c
This options forces cl65 to stop after the assembly step. This means +that C and assembler files given on the command line are translated into +object files, but there is no link step, and object files and libraries +given on the command line are ignored.
+ + +-o name
The -o option is used for the target name in the final step. This causes +problems, if the linker will not be called, and there are several input +files on the command line. In this case, the name given with -o will be +used for all of them, which makes the option pretty useless. You +shouldn't use -o when more than one output file is created.
+ + +-t sys, --target sys
The default for this option is different from the compiler and linker in the +case that the option is missing: While the other tools (compiler, assembler +and linker) will use the "none" system settings by default, cl65 will use +the C64 as a target system by default. This was chosen since most people +seem to use cc65 to develop for the C64.
+ +-Wa options, --asm-args options
Pass options directly to the assembler. This may be used to pass options
+that aren't directly supported by cl65. Several options may be separated by
+commas, the commas are replaced by spaces when passing them to the
+assembler. Beware: Passing arguments directly to the assembler may interfere
+with some of the defaults, because cl65 doesn't parse the options passed. So
+if cl65 supports an option by itself, do not pass this option to the
+assembler by means of the -Wa
switch.
-Wl options, --ld-args options
Pass options directly to the linker. This may be used to pass options that
+aren't directly supported by cl65. Several options may be separated by
+commas, the commas are replaced by spaces when passing them to the linker.
+Beware: Passing arguments directly to the linker may interfere with some of
+the defaults, because cl65 doesn't parse the options passed. So if cl65
+supports an option by itself, do not pass this option to the linker by means
+of the -Wl
switch.
Since cl65 was created to simplify the use of the cc65 development +package, it tries to be smart about several things.
++
The type of an input file is derived from its extension:
++
.c
.s
, .asm
, .a65
.o
.obj
.a
, .lib
.grc
.o65
, .emd
, .joy
, .tgi
Please note that the program cannot handle input files with unknown file +extensions.
+ + +The morse trainer software, which consists of one C file (morse.c) and one +assembler file (irq.s) will need the following separate steps to compile +into an executable named morse:
++
+
+ cc65 -g -Oi -t c64 morse.c
+ ca65 -g morse.s
+ ca65 -g irq.s
+ ld65 -t c64 -o morse c64.o morse.o irq.o c64.lib
+
+
+
+When using cl65, this is simplified to
++
+
+ cl65 -g -Oi morse.c irq.s
+
+
+
+As a general rule, you may use cl65 instead of cc65 at most times, +especially in makefiles to build object files directly from C files. Use
++
+
+ .c.o:
+ cl65 -g -Oi $<
+
+
+
+to do this.
+ + + +If you have problems using the utility, 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 ( +uz@cc65.org).
+ + + +cl65 (and all cc65 binutils) are (C) Copyright 1998-2004 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply:
+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:
++
+
+
+
+
+
+
co65 is an object file conversion utility. It converts o65 object files into +assembler files, which may be translated by ca65 to generate object files in +the native object file format used by the cc65 tool chain.
+Since loadable drivers used by the library that comes with cc65 use the o65 +relocatable object code format, using the co65 utility allows to link these +drivers statically. This enables the use of these drivers without loading +additional files from a disk or other secondary storage.
+Another use would be to link object files generated by other development tools +to projects using the cc65 tool chain, but this has not been tested until now, +since such tools are currently rare.
+ + + +The co65 utility converts one o65 file per run into one assembler files in +ca65 format. The utility tries to autodetect the type of the o65 input file +using the operating system identifier contained in the o65 option list.
+ + +The converter may be called as follows:
++
+
+---------------------------------------------------------------------------
+Usage: co65 [options] file
+Short options:
+ -V Print the version number
+ -g Add debug info to object file
+ -h Help (this text)
+ -m model Override the o65 model
+ -n Don't generate an output file
+ -o name Name the output file
+ -v Increase verbosity
+
+Long options:
+ --bss-label name Define and export a BSS segment label
+ --bss-name seg Set the name of the BSS segment
+ --code-label name Define and export a CODE segment label
+ --code-name seg Set the name of the CODE segment
+ --data-label name Define and export a DATA segment label
+ --data-name seg Set the name of the DATA segment
+ --debug-info Add debug info to object file
+ --help Help (this text)
+ --no-output Don't generate an output file
+ --o65-model model Override the o65 model
+ --verbose Increase verbosity
+ --version Print the version number
+ --zeropage-label name Define and export a ZEROPAGE segment label
+ --zeropage-name seg Set the name of the ZEROPAGE segment
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
--bss-label name
Set the label used to mark the start of the bss segment. When this option is +given, the label is also exported and may be accessed from other code. When +accessing such a label from C code, be sure to include the leading +underscore. If you don't need to access the bss segment, there's no need to +use this option.
+ + +--bss-name seg
Set the name of the bss segment. The default name is "BSS" which is +compatible with the standard ld65 linker configurations.
+ + +--code-label name
Set the label used to mark the start of the code segment. When this option +is given, the label is also exported and may be accessed from other code. +When accessing such a label from C code, be sure to include the leading +underscore. If you don't need to access the code segment, there's no need to +use this option.
+ + +--code-name seg
Set the name of the code segment. The default name is "CODE" which is +compatible with the standard ld65 linker configurations.
+ + +--data-label name
Set the label used to mark the start of the data segment. When this option +is given, the label is also exported and may be accessed from other code. +When accessing such a label from C code, be sure to include the leading +underscore. If you don't need to access the data segment, there's no need to +use this option.
+ + +--data-name seg
Set the name of the data segment. The default name is "DATA" which is +compatible with the standard ld65 linker configurations.
+ + +-d, --debug
Enables debug mode, something that should not be needed for mere mortals.
+Currently the converter does only accept cc65 loadable modules generated by
+ld65 when not in debug mode. Please note that correct conversion has never
+been tested for o65 files from other sources, so be careful when using
+-d
.
-g, --debug-info
This will cause the converter to insert a .DEBUGINFO
command into the
+generated assembler code. This will cause the assembler to include all
+symbols in a special section in the object file.
-h, --help
Print the short option summary shown above.
+ + +-m model, --o65-model model
Set an o65 model. This option changes the way, output is generated for the +given o65 file. For example, cc65 loadable drivers have a zero page segment, +but this segment must not be defined in the file itself, because the +standard module loader will overlay it with the zeropage space used by the +application that loads this module. So instead of allocating space in the +zero page segment, the converter will reference the start of the zero page +area used by the application.
+Currently, the following models are defined:
++
The default is to autodetect the model to use from the input file, so +there's rarely a need to use this option.
+ + +-n, --no-output
Don't do the actual conversion, just read in the o65 file checking for
+problems. This option may be used in conjunction with --verbose
to
+view some information about the input file.
-o name
Specify the name of the output file. If you don't specify a name, the +name of the o65 input file is used, with the extension replaced by ".s".
+ + +-v, --verbose
Using this option, the converter will be somewhat more verbose and print
+some information about the o65 input file (among other things). You may use
+this option together with --no-output
to just get the o65 info.
-V, --version
Print the version number of the compiler. When submitting a bug report, +please include the operating system you're using, and the compiler +version.
+ + +--zeropage-label name
Set the label used to mark the start of the zeropage segment. When this +option is given, the label is also exported and may be accessed from other +code. When accessing such a label from C code, be sure to include the +leading underscore. If you don't need to access the zeropage segment, +there's no need to use this option.
+ + +--zeropage-name seg
Set the name of the data segment. The default name is "ZEROPAGE" which is +compatible with the standard ld65 linker configurations.
+ +The converter will accept one o65 file per invocation and create a file with +the same base name, but with the extension replaced by ".s". The output +file contains assembler code suitable for the use with the ca65 macro +assembler.
+ + +One main use of the utility is conversion of loadable drivers, so they may be +linked statically to an application. Statically linking will cause a few +things to be different from runtime loading:
++
All loadable drivers used by cc65 have a header and a jump table at the start +of the code segment. The header is needed to detect the driver (it may also +contain some data that is necessary to access the driver). The jump table is +used to access the functions in the driver code.
+When loading a driver at runtime, the load address of the driver is also the +address of the code segment, so the locations of the header and jump table are +known. However, when linking the driver statically, it is up to the programmer +to provide this information to the driver API.
+For this purpose, it is necessary to define a code segment label that can be +accessed from the outside later. Please note that the converter does currently +not create such a label without being ordered to do so, even if the input +file is a cc65 module.
+To create such a label, use the --code-label
option when calling the
+converter. Be sure to begin the label with a leading underscore when accessing
+it from C code. In your code, define an arbitrary variable with this name. Use
+the address of this variable as the address of the code segment of the driver.
+Be sure to never modify the variable which is in reality the start of your
+driver!
As an example, here are some instructions to convert and use the c64-hi.tgi +graphics driver:
+First, convert the driver, generating a label named "_c64_hi" for the code +segment. Use the assembler to generate an object file from the assembler +output.
++
+
+ co65 --code-label _c64_hi c64-hi.tgi
+ ca65 c64-hi.s
+
+
+
+
+Next, change your C code to declare a variable that is actually the first byte +of the driver:
++
+
+ extern char c64_hi;
+
+
+
+
+Instead of loading and unloading the driver, change the code to install and +uninstall the driver, which will be already in memory after linking:
++
+
+ /* Install the driver */
+ tgi_install (&c64_hi);
+
+ ...
+
+ /* Uninstall the driver */
+ tgi_uninstall ();
+
+
+
+
+Don't forget to link the driver object file to your application, otherwise you +will get an "undefined external" error for the _c64_hi symbol.
+ + + + +If you have problems using the converter, if you find any bugs, or if you're +doing something interesting with the code, I would be glad to hear from you. +Feel free to contact me by email ( +uz@cc65.org).
+ + + +co65 is (C) Copyright 2003 Ullrich von Bassewitz. For usage of the binaries +and/or sources the following conditions apply:
+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:
++
+
+
+
+
+
+
This will not only help to find errors between separate modules, it will also +generate better code, since the compiler must not assume that a variable sized +parameter list is in place and must not pass the argument count to the called +function. This will lead to shorter and faster code.
+ + + +Variable declarations in nested blocks are usually a good thing. But with +cc65, there is a drawback: Since the compiler generates code in one pass, it +must create the variables on the stack each time the block is entered and +destroy them when the block is left. This causes a speed penalty and larger +code.
+ + + +The compiler needs hints from you about the code to generate. When accessing +indexed data structures, get a pointer to the element and use this pointer +instead of calculating the index again and again. If you want to have your +loops unrolled, or loop invariant code moved outside the loop, you have to do +that yourself.
+ + + +While long support is necessary for some things, it's really, really slow on +the 6502. Remember that any long variable will use 4 bytes of memory, and any +operation works on double the data compared to an int.
+ + + +The CPU has no opcodes to handle signed values greater than 8 bit. So sign +extension, test of signedness etc. has to be done by hand. The code to handle +signed operations is usually a bit slower than the same code for unsigned +types.
+ + + +While in arithmetic operations, chars are immidiately promoted to ints, they +are passed as chars in parameter lists and are accessed as chars in variables. +The code generated is usually not much smaller, but it is faster, since +accessing chars is faster. For several operations, the generated code may be +better if intermediate results that are known not to be larger than 8 bit are +casted to chars.
+When doing
++
+
+ unsigned char a;
+ ...
+ if ((a & 0x0F) == 0)
+
+
+
+the result of the & operator is an int because of the int promotion rules of +the language. So the compare is also done with 16 bits. When using
++
+
+ unsigned char a;
+ ...
+ if ((unsigned char)(a & 0x0F) == 0)
+
+
+
+the generated code is much shorter, since the operation is done with 8 bits +instead of 16.
+ + + +When indexing into an array, the compiler has to calculate the byte offset +into the array, which is the index multiplied by the size of one element. When +doing the multiplication, the compiler will do a strength reduction, that is, +replace the multiplication by a shift if possible. For the values 2, 4 and 8, +there are even more specialized subroutines available. So, array access is +fastest when using one of these sizes.
+ + + +Since cc65 is not building an explicit expression tree when parsing an +expression, constant subexpressions may not be detected and optimized properly +if you don't help. Look at this example:
++
+
+ #define OFFS 4
+ int i;
+ i = i + OFFS + 3;
+
+
+
+The expression is parsed from left to right, that means, the compiler sees 'i', +and puts it contents into the secondary register. Next is OFFS, which is +constant. The compiler emits code to add a constant to the secondary register. +Same thing again for the constant 3. So the code produced contains a fetch +of 'i', two additions of constants, and a store (into 'i'). Unfortunately, the +compiler does not see, that "OFFS + 3" is a constant for itself, since it does +it's evaluation from left to right. There are some ways to help the compiler +to recognize expression like this:
++
The compiler is not always smart enough to figure out, if the rvalue of an +increment is used or not. So it has to save and restore that value when +producing code for the postincrement and postdecrement operators, even if this +value is never used. To avoid the additional overhead, use the preincrement +and predecrement operators if you don't need the resulting value. That means, +use
++
+
+ ...
+ ++i;
+ ...
+
+
+
+instead of
++
+
+ ...
+ i++;
+ ...
+
+
+
+
+
+
+The compiler produces optimized code, if the value of a pointer is a constant. +So, to access direct memory locations, use
++
+
+ #define VDC_DATA 0xD601
+ *(char*)VDC_STATUS = 0x01;
+
+
+
+That will be translated to
++
+
+ lda #$01
+ sta $D600
+
+
+
+The constant value detection works also for struct pointers and arrays, if the +subscript is a constant. So
++
+
+ #define VDC ((unsigned char*)0xD600)
+ #define STATUS 0x01
+ VDC [STATUS] = 0x01;
+
+
+
+will also work.
+If you first load the constant into a variable and use that variable to access +an absolute memory location, the generated code will be much slower, since the +compiler does not know anything about the contents of the variable.
+ + + +Initialization of local variables when declaring them gives shorter and faster +code. So, use
++
+
+ int i = 1;
+
+
+
+instead of
++
+
+ int i;
+ i = 1;
+
+
+
+But beware: To maximize your savings, don't mix uninitialized and initialized +variables. Create one block of initialized variables and one of uniniitalized +ones. The reason for this is, that the compiler will sum up the space needed +for uninitialized variables as long as possible, and then allocate the space +once for all these variables. If you mix uninitialized and initialized +variables, you force the compiler to allocate space for the uninitialized +variables each time, it parses an initialized one. So do this:
++
+
+ int i, j;
+ int a = 3;
+ int b = 0;
+
+
+
+instead of
++
+
+ int i;
+ int a = 3;
+ int j;
+ int b = 0;
+
+
+
+The latter will work, but will create larger and slower code.
+ + + +The result type of the ?:
operator is a long, if one of the second or
+third operands is a long. If the second operand has been evaluated and it was
+of type int, and the compiler detects that the third operand is a long, it has
+to add an additional int
-> long
conversion for the second
+operand. However, since the code for the second operand has already been
+emitted, this gives much worse code.
Look at this:
++
+
+ long f (long a)
+ {
+ return (a != 0)? 1 : a;
+ }
+
+
+
+When the compiler sees the literal "1", it does not know, that the result type
+of the ?:
operator is a long, so it will emit code to load a integer
+constant 1. After parsing "a", which is a long, a int
-> long
+conversion has to be applied to the second operand. This creates one
+additional jump, and an additional code for the conversion.
A better way would have been to write:
++
+
+ long f (long a)
+ {
+ return (a != 0)? 1L : a;
+ }
+
+
+
+By forcing the literal "1" to be of type long, the correct code is created in +the first place, and no additional conversion code is needed.
+ + + +When addressing an array via a pointer, don't use the plus and dereference +operators, but the array operator. This will generate better code in some +common cases.
+Don't use
++
+
+ char* a;
+ char b, c;
+ char b = *(a + c);
+
+
+
+Use
++
+
+ char* a;
+ char b, c;
+ char b = a[c];
+
+
+
+instead.
+ + + +Register variables may give faster and shorter code, but they do also have an +overhead. Register variables are actually zero page locations, so using them +saves roughly one cycle per access. Since the old values have to be saved and +restored, there is an overhead of about 70 cycles per 2 byte variable. It is +easy to see, that - apart from the additional code that is needed to save and +restore the values - you need to make heavy use of a variable to justify the +overhead.
+As a general rule: Use register variables only for pointers that are +dereferenced several times in your function, or for heavily used induction +variables in a loop (with several 100 accesses).
+When declaring register variables, try to keep them together, because this +will allow the compiler to save and restore the old values in one chunk, and +not in several.
+And remember: Register variables must be enabled with -r
or -Or
.
The language rules for constant numeric values specify that decimal constants +without a type suffix that are not in integer range must be of type long int +or unsigned long int. This means that a simple constant like 40000 is of type +long int, and may cause an expression to be evaluated with 32 bits.
+An example is:
++
+
+ unsigned val;
+ ...
+ if (val < 65535) {
+ ...
+ }
+
+
+
+Here, the compare is evaluated using 32 bit precision. This makes the code +larger and a lot slower.
+Using
++
+
+ unsigned val;
+ ...
+ if (val < 0xFFFF) {
+ ...
+ }
+
+
+
+or
++
+
+ unsigned val;
+ ...
+ if (val < 65535U) {
+ ...
+ }
+
+
+
+instead will give shorter and faster code.
+ + +Since cc65 has the "wrong" calling order, the location of the fixed parameters +in a variadic function (a function with a variable parameter list) depends on +the number and size of variable arguments passed. Since this number and size +is unknown at compile time, the compiler will generate code to calculate the +location on the stack when needed.
+Because of this additional code, accessing the fixed parameters in a variadic +function is much more expensive than access to parameters in a "normal" +function. Unfortunately, this additional code is also invisible to the +programmer, so it is easy to forget.
+As a rule of thumb, if you access such a parameter more than once, you should +think about copying it into a normal variable and using this variable instead.
+ + + + diff --git a/usr/share/doc/cc65/webdoc/compile.txt b/usr/share/doc/cc65/webdoc/compile.txt new file mode 100644 index 0000000..5061d1e --- /dev/null +++ b/usr/share/doc/cc65/webdoc/compile.txt @@ -0,0 +1,316 @@ + + +Instructions for compiling cc65 and the ca65 binutils: + + +Linux (and probably most other Unices) +-------------------------------------- + +Preconditions: + +You need the GNU C Compiler, Perl and sgml-tools installed. + +The simple way: + +From the main directory, use + + make -f make/gcc.mak + +to build all binaries, libraries and the docs. Use + + make -f make/gcc.mak install + +to install the files. Check the makefile before doing so and adjust the PREFIX +variable as you like it. + + +Step by step: + +Enter the src/ directory and do a + + make -f make/gcc.mak + +This will build all executables. You may use + + make -f make/gcc.mak strip + +to remove debugging information from the binaries. + +After that, you need to compile the libraries. Do + + cd libsrc; make + +HTML docs can be generated with + + cd doc; make html + +That's it! Installation directories for the RPM packages are + + /usr/bin for the binaries + /usr/lib/cc65/include for include files + /usr/lib/cc65/lib for libraries and startup files + /usr/share/doc/cc65-da65 is a disassembler for 6502/65C02 code. It is supplied as a utility with +the cc65 C compiler and generates output that is suitable for the ca65 +macro assembler.
+Besides generating output for ca65, one of the design goals was that the user +is able to feed additional information about the code into the disassembler +for improved results. This information may include the location and size of +tables, and their format.
+One nice advantage of this concept is that disassembly of copyrighted binaries +may be handled without problems: One can just pass the information file for +disassembling the binary, so everyone with a legal copy of the binary can +generate a nicely formatted disassembly with readable labels and other +information.
+ + +The assembler accepts the following options:
++
+
+---------------------------------------------------------------------------
+Usage: da65 [options] [inputfile]
+Short options:
+ -g Add debug info to object file
+ -h Help (this text)
+ -i name Specify an info file
+ -o name Name the output file
+ -v Increase verbosity
+ -F Add formfeeds to the output
+ -S addr Set the start/load address
+ -V Print the disassembler version
+
+Long options:
+ --comments n Set the comment level for the output
+ --cpu type Set cpu type
+ --debug-info Add debug info to object file
+ --formfeeds Add formfeeds to the output
+ --help Help (this text)
+ --info name Specify an info file
+ --pagelength n Set the page length for the listing
+ --start-addr addr Set the start/load address
+ --verbose Increase verbosity
+ --version Print the disassembler version
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
--comments n
Set the comment level for the output. Valid arguments are 0..4. Greater +values will increase the level of additional information written to the +output file in form of comments.
+ + +--cpu type
Set the CPU type. The option takes a parameter, which may be one of
+6502, 65SC02, 65C02
+Support for the 65816 is currently not available.
+ + +-F, --formfeeds
Add formfeeds to the generated output. This feature is useful together
+with the
+--pagelength
option.
+If --formfeeds
is given, a formfeed is added to the output after each
+page.
-g, --debug-info
This option adds the .DEBUGINFO
command to the output file, so the
+assembler will generate debug information when reassembling the generated
+output.
-h, --help
Print the short option summary shown above.
+ + +-i name, --info name
Specify an info file. The info file contains global options that may +override or replace command line options plus informations about the code +that has to be disassembled. See the separate section +Info File Format.
+ + +-o name
Specify a name for an output file. The default is to use stdout
, so
+without this switch or the corresponding
+global option
+OUTPUTNAME
,
+the output will go to the terminal.
--pagelength n
Sets the length of a listing page in lines. After this number of lines, a
+new page header is generated. If the
+--formfeeds
is also given, a formfeed is inserted before
+generating the page header.
A value of zero for the page length will disable paging of the output.
+ + +-S addr, --start-addr addr
Specify the start/load address of the binary code that is going to be +disassembled. The given address is interpreted as an octal value if +preceded with a '0' digit, as a hexadecimal value if preceded +with '0x', '0X', or '$', and as a decimal value in all other cases. If no +start address is specified, $10000 minus the size of the input file is used.
+ + +-v, --verbose
Increase the disassembler verbosity. Usually only needed for debugging +purposes. You may use this option more than one time for even more +verbose output.
+ + +-V, --version
Print the version number of the assembler. If you send any suggestions +or bugfixes, please include the version number.
+ +The default (no CPU given on the command line or in the GLOBAL
section of
+the info file) is the 6502 CPU. The disassembler knows all "official" opcodes
+for this CPU. Invalid opcodes are translated into .byte
commands.
With the command line option
+--cpu
, the
+disassembler may be told to recognize either the 65SC02 or 65C02 CPUs. The
+latter understands the same opcodes as the former, plus 16 additional bit
+manipulation and bit test-and-branch commands.
While there is some code for the 65816 in the sources, it is currently +unsupported.
+ + +The disassembler works by creating an attribute map for the whole address +space ($0000 - $FFFF). Initially, all attributes are cleared. Then, an +external info file (if given) is read. Disassembly is done in several passes. +In all passes with the exception of the last one, information about the +disassembled code is gathered and added to the symbol and attribute maps. The +last pass generates output using the information from the maps.
+ +Some instructions may generate labels in the first pass, while most other
+instructions do not generate labels, but use them if they are available. Among
+others, the branch and jump instructions will generate labels for the target
+of the branch in the first pass. External labels (taken from the info file)
+have precedence over internally generated ones, They must be valid identifiers
+as specified for the ca65 assembler. Internal labels (generated by the
+disassembler) have the form Labcd
, where abcd
is the hexadecimal
+address of the label in upper case letters. You should probably avoid using
+such label names for external labels.
The info file is used to pass additional information about the input code to +the disassembler. This includes label names, data areas or tables, and global +options like input and output file names. See the +next section for more information.
+ + + +The info file contains lists of specifications grouped together. Each group +directive has an identifying token and an attribute list enclosed in curly +braces. Attributes have a name followed by a value. The syntax of the value +depends on the type of the attribute. String attributes are places in double +quotes, numeric attributes may be specified as decimal numbers or hexadecimal +with a leading dollar sign. There are also attributes where the attribute +value is a keyword, in this case the keyword is given as is (without quotes or +anything). Each attribute is terminated by a semicolon.
++
+
+ group-name { attribute1 attribute-value; attribute2 attribute-value; }
+
+
+
+
+
+Comments start with a hash mark (#
) and extend from the position of
+the mark to the end of the current line. Hash marks inside of strings will
+of course not start a comment.
Global options may be specified in a group with the name GLOBAL
. The
+following attributes are recognized:
+
COMMENTS
This attribute may be used instead of the
+--comments
option on the command line. It takes a numerical
+parameter between 0 and 4. Higher values increase the amount of information
+written to the output file in form of comments.
CPU
This attribute may be used instead of the
+--cpu
option on the command line. It takes a string parameter.
INPUTNAME
The attribute is followed by a string value, which gives the name of the +input file to read. If it is present, the disassembler does not accept an +input file name on the command line.
+ + +INPUTOFFS
The attribute is followed by a numerical value that gives an offset into +the input file which is skipped before reading data. The attribute may be +used to skip headers or unwanted code sections in the input file.
+ + +INPUTSIZE
INPUTSIZE
is followed by a numerical value that gives the amount of
+data to read from the input file. Data beyond INPUTOFFS + INPUTSIZE
+is ignored.
OUTPUTNAME
The attribute is followed by string value, which gives the name of the
+output file to write. If it is present, specification of an output file on
+the command line using the
+-o
option is
+not allowed.
The default is to use stdout
for output, so without this attribute or
+the corresponding command line option
+-o
+the output will go to the terminal.
PAGELENGTH
This attribute may be used instead of the
+--pagelength
option on the command line. It takes a numerical
+parameter. Using zero as page length (which is the default) means that no
+pages are generated.
STARTADDR
This attribute may be used instead of the
+--start-addr
option on the command line. It takes a numerical
+parameter. The default for the start address is $10000 minus the size of
+the input file (this assumes that the input file is a ROM that contains the
+reset and irq vectors).
The RANGE
directive is used to give information about address ranges. The
+following attributes are recognized:
+
COMMENT
This attribute is only allowed if a label is also given. It takes a string
+as argument. See the description of the
+LABEL
directive for an explanation.
END
This gives the end address of the range. The end address is inclusive, that +means, it is part of the range. Of course, it may not be smaller than the +start address.
+ +NAME
This is a convenience attribute. It takes a string argument and will cause
+the disassembler to define a label for the start of the range with the
+given name. So a separate
+LABEL
+directive is not needed.
START
This gives the start address of the range.
+ +TYPE
This attribute specifies the type of data within the range. The attribute +value is one of the following keywords:
++
ADDRTABLE
The range consists of data and is disassembled as a table of words
+(16 bit values). The difference to the WORDTABLE
type is that
+a label is defined for each entry in the table.
BYTETABLE
The range consists of data and is disassembled as a byte table.
+ +CODE
The range consists of code.
+ +DBYTETABLE
The range consists of data and is disassembled as a table of dbytes +(double byte values, 16 bit values with the low byte containing the +most significant byte of the 16 bit value).
+ +DWORDTABLE
The range consists of data and is disassembled as a table of double +words (32 bit values).
+ +RTSTABLE
The range consists of data and is disassembled as a table of words (16 bit
+values). The values are interpreted as words that are pushed onto the
+stack and jump to it via RTS
. This means that they contain
+address-1
of a function, for which a label will get defined by the
+disassembler.
SKIP
The range is simply ignored when generating the output file. Please note
+that this means that reassembling the output file will not generate
+the original file, not only because the missing piece in between, but also
+because the following code will be located on wrong addresses. Output
+generated with SKIP
ranges will need manual rework.
TEXTTABLE
The range consists of readable text.
+ +WORDTABLE
The range consists of data and is disassembled as a table of words +(16 bit values).
+ +The LABEL
directive is used to give names for labels in the disassembled
+code. The following attributes are recognized:
+
ADDR
Followed by a numerical value. Specifies the value of the label.
+ +COMMENT
Attribute argument is a string. The comment will show up in a separate line +before the label, if the label is within code or data range, or after the +label if it is outside.
+Example output:
++
+
+ foo := $0001 ; Comment for label named "foo"
+
+ ; Comment for label named "bar"
+ bar:
+
+
+
+
+NAME
The attribute is followed by a string value which gives the name of the +label.
+ +SIZE
This attribute is optional and may be used to specify the size of the data
+that follows. If a size greater than 1 is specified, the disassembler will
+create labels in the form label+offs
for all bytes within the given
+range, where label
is the label name given with the NAME
+attribute, and offs
is the offset within the data.
The ASMINC
directive is used to give the names of input files containing
+symbol assignments in assembler syntax:
+
+
+ Name = value
+ Name := value
+
+
+
+The usual conventions apply for symbol names. Values may be specified as hex +(leading $), binary (leading %) or decimal. The values may optionally +be signed.
+NOTE: The include file parser is very simple. Expressions are not allowed, and
+anything but symbol assignments is flagged as an error (but see the
+IGNOREUNKNOWN
directive below).
The following attributes are recognized:
++
FILE
Followed by a string value. Specifies the name of the file to read.
+ +COMMENTSTART
The optional attribute is followed by a character constant. It specifies the
+character that starts a comment. The default value is a semicolon. This
+value is ignored if IGNOREUNKNOWN
is true.
IGNOREUNKNOWN
This attribute is optional and is followed by a boolean value. It allows to +ignore input lines that don't have a valid syntax. This allows to read in +assembler include files that contain more than just symbol assignments. +Note: When this attribute is used, the disassembler will ignore any errors +in the given include file. This may have undesired side effects.
+ +The following is a short example for an info file that contains most of the +directives explained above:
++
+
+ # This is a comment. It extends to the end of the line
+ GLOBAL {
+ OUTPUTNAME "kernal.s";
+ INPUTNAME "kernal.bin";
+ STARTADDR $E000;
+ PAGELENGTH 0; # No paging
+ CPU "6502";
+ };
+
+
+ RANGE { START $E612; END $E631; TYPE Code; };
+ RANGE { START $E632; END $E640; TYPE ByteTable; };
+ RANGE { START $EA51; END $EA84; TYPE RtsTable; };
+ RANGE { START $EC6C; END $ECAB; TYPE RtsTable; };
+ RANGE { START $ED08; END $ED11; TYPE AddrTable; };
+
+ # Zero page variables
+ LABEL { NAME "fnadr"; ADDR $90; SIZE 3; };
+ LABEL { NAME "sal"; ADDR $93; };
+ LABEL { NAME "sah"; ADDR $94; };
+ LABEL { NAME "sas"; ADDR $95; };
+
+ # Stack
+ LABEL { NAME "stack"; ADDR $100; SIZE 255; };
+
+ # Indirect vectors
+ LABEL { NAME "cinv"; ADDR $300; SIZE 2; }; # IRQ
+ LABEL { NAME "cbinv"; ADDR $302; SIZE 2; }; # BRK
+ LABEL { NAME "nminv"; ADDR $304; SIZE 2; }; # NMI
+
+ # Jump table at end of kernal ROM
+ LABEL { NAME "kscrorg"; ADDR $FFED; };
+ LABEL { NAME "kplot"; ADDR $FFF0; };
+ LABEL { NAME "kiobase"; ADDR $FFF3; };
+ LABEL { NAME "kgbye"; ADDR $FFF6; };
+
+ # Hardware vectors
+ LABEL { NAME "hanmi"; ADDR $FFFA; };
+ LABEL { NAME "hares"; ADDR $FFFC; };
+ LABEL { NAME "hairq"; ADDR $FFFE; };
+
+
+
+
+
+
+
+
+If you have problems using the disassembler, if you find any bugs, or if +you're doing something interesting with the assembler, I would be glad to hear +from you. Feel free to contact me by email ( +uz@cc65.org).
+ + + +da65 (and all cc65 binutils) are (C) Copyright 1998-2003 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply:
+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:
++
+
+
+
+
+
+
This document describes how to debug your programs using the cc65 development +tools and the VICE CBM emulator.
+ + + +VICE is an emulator for many of the CBM machines. It runs on Unix, DOS and +Windows 95. It emulates the Commodore 64, 128, VIC20, PET and the 600/700 +machines. For more information see the VICE home page:
++http://www.cs.cmu.edu/~dsladic/vice/vice.html
+VICE has a builtin machine language monitor that may be used for debugging +your programs. Using an emulator for debugging has some advantages:
++
Please note that you need at least VICE version 0.16 for the label file +feature to work. This version has still some problems (see +Problems and workarounds), but older versions had even more problems +and do not work correctly.
+ + + +VICE support is mostly done via a label file that is generated by the linker
+and that may be read by the VICE monitor, so it knows about your program.
+Source level debugging is not
available, you have to debug your programs
+in the assembler view.
The first step is to generate object files that contain information about +all labels in your sources, not just the exported ones. This can be done +by several means:
++
+
+ .debuginfo +
+
+
+
+command in your source.
+-g
switch when invoking the compiler. The compiler will
+then place a .debuginfo
command into the generated assembler source.
+So, if you have just C code, all you need is to invoke the compiler with
+-g
. If you're using assembler code, you have to use -g
for the
+assembler, or add ".debuginfo on
" to your source files. Since the
+generated debug info is not appended to the generated executables, it is a
+good idea to always use -g
. It makes the object files and libraries
+slightly larger (~30%), but this is usually not a problem.
The second step is to tell the linker that it should generate a VICE label
+file. This is done by the -L
switch followed by the name of the label
+file (I'm usually using a .lbl
extension for these files). An example for
+a linker command line would be:
+
+
+ ld65 -t c64 -L hello.lbl -m hello.map -o hello crt0 hello.o c64.lib
+
+
+
+This will generate a file named hello.lbl that contains all symbols used in +your program.
+Note: The runtime libraries and startup files were generated with +debug info, so you don't have to care about this.
+ + + +Load your program, then enter the monitor and use the "ll
" command to
+load your label file like this:
+
+
+ ll "hello.lbl"
+
+
+
+You will get lots of warnings and even a few errors. You may ignore safely all +these warnings and errors as long as they reference any problems VICE thinks +it has with the labels.
+After loading the labels, they are used by VICE in the disassembler listing, +and you may use them whereever you need to specify an address. Try
++
+
+ d ._main
+
+
+
+as an example (note that VICE needs a leading dot before all labels, and that +the compiler prepends an underline under most named labels).
+ + + +Older versions of VICE had several problems with labels. However, even those +versions were still tremendously useful, and all known problems are gone in +current versions. So, here is a list of the problems known to me as of version +0.16.1:
++
ll
" command does not work. Worse, it seems that internal
+memory gets corrupted when using this command, so VICE will crash after use.
+Use the "pb
" command to load the label file in this case.
+Note: All these problems are fixed in current (>= 1.0) VICE +versions. If you're really using such an old version, you should think about +an upgrade.
+ + + ++
+
+
+
+
Prior to using these functions a handle to the drive has to be obtained. This
+is done with the dio_open
function. After use, the handle should be
+released with the dio_close
function.
+
+
+ dhandle_t __fastcall__ dio_open (driveid_t drive_id);
+
+
+
+The drive_id
specifies the drive to access, with 0 being the first
+disk drive, 1 the second, and so on.
+
+
+ unsigned char __fastcall__ dio_close (dhandle_t handle);
+
+
+
+Closes a handle obtained by dio_open
. Returns status code.
The read and write functions are:
++
+
+ unsigned char __fastcall__ dio_read (dhandle_t handle,
+ sectnum_t sect_num,
+ void *buffer);
+
+
+
+This function will read the sector specified by sect_num
into the memory
+location at buffer.
+
+
+ unsigned char __fastcall__ dio_write (dhandle_t handle,
+ sectnum_t sect_num,
+ const void *buffer);
+
+
+
+This function will write the memory contents at buffer to the sector specified
+by sect_num
. No verify is performed.
+
+
+ unsigned char __fastcall__ dio_write_verify (dhandle_t handle,
+ sectnum_t sect_num,
+ const void *buffer);
+
+
+
+This function will write the memory contents at buffer to the sector specified
+by sect_num
. A verification is performed.
Use the
+dio_query_sectsize
function to query the size of a sector.
All these functions will return 0 for success and an OS specific error code in +case of failure.
+ + +Some systems support multiple diskette formats which have different sector sizes. +The following function returns the sector size of the currently inserted disk:
++
+
+ sectsize_t __fastcall__ dio_query_sectsize(dhandle_t handle);
+
+
+
+On the Atari platform, the sector size is handled specially. Please refer +to the DIO section in the +Atari +specific platform documentation.
+ +Since the read and write functions expect a sector number, for systems where +the sectors aren't addressed by a logical sector number (e.g. CBM drives), +there are 2 conversion functions. One of them converts a logical sector number +to a head/track/sector triple. The other conversion function works the other +way round.
++
+
+ unsigned char __fastcall__ dio_phys_to_log (dhandle_t handle,
+ const dio_phys_pos *physpos,
+ sectnum_t *sectnum);
+
+
+
+This function converts track/head/sector to logical sector number.
++
+
+ unsigned char __fastcall__ dio_log_to_phys (dhandle_t handle,
+ const _sectnum_t *sectnum,
+ dio_phys_pos *physpos);
+
+
+
+This function converts a logical sector number to track/head/sector notation.
+ +Note, that on systems which natively use logical sector numbers (e.g. Atari),
+the conversion functions are dummies. They ignore head/track
+(dio_phys_to_log
) or return them as zero (dio_log_to_phys
).
+The logical sector number is returned as physical sector and vice versa.
+
+
+
+
+These changes have been lingering in my inbox for quite a while, only now did I find the +time to update the document. +
+The order for saving the undefined reference and the low byte of a +high byte relocation entry has changed. This makes the OS/A65 lib6502 +implementation easier. +
++
+With some new 6502/C64/C128 operating systems comes the need for a new +binary format. In multitasking operating systems like Lunix, SMOS, or +OS/A65, a binary file cannot be loaded to a fixed location that might +already be used by another program. Therefore it must be possible to +relocate the program to an arbitrary address at least at load time. +In addition to that, more specific information might be stored in a +binary executable file, like interrupt vectors for example. +
+This text gives a good solution to this problem for the 6502 CPU and an +assembler source format to use this format in a general manner. The file +format can even be used as an object file format, i.e. a format a linker +can use as an input file. It is also usable as a 65816 file format. +Instead of zeropage addressing modes, the 65816 has direct addressing +modes, that add the contents of the direct register to the zeropage +address in the opcode. +
+ +
+The 6502 has the special feature of a 'zeropage', i.e. a very limited +memory address range used for special addressing modes. So the format +should not only provide a means to relocate absolute addresses but also +zeropage addresses. The 65816 replaces zeropage addressing with direct +addressing modes. +
+The stack space is also very limited. A binary format has to provide a +measure of how much stack space is needed for the application. +
+Such limits should be defined as 2 byte values, even if the 6502 only has +a range of 8 address bits for zeropage and stack. But the 65816 behaves +differently, it has a 16 bit stack pointer for example. For further +expandability, a 32 bit format should be provided, although the 16 bit +format suffices for the 65816 already. +
+Another problem is, that an address can be 'split', i.e. you can just use +the high byte or the low byte separately in an opcode. This gives need +to a special relocation table format, that can cope with half-address +references. The 65816 can even have three byte addresses, i.e. address +in a segment and segment number. +
+ +
+The file differs from the known Commodore file formats, in that a lot +more information is stored in the file. First the data is structured +in separate segments to allow different handling of text (program code), +data (like tables) and bss (uninitialized data). +
+Also tables are included to allow late binding, i.e. linking the +file with other files at load time, and relocation, i.e. executing +the file at different addresses in 6502 address space. +
+
+As already used in other formats, the assembler uses three different +segment types, i.e. text (the actual program code), data (initialized +variables), and bss (uninitialized variables). +To have these different segments seems to be 'overdesigned', but they +actually make memory handling easier in more complex operating systems +or systems with virtual addresses (OS/A65, for example). +
+The text segment is defined to be read-only memory. This doesn't allow +self-modifying code in this segment, but allows memory sharing in virtual +memory architectures. The data segment actually is like the text segment, +only it is allocated writable. This segment might not be shared between +different processes. The contents of these two segments are loaded from +the file. The bss segment is uninitialized data, i.e. upon program start, +it is not defined - and not loaded from the file. This area is read-write +and can be used during program execution. It is also not shared between +processes. In addition to these segments, the 6502 format also includes a +zeropage segment type, to allow zeropage variables to be relocated. This +zeropage segment is like a bss segment, in that only the length, but +not the data is saved. For the 65816 the zeropage segment changes its +meaning to a bank zero segment. +
+The different segments hold different type of data and can be located +anywhere in memory (except zero segment, which has to be in the zeropage +resp. bank zero). The program must therefore not assume anything about +the relative addresses between different segments. +
+
+In general, there are three ways to handle the relocation problem so far: +
+- Tables: have a relocation table for a text segment + if the relocation table is put in front of code + you have to save the table in a side-storage + if table is behind, you still cannot relocate 'on the fly'. + +- Deassembling: go through the code, deassemble it and change all absolute + addresses. Problem: needs to know or have hints about where some + data is in the code. + +- Relocation info in the code: here each address is preceeded with an + 'escape' code and is relocated when loading. But this disallows block + oriented transfer from storage media to memory. ++This binary format uses the first method, with the table after the +code/data. This way block oriented transfer for the text/data segment can +be used. And while reading the relocation tables bytewise, the relocation +can be done without the need to save the table somewhere. +
+
+As this file format should not only be used as an executable format, but +also as object file format, it must provide a way to define references +- references exported from this object and labels referenced in this +object. The external references list (also called 'undefined list') lists +the addresses where labels not defined in this object are referenced. +The exported globals list lists the addresses that are available for +other objects. The labels are named by null-terminated ASCII strings. +
+Even an executable file can have non-empty globals and externals lists, +but only if the operating system allows this. In this case, so called +'late binding' is used to link the object with some global libraries +at link time. +
+
+The proposed standard extension for the described format is ".o65" when +used as an object file. +
+
+The binary format is the following: +
+ ( + header + + text segment + + data segment + + external references list + + relocation table for text segment + + relocation table for data segment + + exported globals list + ) ++The description of the parts follows: +
+
+The header contains the minimum needed data in a fixed struct. +The rest of the necessary information is put into the header options. +[Note: .word is a 16 bit value, low byte first, .byt is a simple byte. +.long is a 32 bit value, low byte first. .size is a 16 or 32 bit +value according to .word and .long, depending on the size bit in the +mode field ] +
+This is the fixed struct: +
+ ( + .byt $01,$00 ; non-C64 marker + + .byt $6f, $36, $35 ; "o65" MAGIC number! + .byt 0 ; version + + .word mode ; mode word + + .size tbase ; address to which text is assembled to + ; originally + .size tlen ; length of text segment + .size dbase ; originating address for data segment + .size dlen ; length of data segment + .size bbase ; originating address for bss segment + .size blen ; length of bss segment + .size zbase ; originating address for zero segment + .size zlen ; length of zero segment + .size stack ; minimum needed stack size, 0= not known. + ; the OS should add reasonable values for + ; interrupt handling before allocating + ; stack space + ) ++The mode word currently has these defined bits: + +
+ mode.15 : CPU 0= 6502 1= 65816 + mode.14 : reloc 0= bytewise... 1= page(256byte)wise relocation + allowed + mode.13 : size 0= size=16 bit, 1= size=32 bit + mode.12 : obj 0= executable 1= object file + mode.11 : simple 0= (ignored) 1= simple file addresses + mode.10 : chain 0= (ignored) 1= another file follows this one + mode.9 : bsszero 0= (ignored) 1= the bss segment must be zeroed out for this file + + mode.4-7 : CPU2 0000 = 6502 core (no undocumented opcodes) + 0001 = 65C02 /w some bugfix, no illegal opcodes + 0010 = 65SC02 (enhanced 65C02), some new opcodes + 0011 = 65CE02 some 16bit ops/branches, Z register is modifiable + 0100 = NMOS 6502 (including undocumented opcodes) + 0101 = 65816 in 6502 emulation mode + 011x = reserved + 1xxx = reserved + ^^^^ + |||+- Bit 4 + ||+-- Bit 5 + |+--- Bit 6 + +---- Bit 7 + + mode.0-1: align 0= byte align, + 1= word (i.e. 2 byte) align + 2= long (4 byte) align + 3= block (256 byte) align ++The
CPU
bit tells the loader for which CPU the file was made. This has
+implications on the zero segment, for example. Also a system can check
+if the program will run at all (on a 6502 that is).
+The reloc
bit defines if an object file can be relocated bytewise,
+or if it must be page-aligned. A page has 256 bytes. The restriction to
+pagewise relocation simplifies the relocation table and also allows
+simpler compilers/assemblers.
+The size
bit determines the size of the segment base address and length
+entries. Currently the 16 bit size (size bit = 0) works for 6502 and
+65816 CPUs.
+
+The obj
bit distinguishes between object files and executables.
+An object file is used as assembler output that can be linked with
+other object files to build an executable or an object library.
+
+The simple
bit signals the loader that the load addresses have a specific form.
+This form fulfills the following conditions:
+
+ dbase = tbase + tlen + bbase = dbase + dlen ++This condition ensures that the loader can actually load the text and data segments in +one block, and can then use the same base address for the relocation of all three, the +text, data and bss segments. The
simple
mode bit is optional, in that when it is set the conditions
+must be fulfilled, but if not set the conditions may or may not be fulfilled.
+
+The chain
bit signals the loader that after the current o65 "file"
+there is another "file" appended to the actual file on disk. This way "multi-o65" files can be
+built. An "o65" file in a multi-o65 file is here now called "section".
+Chaining allows the following scenarios:
+
chain=0
.
+The chain
bit is optional, if it is set and a loader does not support it, the file
+may be rejected right away.
+It is recognized that for these purposes the loader must have a means of identifying
+different sections and their purposes. Currently there is no simple way except using the
+order of the sections in the file. A more complicated way would be to use optional headers
+in each section.
+
+The bsszero
bit tells the loader that the executable to be loaded requires the bss segment to be zeroed out. If it is not set, then the code must not assume any special value in the bss segment (which is the default behaviour for o65 version 1.2 and below). A loader that does not support zeroing out the bss segment must reject a file with this bit set.
+
+The CPU2
bits determine the type of 6502 CPU. 6502 core
means that
+only the originally documented 6502 opcodes are used. In addition the NMOS 6502
+signals that in addition to the code, some undocumented opcodes of the NMOS version are
+used. The other values indicate other versions of 6502 CPUs. Please see the appendix for an additional note.
+
+The two align
bits give the address boundary the segments can be
+placed. Even the 6502 needs this, as, for example, "jmp ($xxFF)" is
+broken. The align bits are valid for all of the segments.
+[Note: if reloc=1, then align should be 3. But if align=3, reloc need
+not be 1, because reloc switches to a simpler version of the relocation
+table. The reloc bit might be obsoleted in newer versions of this
+format. Though it should be set, if necessary.]
+
+All unused bits in the mode field must be zero. +
+Note that the header size is 26 if the size bit is zero and 44 if the +size bit is one. +
+The fixed sized struct is immediately followed by a list of header options. +Each header option consists of a single byte total length, a type byte +and some data bytes if needed. A single length byte of $00 ends the +header option list. +
+ ( + { ; optional options, more than one allowed + .byt olen ; overall length (including length and type + ; byte + .byt otype ; option type + [ .byt option_bytes ] + } + .byt $00 ; end of options marker (i.e. option len=0) + ) ++The header options currently defined/proposed are: + +
+- Filename: + type=0; len=strlen(filename_in_ascii)+3; content="filename_in_ascii",0 + The string contains the name of the object. + +- Operating System Header + type=1; len=? + the first data byte is the OS type: + 1 OSA/65 header supplement + 2 Lunix header supplement + 3 CC65 generic module (new in v1.3) + 4 opencbm floppy modules (new in v1.3) + [others to follow?] + the following data contains OS specific information. + A suggested data byte is the OS version as second byte. + +- Assemblerprogram: + type=2; len=strlen(ass)+3; content="ass",0 + The string contains the name of the assembler resp. linker that produced + this file/object. + For example (syntax see below) + .fopt 2, "xa 2.1.1g",0 + becomes + 0c 02 78 61 20 32 2e 31 2e 31 67 00 + in the file. + +- Author: + type=3; len=strlen(author)+3; content="author",0 + The string contains the author of the file. + +- Creation data: + type=4; len=strlen(date)+3; content="date_string",0 + The string contains the creation date in format like: + "Sat Dec 21 14:00:23 MET 1996", where we have the day, Month, date, + time, timezone and year. See output of `date`... ++
+The text and data segments are just the assembled code. +The only difference between text and data segments is the read/write mode +of the two segments. Therefore, to be compliant to this file format, +self-modifying code goes into the data segment. +
+
+The next list is an ASCII list of labels that are referenced in this file +but not defined. The lists is preceeded with the number of undefined labels +(16 or 32 bits, according to the mode.size bit). +
+undef_list: number_of_undefined_labels.s + "undefined_label1",0 + "undefined_label2",0 + ... ++
+The character encoding and length of the names of the undefined labels should be +appropriate for the target platform, that may define additional constraints. +The encoding must allow zero-terminated byte arrays +as string representations. To allow short loading times, the names should not be +exceedingly long. +
++The relocation tables are the same format for the two segments, text and +data. In general a relocation entry consists of the offset from the +previous relocation address to the next one, the type of the relocation +and additional info. Relocation not only defines the relocation when +moving object code to a different address, but also filling in the +undefined references. +
+Each table starts at relocation address = segment base address -1. +I.e. if the segment base address is $1000 for example, the first entry +has an offset computed from base address-1 = $0fff. +The offset to the next relocation address is the first byte of each +entry. If the offset is larger than 254 (i.e. 255 or above), than a +255 is set as offset byte, the offset is decremented by 254 (note the +difference) and the entry is started again. +
+{ [255,...,255,] offset of next relocation (b), typebyte|segmentID [, low_byte] }+ ++where typebyte has the bits 5, 6 and 7 and is one of +
+WORD $80 2 byte address +HIGH $40 high byte of an address +LOW $20 low byte of an address +SEGADR $c0 3 byte address (65816) +SEG $a0 segment byte of 3 byte address ++The segmentID stands for the segment the reference points to: +
+0 undefined +1 absolute value +2 text segment +3 data segment +4 bss segment +5 zero segment ++(Of course the absolute value will never appear in a relocation table, +but this value is necessary for the exported list) +
+If the type is HIGH, the low byte of the value is stored behind the +relocation table entry, if bytewise relocation is allowed (header mode +field bit 14). If only pagewise relocation is allowed, then only HIGH +relocation entries can occur, and the low byte is implicitely set zero +(i.e. it is _not_ saved in the relocation table). +
+If the type is SEG, then the two lower bytes of the three byte segment +address are stored behind the entry in the relocation table, lower byte +first. +
+ + +If the segment is "undefined", the typebyte is immediately followed +by the two (mode size=0) or four (mode size=1) byte value index +in the undefined references list. If it is a high byte relocation, +the low byte is saved behind the index value. The index value +determines the undefined reference, which must be looked up by the +loader. +
+The value taken from the relocation address in the segment, together with +the low byte from the relocation table (if HIGH entry) form the address +used if the segment would be used unrelocated. To relocate the segment, +the difference between the relocated segment base address and the segment +base address from the file is then added to the above address. The result +is again saved in the segment. +
+A zero offset byte ends the relocation table. The first offset is computed +from the segment base address-1, to avoid a 0 value in the first entry. +
+Note that direct addressing modes do not generate entries in the +relocation table. instead it is assumed that the 65816 direct register +holds the correct value (i.e. zero segment base address) when running +this program. +
+Example (for file contents see appendix B.1): +
+Segment Base address in file (header.tbase) is $1000. +The start address of the text segment after relocation is real.tbase = $1234. +
+Now the first (unrelocated) address at which a relocation should take +place is here: +
+$1222 A9 23 lda #>vector ++ +To compute the relocation table entry, we have to identify the address +that must be relocated. This is not the opcode address $1222, but the +address of the parameter to the offset, i.e. $1223. The first relocation +table entry offset is calculated from the start of the segment minus one, i.e. +$0fff in this case. The offset to be stored in the relocation table +therefore is $1223-$0fff=$224. This is larger than $fe, therefore the +first byte in the relocation table entry is $ff, and the offset is +decremented by $fe, which results in $126. This again is larger than +$fe, so the next byte in the relocation table entry is $ff again and the +offset is decremented by $fe, resulting in $28. This offset becomes the +next byte in the relocation table entry. +The offset for the next relocation table entry is then computed from $1223, +because this is the last relocation address. +
+Now we reference the high byte of an address, lets say vector=$23d0 (not +relocated), in the text segment. Therefore the relocation type becomes +'HIGH | text_segmentID = $42', which is the next byte. Because we are +referencing a high byte of an address, the low byte of the unrelocated +address is saved behind the typebyte in the relocation entry. This byte +is missing when referencing a low byte or address. +
+The relocation table entry is now: +
+$ff, $ff, $28, $42, $d0. ++When actually doing the relocation, the relocation pointer is initialized +to real.tbase-1 = $1233 (this value correlates to the unrelocated text segment +start minus one, $0fff). Then we add the offset of $224 from the first +relocation table entry, which brings +us to $1457, where the parameter byte of the opcode is after loading +the file to $1234. We now have to compute the new address, where
vector
+is after relocation. So we take the unrelocated low byte from the
+relocation table ($d0) and the high byte from $1457 ($23).
++vector_file = ($23 << 8) + $d0 = $23d0 ++To this value we add +the difference between the address the program is assembled to and the +real load address: +
+vector_relocated = vector_file + (real.tbase - header.tbase) + = $23d0 + ($1234 - $1000) + = $23d0 + $234 + = $2604 ++From this value the high byte is then written back to the address $1457. +Had we not saved the low byte in the relocation table, and only added +the high bytes, we would have missed the carry bit that increments +the high byte in this case! +
+Had "vector" now been an undefined reference, and "vector" would be +the second label in the undefined references list, we would get the +following relocation table entry (assuming mode.size=0): +
+$ff, $ff, $28, $40, $02, $00, $00 ++The value computed with the above formula for vector_file is now added +to the address the label "vector" now really has (This must of course +be looked up into an external table or list). +Had the opcode been "LDA #>vector+$567", then the low byte in the relocation +table would be $67, while the high byte in the opcode would be $05. +This value would result in vector_file and the real address of "vector" +would be added before wrting back the high byte to the opcode. +
+ +
+The global list is a list of names, together with the target segment +and the offset in the segment for each name. It is preceeded with the +number of exported labels. This allows the loader to allocate a table +large enough, if needed. The number of labels and the offset value +are 16 bit or 32 bit values according to the size bit in the header mode +field. The segmentID is a byte value and the same as in the relocation +table entry (see section 2.6.3). +
+ number_of_exported_labels.s + "global_label_name_in_asc1",0, segmentID.b, value.s + ... ++ +
Note: an undefined reference can not be exported. Doing this would lead +to circular references for example when linking multiple object files, +therefor it is not allowed. +
+The character encoding and length of the names of the undefined labels should be +appropriate for the target platform, that may define additional constraints. +The encoding must allow zero-terminated byte arrays +as string representations. To allow short loading times, the names should not be +exceedingly long. +
+ ++The assembler source format is a suggestion only. It will be implemented +in xa65, a cross assembler for 6502 CPUs running on Unix/Atari ST/Amiga +as a reference platform. +
+The assembler provides a way to embed absolute address code in relocatable +code. This is needed when code should be copied to a specific location +known at assemble time. +There also is a way to make a file 'romable'. You can give the start +address of the _file_ in ROM, and the assembler automatically sets +the text segment start address to where the code will be in the ROM. +Of course, the other segments must be taken care of with -b? command +line parameter, that set the segment start address. +
+
+When the assembler is started in relocatable mode, everything is put into +a .o65 relocatable file. All address references generate relocation table +entries. If a "*= value" pseudo opcode is encountered, +then the assembler switches to absolute mode. The following opcodes don't +generate relocation table entries. If a "*=" without a value is read, +then the assembler switches back to relocatable mode. The relocation +program counter is increased with the length of the absolute part and +the absolute code is embedded between the relocatable parts. +
+
+This is dropped - too complicated. Should better be done with some +objdump or linker programs or so. +
+
+Before any opcode (after starting in relocatable mode, or after a .reloc +opcode), a header option can be set by: +
+ .fopt byte1, byte2, ... ++The header option length is automatically set by the assembler. +An example for an file author entry: +
+ .fopt 3, "Andre Fachat",0 ++The 3 is the type byte for the author header option. The last zero ends +the name. The assembler can be configured to automatically include an +assembler header option into a file header. +
+
+The assembler switches between the different segments by the means of +".text", ".data", ".bss" and ".zero" pseudo opcodes. After starting in +relocatable mode, the assembler is in the text segment. +
+The text segment contains the program code. Data holds the initialized data, +while bss and zero segments contain uninitialized data for normal/zeropage +address space. +Everything that is between one of these segment opcodes and the next segment +opcode gets into the corresponding segment, i.e. labels, assembled code etc. +The text and data segments are saved in the file, while for the bss and +zero segments only the length is saved in the file. +
+The assembler should issue a warning when a direct addressing mode +is used without a zero segment address and vice versa for 65816 CPUs. +
+
+One problem with the 6502 is, that it cannot load an address within one +step or assembler opcode. So an address is loaded with standard byte +opcodes, like "lda #<label". But how do we decide, whether "label" +is an address or not, and what do we if we get something like +"lda #zp_label + 12 * label2"? +
+The assembler is now intelligent enough to evaluate such expressions +and check for: +
+- no address label : ok, absolute +- one address label, only add to label : ok, relocate +- difference between two addresses : If addresses in same segment, compute + diff and set absolute, otherwise bail +- everything else : warning ++This way there is no change in syntax. Address labels are distinguished +by using the "label:" syntax, as opposed to "label = value". +Also, if the assembler is capable of doing so, an address label may be +defined by "label opcode", i.e. without a colon. +
+
+The 6502 has the problem that some opcodes (e.g. "JMP ($xxFF)" are +broken, if the address given is at some (odd) address. But when loading +a relocatable file, one cannot know if an address will be odd or even. +Therefore there is a new opcode, +
+ .align 2 ++that aligns the next address at the given address boundary. Valid +values are 2, 4, and 256. For the 6502 the opcode may insert NOP +operations ($EA opcodes) until the alignment is reached. In addition +the header align bits must be set appropriately. +
+
+This file is surely not the optimum and could be improved. Also the +header option "assigned numbers" should be added here. +
+For this reason the author, André Fachat, will function as a +clearing point, where problems can be discussed and numbers can be assigned. +
+ mode.4-7 : CPU2 0000 = 6502 core (no undocumented opcodes) + 0001 = 65C02 /w some bugfix, no illegal opcodes + 0010 = 65SC02 (enhanced 65C02), some new opcodes + 0011 = 65CE02 some 16bit ops/branches, Z register is modifiable + 0100 = NMOS 6502 (including undocumented opcodes) + 0101 = 65816 in 6502 emulation mode + 011x = reserved + + 1000 = 6809 + + 1010 = Z80 + + 1101 = 8086 + 1110 = 80286 + ^^^^ + |||+- Bit 4 + ||+-- Bit 5 + |+--- Bit 6 + +---- Bit 7 + ++
+ +Late binding means that during the assembler run the values of some +variables are not known. Instead these variable values are filled in +when the program file is loaded into the system. +
+As an example let's discuss an example for a program that needs to +access some hardware at the expansion port of the C64. The hardware +is located either at IO1 ($de00) or IO2 ($df00) depending on some +hardware switch. To allow to use only one executable for the program, +it uses a variable "IOPORT" that is not defined in the program itself, +but set by the o65 loader using late binding. +
++The program accesses the io port is using the variable: +
+ lda IOPORT ++When assembling this one line program, the assembler is told to accept the +variable IOPORT as undefined. In
xa
this is done
+using the -L
option:
++ xa -R -LIOPORT -o program.o65 program.a65 ++Then
program.o65
contains relocatable code with an
+undefined reference named IOPORT
. Every time the
+code uses this variable, the relocation table contains an entry
+with a reference to the label in the undefined reference table.
+
+The resulting file looks like: +
+00000000 01 00 6f 36 35 00 00 00 00 10 03 00 00 04 00 00 |..o65...........| +00000010 00 40 00 00 04 00 00 00 00 00 00 ad 00 00 01 00 |.@..............| +00000020 49 4f 50 4f 52 54 00 02 80 00 00 00 00 00 00 |IOPORT.........| ++The first six bytes are the magic number. After that the mode bits +(bytes seven and eight) are all zero. The text segment starts at $1000 +and has a length of 3. The data segment starts at $0400 with a length of zero, +and the bss segment starts at $4000 with a length of zero too. +The zerospace segment starts at $0004, but also with a length of zero. +The minimum stack size needed is zero too. The list of header options +starts at file offset $001a. As the first byte is zero, there is no header +option. After this follows the text segment containing the bytes +$ad $00 $00. If the data segment size would not be zero, the data segment +would come here. +Then the undefined references list follows. The first two bytes (at file offset +$001e) state that there is a single undefined reference, and the name of the +undefined reference "IOPORT" followed by the ending zero byte is stored after +this number. Then the relocation table follows. The first byte in the relocation +table is $02. As the relocation table offset starts at
tbase-1
this
+means that the first relocation position is at the second byte (offset 1) in the
+text segment. The type byte $80 defines that it is an undefined, absolute
+reference. The next two bytes define the index in the undefined reference table,
+in this case $0000, which means that the reference IOPORT
is
+referenced. The next byte is zero, signalling the end of the text segment
+relocation table. At file offset $002b the relocation table for the data
+segment starts. As the first byte is zero, there is no relocation entry
+for the data segment (obviously, as the data segment is empty). After this
+relocation table the number of exported globals follows. This is zero, as
+there is no exported global variable.
+
+When loading the file, the loader must know in advance what value
+IOPORT should be assigned. This is not further discussed here.
+When the loader loads the file, and recognizes the name
+IOPORT
in the undefined references table, it remembers
+the index of this name in the table. Then, when the relocation table
+contains a reference to the undefined label with the index value for
+IOPORT
, the value for that variable is then used
+in the relocation.
+
+If, for example the loader knows that IOPORT=$de00
, then the
+text segment is relocated to
+
+ $ad $00 $de ++If the source is changed for example to +
+ lda IOPORT+1 ++one byte in the the file changes: +
+00000010 00 40 00 00 04 00 00 00 00 00 00 ad 01 00 01 00 |.@..............| + ^^ ++If the file is then relocated, the loader adds the value in the opcode in the +text segment ($0001 in this case) to the value resuling from the reference resolution +(
IOPORT
in this case). The resulting code then becomes:
++ $ad $01 $de ++ +
The example source file is +
+.text + .dsb $222,$aa + + lda #>vector + + .dsb $23d0-$1224,$55 + + vector = *; + ++Using the command +
+ xa -R -o test2.o65 test2.a65 ++results in this file +
+00000000 01 00 6f 36 35 00 00 00 00 10 d0 13 00 04 00 00 |..o65...........| +00000010 00 40 00 00 04 00 00 00 00 00 00 aa aa aa aa aa |.@..............| +00000020 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................| +* +00000230 aa aa aa aa aa aa aa aa aa aa aa aa aa a9 23 55 |..............#U| +00000240 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| +* +000013e0 55 55 55 55 55 55 55 55 55 55 55 00 00 ff ff 28 |UUUUUUUUUUU....(| +000013f0 42 d0 00 00 01 00 76 65 63 74 6f 72 00 82 d0 23 |B.....vector...#| +00001400 ++After relocating the file with +
+ ld65 -bt 4660 test2.o65 ++to the new address $1234 (using
ld65
from the xa
+package), the resulting file is:
++00000000 01 00 6f 36 35 00 00 00 34 12 d0 13 00 10 00 00 |..o65...4.......| +00000010 00 40 00 00 02 00 00 00 00 00 00 aa aa aa aa aa |.@..............| +00000020 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa |................| +* +00000230 aa aa aa aa aa aa aa aa aa aa aa aa aa a9 26 55 |..............&U| +00000240 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU| +* +000013e0 55 55 55 55 55 55 55 55 55 55 55 00 00 ff ff 28 |UUUUUUUUUUU....(| +000013f0 42 04 00 00 01 00 76 65 63 74 6f 72 00 82 d0 23 |B.....vector...#| ++which confirms the addresses computed above. +
+(to be done with reference assembler) + diff --git a/usr/share/doc/cc65/webdoc/funcref-1.html b/usr/share/doc/cc65/webdoc/funcref-1.html new file mode 100644 index 0000000..0ec7009 --- /dev/null +++ b/usr/share/doc/cc65/webdoc/funcref-1.html @@ -0,0 +1,51 @@ + + +
+ +cc65 is a C compiler for 6502 based systems. It implements a subset of the ISO +C standard plus additional functions specially crafted for 6502 systems or +just some of the supported machines. This function refrence describes the +available functions together with any limitations.
+For an overview about the available libraries, their purpose, and any +differences to the ISO standard, please have a look at the +cc65 Library Overview.
+Note: Standard C functions are listed here, but not described in detail. +Since these functions behave identical on all standard compliant systems, they +are described in any book covering standard C.
+Each entry for a function contains a detailed description
++
++ + + ++
+- Function
Summary of what function does.
+- Header
The header file that contains the declaration.
+- Declaration
Describes the needed header files and declaration of the +function.
+- Description
Description of the function.
+- Limits
Limits.
+- Availability
The availability of the function.
+- See also
Other related functions.
+- Example
A piece of actual code using the function.
+
c16.h
(incomplete)
+ + ++
++ + + ++
+- Function
Unload an extended memory driver.
+- Header
+
+em.h
- Declaration
+
unsigned char __fastcall__ em_unload (void);
- Description
The function unloads a loaded extended memory driver and +frees all memory allocated for the driver.
+- Limits
+
+
+ +- The function does nothing if no driver is loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Prepare an extended memory page for use.
+- Header
+
+em.h
- Declaration
+
void* __fastcall__ em_use (unsigned page);
- Description
The function maps one page of extended memory into linear +memory and returns a pointer to the page frame. This function is similar to +
++em_map
, but will not transfer data into the +actual memory window in the assumption that the existing data is wrong or +will get overwritten.- Limits
+
+
+ +- Calling
+em_use
will invalidate the memory window, so if you +made any changes to the data in the window, call+em_commit
first, or the changes are lost.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The function produces undefined results if no extended memory driver is +loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Terminate the program.
+- Header
- +
- Declaration
+
void __fastcall__ exit (int status);
- Description
+
exit
terminates the program. The argument specifies the +return code of the program. Before termination, all files are closed, buffered +output is written and any functions registered with+atexit
are called. Common values for status areEXIT_SUCCESS
and +EXIT_FAILURE
which are also defined in+stdlib.h
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- It depends on the host machine if the program return code can be +evaluated or is ignored.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Switch the C128 into 2MHz mode.
+- Header
- +
- Declaration
+
void fast (void);
- Description
The function will switch the clock of the C128 to 2MHz. This +will nearly double the speed compared to slow mode.
+- Limits
+
+
+ +- The function is specific to the C128.
+- 2MHz clock will not work in 40 column mode.
+- Availability
C128
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the end-of-file indicator of a stream.
+- Header
- +
- Declaration
+
int __fastcall__ feof (FILE* f);
- Description
+
feof
tests the end-of-file indicator ofthe stream +f
, and returns a non zero value if it is set.- Limits
+
+
+ +- The indicator is set only after a read past the end of a file is +attempted.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the error indicator of a stream.
+- Header
- +
- Declaration
+
int __fastcall__ ferror (FILE* f);
- Description
+
ferror
tests the error indicator of the stream +f
, and returns a non zero value if it is set.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the file handle used by a stream.
+- Header
- +
- Declaration
+
int __fastcall__ fileno (FILE* f);
- Description
The
+fileno
function returns the file handle used +internally by a C stream. This file handle (an integer) can be used as a +handle for the POSIX input/output functions.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Mixing C file I/O functions and POSIX file I/O functions for the same +file may have unpredictable results.
+- Availability
POSIX 1003.1
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Free a block of dynamic memory.
+- Header
- +
- Declaration
+
void __fastcall__ free (void* block);
- Description
Free a block of dynamic memory previously allocated with +
++malloc
,+calloc
+or+realloc
. As an exception, if the passed +pointer isNULL
, no action is performed.- Limits
+
+
+ +- Passing an already free'd block to
+free
again will cause undefined +behaviour and may crash your program.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+_heapadd, +_heapblocksize, +_heapmaxavail, +_heapmemavail, +calloc, +malloc, +realloc
+- Example
None.
+
+
++ + + ++
+- Function
The function returns the operating system, the program runs on.
+- Header
- +
- Declaration
+
unsigned char get_ostype (void);
- Description
+
get_ostype
is machine dependent and does not exist for +all supported targets. If it exists, it returns a number that identifies the +operating system or machine type, the program runs on. The machine dependent +header files define constants that can be used to check the return code.- Limits
+
+
+ +- The function does not exist on all platforms.
+- The return codes are platform dependent.
+- Availability
cc65 (not all platforms)
+- Example
None.
+
+
++ + + ++
+- Function
Return a value from the environment.
+- Header
- +
- Declaration
+
char* __fastcall__ getenv (const char* name);
- Description
The function searches the environment for an entry that +matches
+name
and returns its value. The environment consists of a list +of strings in the formname=value
. If there is no match,getenv
+returnsNULL
.- Limits
+
+
+ +- What exactly is stored in the environment depends on the machine the +program is running on.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- Example
None.
+
c64.h
+
+
++ + + ++
+- Function
Determine on which CPU the program is running.
+- Header
- +
- Declaration
+
unsigned char getcpu (void);
- Description
The function checks on which CPU the code is running. It +returns one of the constants +
+
+ +- +
CPU_6502
- +
CPU_65C02
- +
CPU_65816
- Limits
+
+
+ +- Other, more exotic CPU types are not disinguished.
+- Availability
cc65
+- Example
None.
+
+
++ + + ++
+- Function
Move the text mode cursor to a new X position.
+- Header
- +
- Declaration
+
void __fastcall__ gotox (unsigned char x);
- Description
The function moves the text mode cursor to the specified X +position while leaving the Y position untouched. The leftmost position on the +screen has the coordinate 0.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Invalid values for the X position (out of screen coordinates) may +lead to undefined behaviour.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Move the text mode cursor to a new position.
+- Header
- +
- Declaration
+
void __fastcall__ gotoxy (unsigned char x, unsigned char y);
- Description
The function moves the text mode cursor to the specified +position. The leftmost position on the screen has the X coordinate 0, the +topmost line has the Y coordinate 0.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Invalid values for any of both coordinates (out of screen positions) may +lead to undefined behaviour.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Move the text mode cursor to a new Y position.
+- Header
- +
- Declaration
+
void __fastcall__ gotoy (unsigned char x);
- Description
The function moves the text mode cursor to the specified Y +position while leaving the X position untouched. The uppermost position on the +screen has the coordinate 0.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Invalid values for the Y position (out of screen coordinates) may lead +to undefined behaviour.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a letter or digit.
+- Header
- +
- Declaration
+
int __fastcall__ isalnum (int c);
- Description
The function returns a value of zero if the given argument +is a letter or digit. The return value is non zero if the character +is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing +the macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a letter.
+- Header
- +
- Declaration
+
int __fastcall__ isalpha (int c);
- Description
The function returns a value of zero if the given argument +is a letter. The return value is non zero if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is in the ASCII (0..127) range.
+- Header
- +
- Declaration
+
int __fastcall__ isascii (int c);
- Description
The function returns a value of zero if the given argument +is in the range 0..127 (the range of valid ASCII characters) and a non zero +value if not.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a space or tab.
+- Header
- +
- Declaration
+
int __fastcall__ isblank (int c);
- Description
The function returns a value of zero if the given argument +is a space or tab character. The return value is non zero if the character +is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
cc65
+- See also
+isalnum, +isalpha, +isascii, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a control character.
+- Header
- +
- Declaration
+
int __fastcall__ iscntrl (int c);
- Description
The function returns a value of zero if the given argument +is a control character. The return value is non zero if the character +is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a digit.
+- Header
- +
- Declaration
+
int __fastcall__ isdigit (int c);
- Description
The function returns a value of zero if the given argument +is a digit. The return value is non zero if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
cbm510.h
+
+ + + ++
++ + + ++
+- Function
Check if a given character is a printable character (except +space).
+- Header
- +
- Declaration
+
int __fastcall__ isgraph (int c);
- Description
The function returns a value of zero if the given argument +is a printable character with the exception of space. The return value is non +zero if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +islower, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a lower case letter.
+- Header
- +
- Declaration
+
int __fastcall__ islower (int c);
- Description
The function returns a value of zero if the given argument +is a lower case letter. The return value is non zero if the character is +anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +isprint, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a printable character.
+- Header
- +
- Declaration
+
int __fastcall__ isprint (int c);
- Description
The function returns a value of zero if the given argument +is a printable character (this includes the space character). The return value +is non zero if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +ispunct, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a printable character but not a +space or an alphanumeric character.
+- Header
- +
- Declaration
+
int __fastcall__ ispunct (int c);
- Description
The function returns a value of zero if the given argument +is a printable character, but not a space or anything alphanumeric. The return +value is non zero if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +isspace, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a a white-space character.
+- Header
- +
- Declaration
+
int __fastcall__ isspace (int c);
- Description
The function returns a value of zero if the given argument +is a white space character. The return value is non zero if the character is +anything else. The standard white space characters are: space, formfeed ('\f'), +newline ('\n'), carriage return ('\r'), horizontal tab ('\t'), and vertical tab +('\v').
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isupper, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is an upper case letter.
+- Header
- +
- Declaration
+
int __fastcall__ isupper (int c);
- Description
The function returns a value of zero if the given argument +is an upper case letter. The return value is non zero if the character is +anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isxdigit
+- Example
None.
+
+
++ + + ++
+- Function
Check if a given character is a hexadecimal digit.
+- Header
- +
- Declaration
+
int __fastcall__ isxdigit (int c);
- Description
The function returns a value of zero if the given argument +is a hexadecimal digit (0..9, a..f and A..F). The return value is non zero +if the character is anything else.
+- Limits
+
+
+ +- When compiling with
+-Os
the function is actually a macro. The +inline sequence generated by the macro will not work correctly for values +outside the range 0..255. Note: The constantEOF
is not part of +this range. The non inline function may be accessed by#undef
'ing the +macro.- When compiling without
+-Os
, the function is only available as +fastcall function, so it may only be used in presence of a prototype.- Availability
ISO 9899
+- See also
+isalnum, +isalpha, +isascii, +isblank, +iscntrl, +isdigit, +isgraph, +islower, +isprint, +ispunct, +isspace, +isupper
+- Example
None.
+
+
++ + + ++
+- Function
Convert an integer into a string.
+- Header
- +
- Declaration
+
char* __fastcall__ itoa (int val, char* buf, int radix);
- Description
+
itoa
converts the integerval
into a string using +radix
as the base.- Limits
+
+
+ +- There are no provisions to prevent a buffer overflow.
+- If
+val
containsINT_MIN
, the behaviour is undefined.- The function is non standard, so it is not available in strict ANSI mode. +You should probably use
+sprintf
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the number of joysticks supported by the current driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_count (void);
- Description
The function returns a the number of joysticks supported +by the current joystick driver.
+- Limits
+
+
+ +- A joystick driver must be loaded using +joy_load_driver before calling this function.
+- The function returns the number of joysticks supported by the driver. +There's no way to check for the number of actually connected joysticks.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Install an already loaded driver and return an error code.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_install (void* driver);
- Description
The function installs a driver that was already loaded into +memory (or linked statically to the program). It returns an error code +(
+JOY_ERR_OK
in case of success).- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
cbm610.h
+
+ + + ++
++ + + ++
+- Function
Load a driver from disk and install it.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_load_driver (const char* driver);
- Description
The function loads a driver with the given name from disk +and installs it. An error code is returned, which is
+JOY_ERR_OK
if the +driver was successfully loaded and installed.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read the status of a joystick.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_read (unsigned char joystick);
- Description
The function reads the status bits for a joystick. The number +of the joystick is passed as parameter. The result may be examined by using one +of the
+JOY_xxx
macros from +joystick.h.- Limits
+
+
+ +- A joystick driver must be loaded using +joy_load_driver before calling this function.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Uninstall the current joystick driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_uninstall (void);
- Description
The function uninstalls the currently installed joystick +driver. It does not remove the driver from memory. The function returns an +error code, which is
+JOY_ERR_OK
if the driver was successfully uninstalled.- Limits
+
+
+ +- A joystick driver must be installed using +joy_install before calling this function.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Uninstall, then unload the current joystick driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ joy_unload (void);
- Description
The function uninstalls the currently installed joystick +driver and removes it from memory. An error code is returned, which is +
+JOY_ERR_OK
if the driver was successfully uninstalled.- Limits
+
+
+ +- A joystick driver must be loaded using +joy_load_driver before calling this function.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Check if there's a key waiting in the keyboard buffer.
+- Header
- +
- Declaration
+
unsigned char kbhit (void);
- Description
The function returns a value of zero if there is no character +waiting to be read from the keyboard. It returns non zero otherwise.
+- Limits
+
+
+ +- If the system does not support a keyboard buffer (most systems +do), the function is rather useless.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Returns the absolute value of a long integer.
+- Header
- +
- Declaration
+
long __fastcall__ labs (long v);
- Description
+
labs
returns the absolute value of the argument passed to +the function.- Limits
+
+
+ +- The return value is undefined if
+LONG_MIN
is passed to the function.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+abs
+- Example
None.
+
+
++ + + ++
+- Function
Convert a long integer into a string.
+- Header
- +
- Declaration
+
char* __fastcall__ ltoa (long val, char* buf, int radix);
- Description
+
itoa
converts the long integerval
into a string +usingradix
as the base.- Limits
+
+
+ +- There are no provisions to prevent a buffer overflow.
+- If
+val
containsLONG_MIN
, the behaviour is undefined.- The function is non standard, so it is not available in strict ANSI mode. +You should probably use
+sprintf
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Returns a pointer to the current locale structure.
+- Header
- +
- Declaration
+
struct lconv* localeconv (void);
- Description
+
localeconv
returns a pointer to the current locale +structure.- Limits
+
+
+ +- cc65 supports only the "C" locale, so even after setting a new locale +using
++setlocale
, the structure returned will +always be the same.- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Non local goto.
+- Header
- +
- Declaration
+
void __fastcall__ longjmp (jmp_buf buf, int retval);
- Description
The
+longjmp
function restores a program context from the +data inbuf
, which must have been set by a preceeding call to ++setjmp
. Program execution continues as if the +call to+setjmp
has just returned the value +retval
.- Limits
+
+
+ +- If the parameter
+retval
is zero, the function will behave as if it +was called with a value of one.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Allocate dynamic memory.
+- Header
- +
- Declaration
+
void* __fastcall__ malloc (size_t size);
- Description
+
malloc
allocates size bytes on the heap and returns a +pointer to the allocated memory block. On error (not enough memory available), +malloc
returnsNULL
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+_heapadd, +_heapblocksize, +_heapmaxavail, +_heapmemavail, +calloc, +free, +realloc, +strdup
+- Example
None.
+
conio.h
+
+
++ + + ++
+- Function
Search for a character in a block of raw memory.
+- Header
- +
- Declaration
+
void* __fastcall__ strchr (const void* mem, int c, size_t count);
- Description
The
+memchr
function locates the first occurrence ofc
+(converted to a char) in the block of raw memory string pointed to bymem
+that is of sizecount
. Upon completion, the function returns a pointer to +the character found, or a null pointer if the character was not found.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Copy a memory area.
+- Header
- +
- Declaration
+
void* __fastcall__ memcpy (void* dest, const void* src, size_t count);
- Description
+
memcpy
copiescount
bytes from the memory area +pointed to bysrc
into the memory area pointed to bydest
. It returns +dest
.- Limits
+
+
+ +- The result is undefined if the memory areas do overlap. Use +
++memmove
to copy overlapping memory areas.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Copy a memory area.
+- Header
- +
- Declaration
+
void* __fastcall__ memmove (void* dest, const void* src, size_t count);
- Description
+
memmove
copiescount
bytes from the memory area +pointed to bysrc
into the memory area pointed to bydest
. It returns +dest
.- Limits
+
+
+ +- While
+memmove
allows the memory areas to overlap, it has some +additional overhead compared to+memcpy
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Fill a memory area.
+- Header
- +
- Declaration
+
void* __fastcall__ memset (void* p, int val, size_t count);
- Description
+
memset
fills the memory area pointed to byp
with +the valueval
. The function returnsp
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Free a relocatable module.
+- Header
- +
- Declaration
+
void __fastcall__ mod_free (void* module);
- Description
The function will free a module loaded into memory by use of +the
++mod_load
function.- Limits
+
+
+ +- The pointer passed as parameter is the pointer to the module memory, +not the pointer to the control structure.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Load a relocatable module.
+- Header
- +
- Declaration
+
unsigned char mod_load (struct mod_ctrl* ctrl);
- Description
The function will load a code module into memory and relocate +it. The function will return an error code. If
MLOAD_OK
is returned, the +outgoing fields in the passedmod_ctrl
struct contain information about +the module just loaded. Possible error codes are: ++
+ +- +
MLOAD_OK
- Module load successful- +
MLOAD_ERR_READ
- Read error- +
MLOAD_ERR_HDR
- Header error- +
MLOAD_ERR_OS
- Wrong operating system- +
MLOAD_ERR_FMT
- Data format error- +
MLOAD_ERR_MEM
- Not enough memory- Limits
+
+
+ +- The +ld65 linker is needed to create +relocatable o65 modules for use with this function.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Specify a bounding box for the mouse cursor.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_box (int minx, int miny, +int maxx, int maxy);
- Description
The function allows to set a bounding box for mouse movement.
+- Limits
+
+
+ +- The function does not check if the mouse cursor is currently within the +given rectangle. Placing the mouse cursor within the bounding box is the +responsibility of the programmer.
+- While the bounding box may be larger than the actual screen size, the +standard mouse cursor draw routines may fail to set the cursor to coordinates +outside of the screen area. Depending on the platform, you may have to supply +your own mouse cursor routines.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return a bit mask encoding the state of the mouse buttons.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_buttons (void);
- Description
The function returns a bit mask that encodes the state of the +mouse buttons. You may use the
+MOUSE_BTN_XXX
flags to decode the function +return value.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return a readable error message for an error code.
+- Header
- +
- Declaration
+
const char* __fastcall__ mouse_geterrormsg (unsigned char +code);
- Description
The function returns an error message (in english) for the +error code passed parameter.
+- Limits
+
+
+ +- The function will return "Unknown error" for invalid error codes.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Hide the mouse pointer.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_hide (void);
- Description
The function hides the mouse pointer. It manages a counter +that is shared between
++mouse_show
and +mouse_hide
so that every call call tomouse_hide
must be followed by +a call to+mouse_show
to make the mouse cursor +visible.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
ctype.h
+
+
++ + + ++
+- Function
Return the state of the mouse buttons and the position of the +mouse.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_info (struct mouse_info* info);
- Description
The function returns the state of the mouse buttons and the +position of the mouse in the
+mouse_info
structure passed as parameter.- Limits
+
+
+ +- The
+mouse_info
struct is a superset of themouse_pos
struct, +so if you just need the mouse position, call+mouse_pos
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Install an already loaded mouse driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_install (const struct +mouse_callbacks* c, void* driver);
- Description
The function installs an already loaded mouse driver and +returns an error code. The
+mouse_callbacks
structure passed as first +parameter contains pointers to routines needed to move or hide/show the mouse +pointer. Defaults for these routines are supplied by the library, so if you +can live with these defaults (which are platform specific), just pass a +pointer tomouse_def_callbacks
. The function may be used to install a +driver linked statically to the program.- Limits
+
+
+ +- Not all drivers are able to detect if the supported hardware is really +present.
+- After installing a driver, the mouse cursor is hidden.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Call the driver specific ioctl function.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);
- Description
The function calls the IOCTL entry in the mouse driver, +which is driver specific. The
+code
parameter will choose between +different IOCTL functions, and thedata
depends on code. The +function returns an error code. The purpose of this function is to allow +for driver specific extensions. See the documentation for a specific mouse +driver for supported ioctl calls.- Limits
+
+
+ +- Calling this function is non portable, because each driver may +implement different ioctl calls (or none at all).
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- Example
None.
+
+
++ + + ++
+- Function
Load and initialize a mouse driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_load_driver (const struct +mouse_callbacks* c, const char* driver);
- Description
Load a mouse driver into memory and initialize it. The +function returns an error code that tells if the call has been successful. The +
+mouse_callbacks
structure passed as first parameter contains pointers to +routines needed to move or hide/show the mouse pointer. Defaults for these +routines are supplied by the library, so if you can live with these defaults +(which are platform specific), just pass a pointer tomouse_def_callbacks
.- Limits
+
+
+ +- The driver is loaded by name, so currently you must know the type of +mouse that should be supported. There is no autodetect capability.
+- Not all drivers are able to detect if the supported hardware is really +present.
+- After installing a driver, the mouse cursor is hidden.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Move the mouse cursor to a specific position.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_move (int x, int y);
- Description
The function updates the mouse position. If the mouse cursor +is visible, it is shown at the new position.
+- Limits
+
+
+ +- The function does not check if the new position is within the bounding +box specified with
++mouse_box
.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the position of the mouse.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_pos (struct mouse_pos* pos);
- Description
The function returns the position of the mouse in the +
+mouse_pos
structure passed as parameter.- Limits
+
+
+ +- The
+mouse_pos
struct is a subset of themouse_info
struct, +so if you do also need the mouse buttons, call+mouse_info
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Show the mouse pointer.
+- Header
- +
- Declaration
+
void __fastcall__ mouse_show (void);
- Description
The function shows the mouse pointer. It manages a counter +that is shared between
++mouse_hide
and +mouse_show
. The mouse cursor is visible if there was one more call to +mouse_show
than to+mouse_hide
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Uninstall an already loaded mouse driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_install (void);
- Description
The function uninstalls an already loaded mouse driver but +don't removes it from memory.
+- Limits
+
+
+ +- If the driver has been loaded using
++mouse_load_driver
,+mouse_unload
+should be used instead ofmouse_uninstall
so the driver is also removed +from memory.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Unload a mouse driver.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ mouse_unload (void);
- Description
The function unloads a loaded mouse driver and frees all +memory allocated for the driver.
+- Limits
+
+
+ +- The function does nothing if no driver is loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Calculate the offset of a struct or union member.
+- Header
- +
- Declaration
+
size_t offsetof (type, member);
- Description
+
offsetof
calculates the address offset of astruct
+orunion
member.- Limits
+
+
+ +- The function is actually a macro.
+- Availability
ISO 9899
+- Example
None.
+
dbg.h
(incomplete)
+ + ++
++ + + ++
+- Function
Open and possibly create a file.
+- Header
- +
- Declaration
+
int open (const char* name, int flags, ...);
- Description
+
open
opens a file and returns the file descriptor +associated with it. On error, -1 is returned and an error code is stored in +errno
. Several flags may be passed toopen
that change the behaviour.- Limits
+
+
+ +- POSIX specifies an additional
+mode
argument that may be passed to +open, which is used as the permission mask when a new file is created. While +cc65 allows to pass this argument, it is ignored.- Availability
POSIX 1003.1
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read one byte from a location in the system bank.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ peekbsys (unsigned addr);
- Description
+
peekbsys
reads one byte from the given address in the +system bank (bank 15) of the CBM PET-II machines and returns it.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- This function may be a macro depending on the compiler options. The +actual function is accessible by #undef'ing the macro.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read one word from a location in the system bank.
+- Header
- +
- Declaration
+
unsigned __fastcall__ peekwsys (unsigned addr);
- Description
+
peekwsys
reads one word from the given address in the +system bank (bank 15) of the CBM PET-II machines and returns it. Following +the usual 6502 conventions, the low byte is read fromaddr
, and the +high byte is read fromaddr+1
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The order in which the two bytes are read is undefined.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Print an error message for the error in
+errno
.- Header
- +
- Declaration
+
void __fastcall__ perror (const char* s);
- Description
+
perror
prints an error message tostderr
. Ifs
+is notNULL
and not an empty string, it is printed followed by a colon and +a blank. Then the error message for the current contents oferrno
is +printed followed by a newline. The message output is the same as returned by ++strerror
with an argument oferrno
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Write one byte to a location in the system bank.
+- Header
- +
- Declaration
+
void __fastcall__ pokebsys (unsigned addr, unsigned char val);
- Description
+
pokebsys
writes one byte to the given address in the +system bank (bank 15) of the CBM PET-II machines.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Write one word to a location in the system bank.
+- Header
- +
- Declaration
+
void __fastcall__ pokewsys (unsigned addr, unsigned val);
- Description
+
pokewsys
writes one word to the given address in the +system bank (bank 15) of the CBM PET-II machines. Following the usual 6502 +conventions, the low byte ofval
is written toaddr
, and the +high byte is written toaddr+1
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The order in which the two bytes are written is undefined.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Sort an array.
+- Header
- +
- Declaration
+
void __fastcall__ qsort (void* base, size_t count, +size_t size, int (*compare) (const void*, const void*));
- Description
+
qsort
sorts an array according to a given compare +functioncompare
.base
is the address of the array,count
+is the number of elements,size
the size of an element andcompare
+the function used to compare the members.- Limits
+
+
+ +- If there are multiple members with the same key, the order after calling +the function is undefined.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Send a signal to the executing program.
+- Header
- +
- Declaration
+
int __fastcall__ raise (int sig);
- Description
+
raise
sends the given signal to the program. If the +program has installed a signal handler for the signal, this signal handler +will be executed. If no handler has been installed, the default action for +the raised signal will be taken. The function returns zero on success, +nonzero otherwise.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return a pseudo random number.
+- Header
- +
- Declaration
+
int rand (void);
- Description
The function returns a pseudo random number +between 0 and
+RAND_MAX
(exclusive).- Limits
+
+ +- Availability
ISO 9899
+- See also
+_randomize, +srand
+- Example
None.
+
+
++ + + ++
+- Function
Change the size of an allocated memory block.
+- Header
- +
- Declaration
+
void* __fastcall__ realloc (void* block, size_t size);
- Description
+
realloc
changes the size of the memory block pointed to +byblock
tosize
bytes. Ifblock
isNULL
,realloc
+behaves as ifmalloc
had been called. Ifsize
is zero,realloc
+behaves as iffree
had been called. On error (not enough memory +available),realloc
returnsNULL
.- Limits
+
+
+ +- The part of the memory block that is returned will have its contents +unchanged.
+- This function is somewhat dangerous to use. Be careful to save the +pointer you're passing somewhere else, otherwise +
++ +will loose your only copy of+
+ ptr = realloc (ptr, size); ++ptr
ifrealloc
returnsNULL
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+_heapadd, +_heapblocksize, +_heapmaxavail, +_heapmemavail, +calloc, +free, +realloc
+- Example
None.
+
dio.h
(incomplete)
+ + ++
++ + + ++
+- Function
Delete a file.
+- Header
- +
- Declaration
+
int __fastcall__ remove (const char* name);
- Description
+
remove
deletes the file with the given name. On success, +zero is returned. On error, -1 is returned anderrno
is set to an error +code describing the reason for the failure.- Limits
+
+
+ +- This function is not available on all cc65 targets (depends on the +availability of file I/O).
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
- #
include <stdio.h>
+#define FILENAME "helloworld"
+if (remove (FILENAME) == 0) { +printf ("We deleted %s successfully\n", FILENAME); +} else { +printf ("There was a problem deleting %s\n", FILENAME); +}
+
+
++ + + ++
+- Function
Resets the break vector to its original value.
+- Header
- +
- Declaration
+
void __fastcall__ reset_brk (void);
- Description
+
reset_brk
resets the break vector to the value it had +before a call toset_brk
.- Limits
+
+
+ +- Since
++set_brk
installs an exit handler, +it is not strictly necessary to call this function as part of the cleanup when +the program ends.- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Control revers character display.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ revers (unsigned char onoff);
- Description
If the argument is non zero, the function enables reverse +character display. If the argument is zero, reverse character display is +switched off. The old value of the setting is returned.
+- Limits
+
+
+ +- The function may not be supported by the hardware, in which case +the call is ignored.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the dimensions of the text mode screen.
+- Header
- +
- Declaration
+
void __fastcall__ screensize (unsigned char* x, unsigned char* y);
- Description
The function returns the dimensions of the text mode screen.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Set the break vector to a user function.
+- Header
- +
- Declaration
+
void __fastcall__ set_brk (brk_handler func);
- Description
+
set_brk
allows a user program to handle breaks within the +program code by letting the vector point to a user written C function. The +runtime library installs a small stub that saves the registers into global +variables that may be accessed (and changed) by the break handler.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The stub saves the zero page registers used by the C runtime and switches +to a small break handler stack. This means that it is safe to execute C code, +even if C code was interrupted. Be careful however not to use too many local +variables, and do not enable stack checks for the handler function or any other +function called from it.
+- The
+brk_pc
variable points to theBRK
instruction. If you want +the continue with the interrupted code, you have to adjustbrk_pc
, +otherwise theBRK
instruction will get executed over and over again.- Since
+set_brk
installs an exit handler, it is not strictly necessary +to call+reset_brk
as part of the cleanup when +the program terminates.- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Save the context for use with
+longjmp
.- Header
- +
- Declaration
+
int __fastcall__ setjmp (jmp_buf buf);
- Description
The
+setjmp
function saves the current context inbuf
+for subsequent use by the+longjmp
function and +returns zero.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- +
setjmp
is actually a macro as required by the ISO standard.- +
setjmp
will not save the signal context.- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Selects a locale.
+- Header
- +
- Declaration
+
char* __fastcall__ setlocale (int category, const char* locale);
- Description
+
setlocale
sets or queries the program's locale.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- cc65 supports only the "C" locale, so calling this function to set a +different locale has no effect.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Install a signal handler.
+- Header
- +
- Declaration
+
__sigfunc __fastcall__ signal (int sig, __sigfunc func);
- Description
+
signal
installs a handler for the given signal. The +handler may either be a user supplied function, or one of the predefined +signal handlersSIG_IGN
orSIG_DFL
. The function returns the +previous value if the signal , or the special function vector SIG_ERR in +case of an error.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Sleep for a specified amount of time.
+- Header
- +
- Declaration
+
void __fastcall__ sleep (unsigned seconds);
- Description
The function will return after the specified number of +seconds have elapsed.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
POSIX 1003.1
+- Example
None.
+
+
++ + + ++
+- Function
Switch the C128 into 1MHz mode.
+- Header
- +
- Declaration
+
void slow (void);
- Description
The function will switch the clock of the C128 to 1MHz. This +will halve the speed compared to fast mode.
+- Limits
+
+
+ +- The function is specific to the C128.
+- Availability
C128
+- See also
- +
- Example
None.
+
em.h
+
+
++ + + ++
+- Function
Initialize the pseudo random number generator.
+- Header
- +
- Declaration
+
void __fastcall__ srand (unsigned seed);
- Description
The function initializes the random number generator using +the given seed. On program startup, the generator behaves as if
+srand
has +been called with an argument of 1.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+_randomize, +rand
+- Example
None.
+
+
++ + + ++
+- Function
Compare two strings case insensitive.
+- Header
- +
- Declaration
+
int __fastcall__ strcasecmp (const char* s1, const char* s2);
- Description
The
+strcasecmp
function compares the two strings passed +as parameters without case sensitivity. It returns a value that is less than +zero ifs1
is less thans2
, zero ifs1
is the same ass2
, +and a value greater than zero ifs1
is greater thans2
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The function is not available in strict ANSI mode.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Concatentate two strings.
+- Header
- +
- Declaration
+
char* __fastcall__ strcat (char* s1, const char* s2);
- Description
The
+strcat
function appends a copy of the string +pointed to by s2 (including the terminating null byte) to the end of the +string pointed to by s1. The initial byte of s2 overwrites the null byte at +the end of s1.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- If copying takes place between objects that overlap, the behaviour +is undefined.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Search for a character in a string.
+- Header
- +
- Declaration
+
char* __fastcall__ strchr (const char* s, int c);
- Description
The
+strchr
function locates the first occurrence ofc
+(converted to a char) in the string pointed to bys
. The terminating null +byte is considered to be part of the string. Upon completion, the function +returns a pointer to the byte, or a null pointer if the byte was not found.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Compare two strings.
+- Header
- +
- Declaration
+
int __fastcall__ strcmp (const char* s1, const char* s2);
- Description
The
+strcmp
function compares the two strings passed as +parameters. It returns a value that is less than zero ifs1
is less than +s2
, zero ifs1
is the same ass2
, and a value greater than zero +ifs1
is greater thans2
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+strcasecmp, +strcoll, +stricmp, +strncmp
+- Example
None.
+
+
++ + + ++
+- Function
Compare two strings.
+- Header
- +
- Declaration
+
int __fastcall__ strcoll (const char* s1, const char* s2);
- Description
The
+strcoll
function compares the two strings passed as +parameters, according to the collating sequence set by+setlocale
. It returns a value that is less than zero ifs1
is +less thans2
, zero ifs1
is the same ass2
, and a value greater +than zero ifs1
is greater thans2
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+setlocale, +strcasecmp, +strcmp, +stricmp, +strncmp
+- Example
None.
+
+
++ + + ++
+- Function
Copy a string.
+- Header
- +
- Declaration
+
char* __fastcall__ strcpy (char* s1, const char* s2);
- Description
The
+strcpy
function copies the string pointed to by +s2
(including the terminating null byte) into the array pointed to by +s1
. The function will always returns1
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- If copying takes place between objects that overlap, the behaviour +is undefined.
+- Availability
ISO 9899
+- See also
- +
- Example
+
+#include <string.h> + +static char hello[14]; + +strcpy (hello, "Hello world!\n"); ++ +
+
++ + + ++
+- Function
Compute the length of a substring.
+- Header
- +
- Declaration
+
size_t __fastcall__ strcspn (const char* s, const char* set);
- Description
The
+strcspn
function computes and returns the length of +the substring pointed to bys
which does not consist of +characters contained in the stringset
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Allocate a copy of a string on the heap.
+- Header
- +
- Declaration
+
char* __fastcall__ strdup (const char* s);
- Description
+
strdup
allocates a memory block on the heap, big enough +to hold a copy ofs
including the terminating zero. If the allocation +fails,NULL
is returned, otherwises
is copied into the allocated +memory block, and a pointer to the block is returned.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- It is up to the caller to free the allocated memory block.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return a string describing an error code.
+- Header
- +
- Declaration
+
char* __fastcall__ strerror (int errcode);
- Description
The
+strerror
function returns a string describing the +given error code. If an invalid error code is passed, the string "Unknown +error" is returned, anderrno
is set toEINVAL
. In all other cases, +errno
is left untouched.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- While the return type of the function is a
+char*
, the returned +string must not be modified by the caller!- Availability
ISO 9899
+- See also
- +
- Example
None.
+
errno.h
(incomplete)
+ + ++
++ + + ++
+- Function
Compare two strings case insensitive.
+- Header
- +
- Declaration
+
int __fastcall__ stricmp (const char* s1, const char* s2);
- Description
The
+stricmp
function compares the two strings passed as +parameters without case sensitivity. It returns a value that is less than zero +ifs1
is less thans2
, zero ifs1
is the same ass2
, and a +value greater than zero ifs1
is greater thans2
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The function is not available in strict ANSI mode.
+- Availability
cc65
+- See also
+strcasecmp, +strcmp, +strcoll, +strncmp
+- Example
None.
+
+
++ + + ++
+- Function
Return the length of a string.
+- Header
- +
- Declaration
+
size_t __fastcall__ strlen (const char* s);
- Description
The
+strlen
function computes the number of bytes in the +string to which s points, not including the terminating null byte.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- When compiling with
+-Os
(inline known standard functions), the +function does not work correctly for strings with more than 255 characters.- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Make a string lower case.
+- Header
- +
- Declaration
+
char* __fastcall__ strlower (char* s);
- Description
The
+strlower
function will apply thetolower
+function to each character of a string. The function will always returns
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The function prototype is unavailable when compiling in strict ANSI mode.
+- An alias name for this function is
+strlwr
.- Availability
cc65
+- See also
- +
- Example
None.
+
+
+See strlower
.
+
+
+
+
++
++ + + ++
+- Function
Concatentate two strings.
+- Header
- +
- Declaration
+
char* __fastcall__ strncat (char* s1, const char* s2, size_t n);
- Description
The
+strncat
function appends not more than n characters +of the string pointed to by s2 to the end of the string pointed to by s1. The +terminating null character at the end of s1 is overwritten. A terminating null +character is appended to the result, even if not all of s2 is appended to s1.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- If copying takes place between objects that overlap, the behaviour +is undefined.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Compare two strings.
+- Header
- +
- Declaration
+
int __fastcall__ strncmp (const char* s1, const char* s2, size_t count);
- Description
The
+strncmp
function compares not more thancount
+characters of the two strings passed as parameters. It returns a value that is +less than zero if the firstcount
characters ofs1
are less than +s2
, zero if they are identical, and a value greater than zero they are +greater.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+strcasecmp, +strcmp, +strcoll, +stricmp
+- Example
None.
+
+
++ + + ++
+- Function
Copy part of a string.
+- Header
- +
- Declaration
+
char* __fastcall__ strcpy (char* s1, const char* s2, size_t n);
- Description
The
+strncpy
function copies not more than n bytes from +the array pointed to bys2
to the array pointed to bys1
. If the array +pointed to bys2
is a string that is shorter than n bytes, null bytes are +appended to the copy in the array pointed to bys1
, untiln
bytes are +written. The function will always returns1
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype. If there is no null byte in the first
+n
+bytes of the array pointed to bys2
, the result is not null-terminated.- If copying takes place between objects that overlap, the behaviour is +undefined.
+- Availability
ISO 9899
+- See also
- +
- Example
+
+#include <string.h> + +static char hello[6]; + +strcpy (hello, "Hello world!\n", sizeof (hello) - 1); +hello[5] = '\0'; ++ +
+
++ + + ++
+- Function
Search for a character in a string.
+- Header
- +
- Declaration
+
char* __fastcall__ strrchr (const char* s, int c);
- Description
The
+strrchr
function locates the last occurrence ofc
+(converted to a char) in the string pointed to bys
. The terminating null +byte is considered to be part of the string. Upon completion, the function +returns a pointer to the byte, or a null pointer if the byte was not found.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Compute the length of a substring.
+- Header
- +
- Declaration
+
size_t __fastcall__ strspn (const char* s, const char* set);
- Description
The
+strspn
function computes and returns the length of +the substring pointed to bys
which does consist only of characters +contained in the stringset
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Find a substring.
+- Header
- +
- Declaration
+
char* __fastcall__ strstr (const char* str, const char* substr);
- Description
+
strstr
searches for the first occurance of the string +substr
withinstr
. If found, it returns a pointer to the copy, +otherwise it returnsNULL
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
fcntl.h
+
+ + + ++
++ + + ++
+- Function
Break a string into tokens.
+- Header
- +
- Declaration
+
char* __fastcall__ strtok (char* s1, const char* s2);
- Description
+
strtok
will break the string s1 into a sequence of +tokens, which are delimited by characters from the string s2. The first call +tostrtok
will return a pointer to the first token in the string s1. +Following calls must pass aNULL
pointer as s1 in order to get the next +token in the string. Different sets of delimiters may be used for the +subsequent calls tostrtok
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- +
strtok
will modify the string s1.- Availability
ISO 9899
+- See also
+strcspn,
+- Example
None.
+
+
++ + + ++
+- Function
Make a string upper case.
+- Header
- +
- Declaration
+
char* __fastcall__ strupper (char* s);
- Description
The
+strupper
function will apply thetoupper
+function to each character of a string. The function will always returns
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- The function prototype is unavailable when compiling in strict ANSI mode.
+- An alias name for this function is
+strupr
.- Availability
cc65
+- See also
- +
- Example
None.
+
+
+See strupper
.
+
+
+
+
++
++ + + ++
+- Function
Set the text color.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ textcolor (unsigned char color);
- Description
The function will set a new text color. It returns the old +(current) text color. Text output using any
+conio.h
function will use +the color set by this function.- Limits
+
+
+ +- Text colors are system dependent. The function may have no effect +on systems where the text color cannot be changed.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Get the time.
+- Header
- +
- Declaration
+
time_t __fastcall__ time (time_t* t);
- Description
The function returns the time since the 1970-01-01 00:00:00 +measured in seconds. If the pointer
+t
is notNULL
, the function +result will also be stored there. If no time is available,(time_t)-1
is +returned anderrno
is set toENOSYS
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Many platforms supported by cc65 do not have a realtime clock, so the +returned value may not be valid.
+- Availability
ISO 9899
+- Example
None.
+
+
++ + + ++
+- Function
Toggle between 40 and 80 column mode.
+- Header
- +
- Declaration
+
void toggle_videomode (void);
- Description
Toggle between 40 and 80 column mode. The settings for the +old mode (cursor position, color and so on) are saved and restored together +with the mode.
+- Limits
+
+
+ +- The function is specific to the C128.
+- Availability
C128
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Convert a character into its lower case representation.
+- Header
- +
- Declaration
+
int __fastcall__ tolower (int c);
- Description
The function returns the given character converted to lower +case. If the given character is not a letter, it is returned unchanged.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Convert a character into its upper case representation.
+- Header
- +
- Declaration
+
int __fastcall__ toupper (int c);
- Description
The function returns the given character converted to upper +case. If the given character is not a letter, it is returned unchanged.
+- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Convert an unsigned long integer into a string.
+- Header
- +
- Declaration
+
char* __fastcall__ ultoa (unsigned long val, char* buf, int radix);
- Description
+
itoa
converts the unsigned long integerval
into a +string usingradix
as the base.- Limits
+
+
+ +- There are no provisions to prevent a buffer overflow.
+- The function is non standard, so it is not available in strict ANSI mode. +You should probably use
+sprintf
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Delete a file.
+- Header
- +
- Declaration
+
int __fastcall__ unlink (const char* name);
- Description
+
unlink
deletes the file with the given name. On success, +zero is returned. On error, -1 is returned anderrno
is set to an error +code describing the reason for the failure.- Limits
+
+
+ +- The use of this function is discouraged. Please use
++remove
instead, which is a native ANSI C function and does the same.- This function is not available on all cc65 targets (depends on the +availability of file I/O).
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Instead of
+unlink
,+remove
should be +used, which has the same semantics, but is more portable, because it conforms +to the ISO C standard.- Availability
POSIX 1003.1
+- See also
- +
- Example
- #
include <stdio.h> +#include <unistd.h>
+#define FILENAME "helloworld"
+if (unlink (FILENAME) == 0) { +printf ("We deleted %s successfully\n", FILENAME); +} else { +printf ("There was a problem deleting %s\n", FILENAME); +}
+
geos.h
(incomplete)
+ + ++
++ + + ++
+- Function
Convert an unsigned integer into a string.
+- Header
- +
- Declaration
+
char* __fastcall__ utoa (unsigned val, char* buf, int radix);
- Description
+
itoa
converts the unsigned integerval
into a string +usingradix
as the base.- Limits
+
+
+ +- There are no provisions to prevent a buffer overflow.
+- The function is non standard, so it is not available in strict ANSI mode. +You should probably use
+sprintf
instead.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Formatted output to the console.
+- Header
- +
- Declaration
+
int __fastcall__ vcprintf (const char* format, va_list ap);
- Description
The arguments specified as a
+va_list
are converted to +text where necessary and formatted according to the format string given. The +resulting string is output to the console.vcprintf
supports the same +format specifiers asvprintf
.- Limits
+
+
+ +- Like all other
+conio
output functions,vcprintf
distinguishes +between\r
and\n
.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the current X position of the text mode cursor.
+- Header
- +
- Declaration
+
unsigned char wherex (void);
- Description
The function returns the current X position of the text mode +cursor. Zero is returned for the leftmost screen position.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the current Y position of the text mode cursor.
+- Header
- +
- Declaration
+
unsigned char wherey (void);
- Description
The function returns the current Y position of the text mode +cursor. Zero is returned for the uppermost screen position.
+- Availability
cc65
+- See also
- +
- Example
None.
+
joystick.h
+
locale.h
+
modload.h
+
+ + + +mouse.h
+
(incomplete)
+ + +nes.h
(incomplete)
+ + +o65.h
The o65.h
header file contains structure and constant definitions that
+may be used when dealing with files in
+o65 format.
+It does not declare any functions.
peekpoke.h
+
+ + + +pet.h
(incomplete)
+ + +6502.h
+
+ + + +plus4.h
(incomplete)
+ + +serial.h
(incomplete)
+ + +setjmp.h
+
+ + + +signal.h
+
+ + + +stdarg.h
(incomplete)
+ + +stdbool.h
(incomplete)
+ + +stddef.h
+
stdio.h
+
+ +(incomplete)
+ + +stdlib.h
+
string.h
+
(incomplete)
+ + +apple2.h
+
tgi.h
(incomplete)
+ + +time.h
+
(incomplete)
+ + +unistd.h
+
+ +(incomplete)
+ + +vic20.h
(incomplete)
+ + +zlib.h
(incomplete)
+ + ++
++ + + ++
+- Function
Add a block to the heap.
+- Header
- +
- Declaration
+
void __fastcall__ _heapadd (void* mem, size_t size);
- Description
The function adds a block of raw memory to the heap.
+- Limits
+
+
+ +- The minimum blocksize that can be added is 6 bytes; the function will +ignore smaller blocks.
+- Availability
cc65
+- See also
+_heapblocksize, +_heapmaxavail, +_heapmemavail, +calloc, +free, +malloc, +realloc
+- Example
None.
+
+
++ + + ++
+- Function
Return the size of an allocated block.
+- Header
- +
- Declaration
+
size_t __fastcall__ _heapblocksize (const void* block);
- Description
The function returns the size of a block that must have +previously been allocated by
++malloc
,+calloc
or+realloc
.- Limits
+
+
+ +- Passing a pointer to a block that was is not the result of one of the +allocation functions, or that has been free'd will give unpredicable results.
+- Availability
cc65
+- See also
+_heapadd, +_heapmaxavail, +_heapmemavail, +calloc, +free, +malloc, +realloc
+- Example
None.
+
+
++ + + ++
+- Function
Return the largest block that is available on the heap.
+- Header
- +
- Declaration
+
size_t __fastcall__ _heapmaxavail (void);
- Description
The function returns the size of the largest block that may +be allocated from the heap using
++malloc
.- Availability
cc65
+- See also
+_heapadd, +_heapblocksize, +_heapmemavail, +calloc, +free, +malloc, +realloc
+- Example
None.
+
+
++ + + ++
+- Function
Return the total available space on the heap.
+- Header
- +
- Declaration
+
size_t __fastcall__ _heapmemavail (void);
- Description
The function returns the total number of bytes available on +the heap.
+- Limits
+
+
+ +- This function is of less use than usually assumed, since the returned +heap space may be available but not in one block. So even if this function +says that several times more heap space is available than needed, +malloc may still return
+NULL
.- Availability
cc65
+- See also
+_heapadd, +_heapblocksize, +_heapmaxavail, +calloc, +free, +malloc, +realloc
+- Example
None.
+
apple2enh.h
(incomplete)
+ + ++
++ + + ++
+- Function
Print an error message for the error in
+_oserrno
.- Header
- +
- Declaration
+
void __fastcall__ _poserror (const char* msg);
- Description
+
_poserror
prints an error message tostderr
. If +msg
is notNULL
and not an empty string, it is printed followed by +a colon and a blank. Then the error message for the current contents of +_oserrno
are printed followed by a newline. The message output is the +same as returned by+_stroserror
with an +argument of_oserrno
.- Limits
+
+
+ +- Since operating system specific error code are - you guessed it - +operating system specific, the value in
+_oserror
and the message that is +printed depend on the cc65 target.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Initialize the pseudo random number generator.
+- Header
- +
- Declaration
+
void _randomize (void);
- Description
The function initializes the random number generator with +a seed derived from fast changing hardware events, so the seed itself can be +considered random to a certain degree.
+- Limits
+
+
+ +- The randomness of the seed depends on the machine hardware.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return a string describing an OS specific error code.
+- Header
- +
- Declaration
+
const char* __fastcall__ _stroserror (unsigned char errcode);
- Description
+
_stroserror
will return a string describing the given +operating system specific error code.- Limits
+
+
+ +- Since operating system specific error code are - you guessed it - +operating system specific, the parameter and the string returned depend on the +cc65 target.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Swap the contents of memory areas.
+- Header
- +
- Declaration
+
void __fastcall__ _swap (void* p, void* q, size_t size);
- Description
+
_swap
will swap (exchange) the contents of the two memory +areas pointed to byp
andq
. Both memory areas are assumed to be +size
bytes in size.- Limits
+
+
+ +- The memory areas may not overlap, otherwise the results are undefined.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Call a subroutine passing register values.
+- Header
- +
- Declaration
+
void __fastcall__ _sys (struct regs* r);
- Description
The function will call the subroutine at the address +specified in the
+pc
member of the passedregs
structure. All +registers and the CPU flags are set to the values given in theregs
+structure. On return from the subroutine, the new values of the registers and +flags are stored back overwriting the old values.- Limits
+
+
+ +- Bits 4 and 5 of the flags value in the
+regs
structure are ignored +when calling the subroutine (they are unchanged from their current values).- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- Example
None.
+
+
++ + + ++
+- Function
Insert a 6502 BRK instrunction into the code.
+- Header
- +
- Declaration
+
void BRK (void);
- Description
The function will insert a 6502 BRK instruction into the code +which may be used to trigger a debugger.
+- Limits
+
+
+ +- The function is actually a macro.
+- The inserted instruction may lead to unexpected results if no debugger +is present.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Insert a 6502 CLI instrunction into the code.
+- Header
- +
- Declaration
+
void CLI (void);
- Description
The function will insert a 6502 CLI instruction into the code, +so interrupts are disabled. Note that non maskable interrupts cannot be +disabled.
+- Limits
+
+
+ +- The function is actually a macro.
+- Disabling interrupts may lead to unexpected results.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read a byte from memory.
+- Header
- +
- Declaration
+
unsigned char PEEK (unsigned addr);
- Description
The function will read the absolute memory given by
+addr
+and return the value read.- Limits
+
+
+ +- The function is actually a macro.
+- This function depends highly on the platform and environment.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read a word (two bytes) from memory.
+- Header
- +
- Declaration
+
unsigned PEEKW (unsigned addr);
- Description
The function will read the absolute memory given by
+addr
+and return the value read. The byte read from the higher address is the high +byte of the return value.- Limits
+
+
+ +- The function is actually a macro.
+- This function depends highly on the platform and environment.
+- The order in which the two bytes are read is unspecified and may +depend of the address expression used.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Write a byte to memory.
+- Header
- +
- Declaration
+
void POKE (unsigned addr, unsigned char val);
- Description
The function writes the value
+val
to the absolute +memory address given byaddr
.- Limits
+
+
+ +- The function is actually a macro.
+- This function depends highly on the platform and environment.
+- Careless use will cause the program to act strange or may crash the +machine.
+- Availability
cc65
+- See also
- +
- Example
None.
+
assert.h
+
+
++ + + ++
+- Function
Write a word (two bytes) to memory.
+- Header
- +
- Declaration
+
void POKEW (unsigned addr, unsigned val);
- Description
The function writes the value
+val
to the absolute +memory address given byaddr
. The low byte ofval
is written to +theaddr
, the high byte is written toaddr+1
.- Limits
+
+
+ +- The function is actually a macro.
+- This function depends highly on the platform and environment.
+- Careless use will cause the program to act strange or may crash the +machine.
+- The order in which the two bytes are written is unspecified and may +depend of the address expression used.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Insert a 6502 SEI instrunction into the code.
+- Header
- +
- Declaration
+
void SEI (void);
- Description
The function will insert a 6502 SEI instruction into the code, +so interrupts are enabled. Enabling interrupts has no effects if they are +already enabled (the default).
+- Limits
+
+
+ +- The function is actually a macro.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
+ ++ + + +
+
++ + + ++
+- Function
Returns the absolute value of an integer.
+- Header
- +
- Declaration
+
int __fastcall__ abs (int v);
- Description
+
abs
returns the absolute value of the argument passed to +the function.- Limits
+
+
+ +- The return value is undefined if
+INT_MIN
is passed to the function.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+labs
+- Example
None.
+
+
++ + + ++
+- Function
Test a condition and possibly abort.
+- Header
- +
- Declaration
+
void assert (int cond);
- Description
+
assert
is a macro that expands to aid
+statement. If the condition evaluates t zero (false), assert prints a message +on stderr and aborts the program.- Limits
+
+
+ +- The function is actually a macro.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Register an exit function.
+- Header
- +
- Declaration
+
int __fastcall__ atexit (void (*exitfunc) (void));
- Description
+
atexit
registers the function pointed to by +exitfunc
as an exit function. Exit functions are called when the program +terminates, they are called in LIFO order (the last function registered is +called first).atexit
returns zero on success and a nonzero value on +failure.- Limits
+
+
+ +- A maximum of 5 exit functions can be registered.
+- There is no way to unregister an exit function.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Convert a string to an integer.
+- Header
- +
- Declaration
+
int __fastcall__ atoi (const char* s);
- Description
+
atoi
converts the given string into an integer. +Conversion stops as soon as any invalid character is encountered.- Limits
+
+
+ +- There is no way to detect any conversion errors.
+- The function does not check for an numerical overflow when converting.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Convert a string to a long integer.
+- Header
- +
- Declaration
+
long __fastcall__ atol (const char* s);
- Description
+
atol
converts the given string into a long integer. +Conversion stops as soon as any invalid character is encountered.- Limits
+
+
+ +- There is no way to detect any conversion errors.
+- The function does not check for an numerical overflow when converting.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Set the background text color.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ bgcolor (unsigned char color);
- Description
The function will set a new background color and return the +old (current) one. The background color is valid for the whole text output +area of the screen, not just for new text.
+- Limits
+
+
+ +- Background colors are system dependent. The function may have no effect +on systems where the background color cannot be changed.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Set the border (frame) color.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ bordercolor (unsigned char color);
- Description
The function will set a new border color. It returns the old +(current) border color.
+- Limits
+
+
+ +- Border colors are system dependent. The function may have no effect +on systems where the border color cannot be changed.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
atari.h
+
(incomplete)
+ + ++
++ + + ++
+- Function
Do a binary search in a sorted array.
+- Header
- +
- Declaration
+
void* __fastcall__ bsearch (const void* key, +const void* base, size_t n, size_t size, +int (*cmp) (const void*, const void*));
- Description
+
bsearch
searches a sorted array for a member that +matches the one pointed to bykey
.base
is the address of the array, +n
is the number of elements,size
the size of an element andcmp
+the function used to compare the members against the key. The function returns +a pointer to the member found, orNULL
if there was no match.- Limits
+
+
+ +- The contents of the array must be sorted in ascending order according to +the compare function given.
+- If there are multiple members that match the key, the function will +return one of the members.
+- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Fill a memory area with zeroes.
+- Header
- +
- Declaration
+
void __fastcall__ bzero (void* p, size_t count);
- Description
+
bzero
fills the memory area pointed to byp
with +zero.- Limits
+
+
+ +- The function is non standard and therefore only available in non ANSI +mode. You should use
++memset
instead.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Switch the C128 into C64 compatible mode.
+- Header
- +
- Declaration
+
void c64mode (void);
- Description
The function will cause the machine to reboot into C64 mode.
+- Limits
+
+
+ +- The function is specific to the C128.
+- The function will not return to the caller.
+- Availability
C128
+- Example
None.
+
+
++ + + ++
+- Function
Allocate and clear memory.
+- Header
- +
- Declaration
+
void* __fastcall__ calloc (size_t n, size_t size);
- Description
+
calloc
allocates memory for an array ofn
elements +of sizesize
, clears the whole block with binary zeroes and returns a +pointer to it. On error (not enough memory available),calloc
returns +NULL
.- Limits
+
+
+ +- Clearing the memory may not have the expected effect on all platforms: +pointers in the block may not be
+NULL
and floating point variables may +not be zero (0.0). In other words: The "clearing" effect of this function +should be used with care for portable programs.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
+_heapadd, +_heapblocksize, +_heapmaxavail, +_heapmemavail, +free, +malloc, +realloc
+- Example
None.
+
+
++ + + ++
+- Function
Clear part of a line (write a given number of spaces).
+- Header
- +
- Declaration
+
void __fastcall__ cclear (unsigned char length);
- Description
The function clears part of a line by writing
+length
+spaces in the current text color.- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Clear part of a line (write a given number of spaces) starting +at a specific screen position.
+- Header
- +
- Declaration
+
void __fastcall__ cclearxy (unsigned char x, unsigned char y, unsigned char length);
- Description
The function moves the cursor to a specific position, and +will then clear part of the line by writing
+length
spaces in the current +text color.- Limits
+
+
+ +- The function is only available as fastcall function, so it may +only be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Read a character from the keyboard.
+- Header
- +
- Declaration
+
char cgetc (void);
- Description
The function reads a character from the keyboard. If there is +no character available,
+cgetc
waits until the user presses a key. If the +cursor is enabled by use of thecursor
function, a blinking cursor is +displayed while waiting.- Limits
+
+
+ +- If the system supports a keyboard buffer,
+cgetc
will fetch a key +from this buffer and wait only if the buffer is empty.- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a horizontal line in text mode.
+- Header
- +
- Declaration
+
void __fastcall__ chline (unsigned char length);
- Description
The function outputs a horizontal line with the given length +starting at the current cursor position.
+- Limits
+
+
+ +- The character used to draw the horizontal line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a horizontal line at a given position in text mode.
+- Header
- +
- Declaration
+
void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length);
- Description
The function outputs a horizontal line with the given length +starting at a given position.
+- Limits
+
+
+ +- The character used to draw the horizontal line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Clear error and end-of-file status of a stream.
+- Header
- +
- Declaration
+
void __fastcall__ clearerr (FILE* f);
- Description
+
clearerr
clears the error and end-of-file status +indicators for the streamf
.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
ISO 9899
+- See also
- +
- Example
None.
+
atmos.h
(incomplete)
+ + ++
+ ++ + + +
+
++ + + ++
+- Function
Close a file descriptor.
+- Header
- +
- Declaration
+
int __fastcall__ close (int fd);
- Description
The function closes the given file descriptor. It returns zero +on success and -1 on error. If an error occurs, the cause can be determined by +reading the
+errno
variable.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
POSIX 1003.1
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Create a file.
+- Header
- +
- Declaration
+
int __fastcall__ creat (const char* name, unsigned mode);
- Description
+
creat
creates a new file and returns the file descriptor +associated with it. On error, -1 is returned and an error code is stored in +errno
.- Limits
+
+
+ +- +
creat
is identical to calling+open
with +flags
equal toO_WRONLY | O_CREAT | O_TRUNC
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
POSIX 1003.1
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Formatted output to the console.
+- Header
- +
- Declaration
+
int cprintf (const char* format, ...);
- Description
The arguments are converted to text where necessary and +formatted according to the format string given. The resulting string is output +to the console.
+cprintf
supports the same format specifiers as +printf
.- Limits
+
+
+ +- Like all other
+conio
output functions,cprintf
distinguishes +between\r
and\n
.- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a character directly to the console.
+- Header
- +
- Declaration
+
void __fastcall__ cputc (char c);
- Description
Output one character to the console at the current cursor +position.
+- Limits
+
+
+ +- Like all other
+conio
output functions,cputc
distinguishes +between\r
and\n
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a character at a specific screen position.
+- Header
- +
- Declaration
+
void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
- Description
+
cputcxy
moves the cursor to the given x/y position on +the screen and outputs one character.- Limits
+
+
+ +- Like all other
+conio
output functions,cputcxy
distinguishes +between\r
and\n
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a string directly to the console.
+- Header
- +
- Declaration
+
void __fastcall__ cputs (const char* s);
- Description
The function outputs the given string on the console at the +current cursor position.
+- Limits
+
+
+ +- Like all other
+conio
output functions,cputs
distinguishes +between\r
and\n
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a string to the console at a given position.
+- Header
- +
- Declaration
+
void __fastcall__ cputsxy (unsigned char x, unsigned char y, const char* s);
- Description
+
cputsxy
moves the cursor to the given x/y position, +and outputs the strings
.- Limits
+
+
+ +- Like all other
+conio
output functions,cputsxy
distinguishes +between\r
and\n
.- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Enable/disable a blinking cursor when waiting for keyboard input.
+- Header
- +
- Declaration
+
unsigned char __fastcall__ cursor (unsigned char onoff);
- Description
If the argument to the function is non zero, a blinking cursor +will be enabled when the
+cgetc
function waits for input from the keyboard. +If the argument is zero,cgetc
will wait without a blinking cursor.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Output a vertical line in text mode.
+- Header
- +
- Declaration
+
void __fastcall__ cvline (unsigned char length);
- Description
The function outputs a vertical line with the given length +starting at the current cursor position.
+- Limits
+
+
+ +- The character used to draw the vertical line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
c128.h
+
+
++ + + ++
+- Function
Output a vertical line at a given position in text mode.
+- Header
- +
- Declaration
+
void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length);
- Description
The function outputs a vertical line with the given length +starting at a given position.
+- Limits
+
+
+ +- The character used to draw the vertical line is system dependent. +If available, a line drawing character is used. Drawing a line that is partially +off screen leads to undefined behaviour.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Divide two ints and return quotient and remainder.
+- Header
- +
- Declaration
+
div_t __fastcall__ div (int numer, int denom);
- Description
+
div
dividesnumer
bydenom
and returns the +quotient and remainder in adiv_t
structure.- Limits
+
+
+ +- The function is only available as fastcall function, so it may only +be used in presence of a prototype.
+- Availability
ISO 9899
+- See also
ldiv
+- Example
None.
+
+
++ + + ++
+- Function
Commit changes into extended memory.
+- Header
+
+em.h
- Declaration
+
void __fastcall__ em_commit (void);
- Description
Commit changes in the memory window to extended storage. If +the contents of the memory window have been changed, these changes may be lost +if
++em_map
,+em_use
, ++em_copyfrom
or+em_copyto
are called without callingem_commit
first.- Limits
+
+
+ +- Calling
+em_commit
does not necessarily mean that changes to the +memory window are discarded, it does just mean that the drivers is allowed +to discard it.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The function produces undefined results if no extended memory driver is +loaded.
+- Availability
cc65
+- See also
+em_load_driver, +em_map, +em_use
+- Example
None.
+
+
++ + + ++
+- Function
Copy from extended into normal memory.
+- Header
+
+em.h
- Declaration
+
void __fastcall__ em_copyfrom (const struct em_copy* copy_data);
- Description
Copy data from extended memory into linear memory. Source and +target addresses as well as the number of bytes to transfer are specified in +the
+em_copy
structure that is passed as a parameter.- Limits
+
+
+ +- Calling
+em_copyfrom
will invalidate the memory window, so if you +made any changes to the data in the window, call+em_commit
first, or the changes are lost.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The function produces undefined results if no extended memory driver is +loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Copy from normal into extended memory.
+- Header
+
+em.h
- Declaration
+
void __fastcall__ em_copyto (const struct em_copy* copy_data);
- Description
Copy data from linear into extended memory. Source and +target addresses as well as the number of bytes to transfer are specified in +the
+em_copy
structure that is passed as a parameter.- Limits
+
+
+ +- Calling
+em_copyto
will invalidate the memory window, so if you +made any changes to the data in the window, call+em_commit
first, or the changes are lost.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The function produces undefined results if no extended memory driver is +loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Install an already loaded extended memory driver.
+- Header
+
+em.h
- Declaration
+
unsigned char _fastcall__ em_install (void* driver);
- Description
The function installs an already loaded extended memory driver +and returns an error code. The function may be used to install a driver linked +statically to the program.
+- Limits
+
+
+ +- Not all drivers are able to detect if the supported hardware is really +present.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Load and initialize an extended memory driver.
+- Header
+
+em.h
- Declaration
+
void __fastcall__ em_load_driver (const char* name);
- Description
Load an extended memory driver into memory and initialize +it. The function returns an error code that tells if all this has been +successful.
+- Limits
+
+
+ +- Not all drivers are able to detect if the supported hardware is really +present.
+- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The driver is loaded by name, so currently you must know the type of +extended memory that should be supported. There is no autodetect capability.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Make a page of extended memory accessible.
+- Header
+
+em.h
- Declaration
+
void* __fastcall__ em_map (unsigned page);
- Description
The function maps one page of extended memory into linear +memory and returns a pointer to the page frame. Depending on the hardware +and driver, the data is either mapped into the address space or transfered +into a buffer. If you don't need the actual contents of the page (for example +because you're going to overwrite it completely, it is better to call +
++em_use
instead.em_use
will not transfer the +data if it is possible to avoid that.- Limits
+
+
+ +- Calling
+em_map
will invalidate the memory window, so if you +made any changes to the data in the window, call+em_commit
first, or the changes are lost.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- The function produces undefined results if no extended memory driver is +loaded.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Return the number of available extended memory pages.
+- Header
+
+em.h
- Declaration
+
unsigned __fastcall__ em_pagecount (void);
- Description
The function returns the size of the extended memory supported +by the driver in 256 byte pages.
+- Limits
+
+
+ +- The function returns zero if no extended memory driver is loaded.
+- The function may return zero if the supported hardware was not detected.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
++ + + ++
+- Function
Uninstall an already loaded extended memory driver.
+- Header
+
+em.h
- Declaration
+
unsigned char __fastcall__ em_install (void);
- Description
The function uninstalls an already loaded extended memory +driver but doesn't remove it from memory.
+- Limits
+
+
+ +- If the driver has been loaded using
++em_load_driver
,+em_unload
+should be used instead ofem_uninstall
so the driver is also removed +from memory.- The function is only available as fastcall function, so it may only be +used in presence of a prototype.
+- Availability
cc65
+- See also
- +
- Example
None.
+
+
+
6502.h
+apple2.h
+apple2enh.h
+assert.h
+atari.h
+atmos.h
+c128.h
+c16.h
+c64.h
+cbm510.h
+cbm610.h
+conio.h
+ctype.h
+dbg.h
+dio.h
+em.h
+errno.h
+fcntl.h
+geos.h
+joystick.h
+locale.h
+modload.h
+mouse.h
+nes.h
+o65.h
+peekpoke.h
+pet.h
+plus4.h
+serial.h
+setjmp.h
+signal.h
+stdarg.h
+stdbool.h
+stddef.h
+stdio.h
+stdlib.h
+string.h
+tgi.h
+time.h
+unistd.h
+vic20.h
+zlib.h
++
As we all know that the best computers in the world are c64 and c128. They have their GUI too - +excellent GEOS. GEOS seems very difficult and cryptic for many people, from programmer's point +of view. That's not true. The designers of GEOS created flexible and powerful system, which +is easy to use and program.
+Coding GEOS in C? That's something new. It is possible now - with Ulrich von Bassewitz's cc65 +package and my GEOSLib you are able to create GEOS applications in no-time.
+GEOSLib supports a subset of standard cc65 libraries. Whenever possible native Kernal functions
+are used (e.g. memset
is an alias for FillRam
), however not all are supported. E.g.
+string functions like strcmp
, strcpy
are doubled with native CmpString
,
+CopyString
because the latter can handle only 256 byte strings. Keep this in mind when
+you will write your program. If you don't need long strings simply use functions from Kernal,
+resulting code will be smaller.
dio
- direct disk access is available, but you might have problems with devices other
+than 1541, 1571 or 1581. RAM drives emulating these should work.
conio
- simple console input-output is available for command line applications.
+This implementation assumes that one character will fit in 8x8 cell, so output with
+default BSW font, which is has 9 points, might be a bit messy.
+cputs
will output characters with fixed width, for proportional spacing use
+cpputs
but this function does not update cursor. There is no color support in
+GEOS 2.0 so color functions are disabled. Both 40 and 80 columns modes are supported
+and automatically detected.
tgi
- TGI driver for GEOS that supports both 40 and 80 columns modes but mode can not be
+changed between tgi_init
and tgi_done
.
joy
- JOY driver for GEOS supports only joystick, not current pointing device.
It is safe to use these standard includes and their contents:
+assert.h, conio.h, dio.h, errno.h, em.h, geos.h, joystick.h, modload.h, mouse.h, stdlib.h, string.h, tgi.h, time.h
For time.h
functions systime()
and clock()
note that the resolution is one second.
It was not tested enough, but functions from these includes might work under GEOS:
+rs232.h, zlib.h
Functions from the headers above are either standard C library functions or cc65-specific, in +either case they are not GEOS specific and so they are not described here.
+I am an assembler programmer and GEOSLib was designed in such way that cc65 could emit the best
+available code (well, the best as for machine :). Many of the void foo (void)
functions are
+just raw calls to Kernal (assembled just as jsr _foo
), look in gsym.h
, where you
+will find many definitions of standard GEOS locations. Access to these addresses is optimized by
+cc65 to simple lda
and sta
. Don't be afraid to use C syntax.
You will not need c64 or c128 for development. The only hardware requirement is a PC capable of +running cc65. You will however need c64 or c128 emulator and GEOS image disks (.d64) to test your +programs.
+The software needed: +
VICE and cc65 are portable - they run on variety of platforms - DOS, Win32 and UNIX. GEOSLib only +needs cc65.
+Update: starting from v2.5.0 GEOSLib is a part of cc65 package as its GEOS support library.
+ +I want to thank Uz for his cc65 package, Alexander Boyce for his excellent GEOS Programmer's +Reference Guide and BSW for GEOS.
+GEOSLib is covered by the same license as cc65. You can find the whole text among documentation. +I would really appreciate if you would like to send me your comments, suggestions, questions, +changes, bug reports etc. I will also appreciate if you will just give me a sign that you are +using GEOSLib - not especially something big and important, mail me even if you are just playing +with it.
+You can send postcards with hellos to:
+Maciej Witkowiak, ul. Slowackiego 6/57, 77-400 ZLOTOW
+POLAND
+e-mail: ytm@elysium.pl
This chapter describes some rules you ought to obey, and how to use GEOSLib.
+ +Apart from this file, which merely describes only standard GEOS library functions, you should read
+grc
(GEOS resource compiler) documentation. There are informations about necessary resource
+files (each GEOS application needs at least one) and the building process - what should be done
+and in what order. Please also read cc65's documentation on how to compile C, assembler and link
+everything together.
All in all, you just need to place +
+
+#include <geos.h>
+
+
+
+on top of your source.
+As a general rule read the sources of example programs and read the headers. These are the most +reliable sources of knowledge ;). You will also find there many C macros representing various +arguments passed to functions. Please use them. You will find your sources easier to understand, +and it will be easier to find bugs.
+All types used in GEOSLib are unsigned
.
Screen coordinates are given in pixels unless stated differently.
+ +Contrary to typical GEOS assembly program which has a main function called after loading that
+setups the screen, menus, icons etc. exiting from main
function in C is equivalent to
+calling exit()
. These two are the only safe methods of terminating applications. DO NOT
+USE EnterDeskTop
! Your data may be lost as library destructors and functions registered
+with atexit
will not be called.
For GEOS GUI applications the recommended program structure is to have everything initialized
+in main
function and at the end of it a call to MainLoop()
function. WARNING! This
+function never returns, any code between MainLoop();
and the end of main
will not
+be executed. You have to call exit()
explicitly somewhere in your code (e.g. in a menu
+handler or via DialogBox action).
Whenever possible use definitions from gsym.h
. The resulting code is translated by cc65 into
+series of lda
and sta
, so you can't do it better :-).
Don't hesitate to use library functions. Everything was written with size and speed in mind. In
+fact many calls are just redirections to GEOS kernal which results in simple jsr
.
The main
function receives the standard argc
and argv
parameters. There are
+always either 1 or 3 parameters. DOS application name is always set as argv[0]
.
+If present, argv[1]
and argv[2]
will be set to data filename and data diskname (it only
+works if user double-clicks on data file associated with your application). Note that it is up
+to your application to determine which of the available (up to four) disk drives has the disk
+with given diskname inside. If this fails your program should ask to insert the proper disk into
+one of available drives.
You might wonder why I have chosen sometimes weird order of arguments in functions. I just
+wanted to avoid unnecessary pushing and popping arguments from stack because cc65 can pass single
+unsigned int
through CPU registers.
Do not try to compile in strict ANSI mode. Library uses cc65 extensions which are not available in +ANSI.
+It is possible to use dynamically loaded modules, three such modules are provided: +GEOS TGI driver, GEOS EMD driver (for VDC extended memory) and GEOS JOY driver. +Just make sure that their filenames appear UPPERCASE in DeskTop. There are no more special +recommendations, read cc65 documentation about modules and demo programs source code.
+ +Functions here are sorted more or less in the way they appear in header files. This way I am able
+to keep functions covering similar task near each other. All function names are identical to those
+from geosSym
file provided with GeoProgrammer package. Only my extensions to geosSym
+are covered by new names, but I tried to keep them in the naming convention.
This section covers drawing package of GEOS along with text output routines.
+ +void SetPattern (char pattern)
This function sets current pattern to given. There are 32 different patterns in GEOS. You can +see them together in the filling box in GeoPaint.
+ +void GraphicsString (char *myGString)
One of the more powerfull routines of GEOS. This function calls other graphic functions depending +on given command string. See structures chapter for more detailed description of the structure of it.
+ +Parameters to those functions are grouped in struct window drawWindow
. To speed up things and
+reduce overhead this structure is glued to zero page locations, where all rectangle functions
+expect their parameters. You can modify data directly (e.g. drawWindow.top=10
) or via
+InitDrawWindow
function. Contents of drawWindow
are guaranteed not to change only when
+using graphics functions. In other case you should keep your data in separate struct window
+and use InitDrawWindow
before first call to rectangle functions.
void InitDrawWindow (struct window *myWindow)
This function only copies contents of myWindow
into system area of drawWindow
. Use it
+if for some reason you have to keep window data out of zero page space.
void Rectangle (void)
This draws on screen rectangle filled with current pattern.
+ +void FrameRectangle (char pattern)
This one draws frame with given bit pattern (not a pattern from GEOS palette).
+ +void InvertRectangle (void)
Just as the name says...
+ +void ImprintRectangle (void)
void RecoverRectangle (void)
These two functions are for copying parts of the screen to (Imprint
) and from (Recover
)
+backbuffer of the screen. For example when drawing new menu box GEOS first uses
+ImprintRectangle
to save the area under the box, and restores it by RecoverRectangle
upon
+destroying the menu.
GEOS drawing package is optimized so there are different functions for drawing vertical and +horizontal lines.
+ +void HorizontalLine (char pattern, char y, unsigned xStart, unsigned xEnd)
This function draws horizontal line using given pattern - here it is a true bit pattern, not
+pattern set by SetPattern
.
void InvertLine (char y, unsigned xStart, unsigned xEnd)
There is only horizontal version.
+ +void RecoverLine (char y, unsigned xStart, unsigned xEnd)
This function recovers only one line. It is utilized by RecoverRectangle
. See its description
+for more details.
void VerticalLine (char pattern, char yStart, char yEnd, unsigned x)
This function draws vertical line using given pattern. Note that pattern
is not a pattern
+number as set in SetPattern
but a true bit pattern.
void DrawLine (char mode, struct window *myWindow)
top
parameters of struct window
describe the starting point of the line, while
+bottom
are for the ending point. If mode
is DRAW_DRAW
then current pattern from
+SetPattern
is used for drawing. If mode
is DRAW_ERASE
then line is erased from the
+screen. If mode
is DRAW_COPY
then line is copied from/to back/frontbuffer, according to
+dispBufferOn
setting.
Parameters to these two functions are passed by a pointer to own struct pixel
filled with
+proper values.
void DrawPoint (char mode, struct pixel *myPixel)
Depending on mode
(see DrawLine
) draws/erases/copies a single point
+on the screen.
char TestPoint (struct pixel *myPixel)
This function tests if given pixel is set and returns true
(non-zero) or false
(zero).
cpputsxy (char x, char y, char *myString)
cpputs (char *myString)
Actually this is a part of conio
, but this function is non-standard. It is
+a variety of cputs
that will output string with proportional spacing, not
+fixed like cputs
.
void PutChar (char character, char y, unsigned x)
This function outputs single character using current style and font to screen.
+ +void PutString (char *myString, char y, unsigned x)
Same as PutChar
except the fact that you can output whole NULL
-terminated string.
+See ggraph.h
for list of tokens that you can also place in the string - like CBOLDON
or
+COUTLINEON
.
void PutDecimal (char parameter, unsigned value, char y, unsigned x)
This function converts value
to its decimal representation and outputs it to the screen.
+The parameter
is the field width in pixels (range 1-31) and mode bits. Depending on them
+the string can be filled with zeroes (string always 5 characters long) or not and left or right
+justified to given pixel. See ggraph.h
for predefined values for parameter
.
char GetCharWidth (char character)
This function returns real width (in pixels) of given character with current font. It can be used +for counting the length of string on screen, allowing for indentation or justification.
+ +void LoadCharSet (struct fontdesc *myFont)
This function forces GEOS to use given font instead of own. myFont
should be casted from
+pointer to the start of area where was loaded record from font file (VLIR structure).
void UseSystemFont (void)
This function forces GEOS to use built-in BSW font.
+ +I'm not quite sure how are these functions working (except BitmapUp
) so you should
+probably look into library sources and compare it with your knowledge. Please let me know
+if something is wrong or broken.
void BitmapUp (struct iconpic *myPic)
This function unpacks the bitmap and places it on the screen - just as you set it in the
+struct iconpic
pointer to which you pass. See gstruct.h
for description of this
+structure. Note that you can only use packed GEOS bitmaps - simple Photo Scrap is in this format.
void BitmapClip (char skipLeft, char skipRight, unsigned skipTop, struct iconpic *myPic)
This function acts similar to BitmapUp
but you can also define which parts of the bitmap are
+to be drawn - you give the number of columns (8-pixel) to skip on the right and left of the bitmap,
+and the number of rows to skip from the top if it.
void BitOtherClip (void *proc1, void *proc2, char skipLeft, char skip Right, unsigned skipTop,
+struct iconpic *myPic)
Similar to the previous one with some extension. proc1
is called before reading a byte (it
+returns in .A next value), and proc2
is called every time the parser reads a byte which is
+not a piece of pattern (byte of code greater than 219). Both procedures should be written
+separately in assembler and declared as __fastcall__
returning char.
Here you will find information about functions related with menus and icons.
+ +Menus are essential for GUI. GEOS can handle only one menu at a time, but each menu can call +another one, which results in submenu tree. There can be up to 8 menu levels, each one with up +to 32 items.
+Menus are initialized with DoMenu
and then Kernal takes care for everything. Your code
+(called from event handler) should be a function without parameters, returning void. You should
+use DoPreviousMenu
or GotoFirstMenu
at least once in its code to have the screen clean.
void DoMenu (struct menu *myMenu)
This function initializes GEOS menu processor and exits. See DoMenu structure
for more
+information about it. Know that many GEOS application just initializes the screen, menu and
+exits to main Kernal loop, this proves the power of DoMenu
.
void ReDoMenu (void)
This simply redraws the menu at lowest level. It works like calling DoMenu
again with
+the same parameters.
void RecoverMenu (void)
This function erases current menu from the screen. It doesn't change the menu level.
+ +void RecoverAllMenus (void)
This calls RecoverMenu
and erases all menus from the screen. Then the menu level is
+set to 0 (topmost).
void DoPreviousMenu (void)
This functions causes menu processor to go back one menu level. You should use it in menu +handler code to have the screen clean.
+ +void GotoFirstMenu (void)
This one jumps back to the topmost menu. If there is only menu and submenu it works the
+same as DoPreviousMenu
.
Icons are working similar to menus except the fact that there is only one level. Icons are
+defined as a screen area filled with a bitmap, but if you would setup icons and erase the
+screen they are still active and clicking in the place where formerly an icon was will cause
+an effect. Similarly if you would setup icons and then turn them off with ClearMouseMode
+the bitmap will be still on the screen but clicking on it would not cause any action.
+There is only one, but powerful icon function.
void DoIcons (struct icontab *myIconTab)
This function initializes all icons that are present on the screen at once. For more information
+look at Icons
chapter in this manual.
This chapter covers the most powerful GEOS user interface function - DoDlgBox
.
char DoDlgBox (char *dialogString)
DialogBox returns one byte. It can be the value of one of six standard icons (see gdlgbox.h
)
+or whatever closing routine passes. Register r0L
also contains this value.
Read structures chapter for the specs of the dialogString
.
char RstrFrmDialogue
This function called from within DialogBox event immediately closes the DialogBox and returns +the owner ID (or whatever caller has in the .A register).
+ +To simplify usage of DoDlgBox from C I've wrote some help functions - wrappers for DoDlgBox, +with predefined data. In one word - these are standard DialogBoxes you can see in almost every +GEOS application.
+ +char DlgBoxYesNo (char *line1, char *line2)
char DlgBoxOkCancel (char *line1, char *line2)
void DlgBoxOk (char *line1, char *line2)
These function show two lines of text in standard-sized DialogBox. You can read the code of
+pressed icon from return value. E.g. for DlgBoxYesNo
it can only be YES
or NO
.
+You can pass an empty string or NULL to get a blank line.
char DlgBoxGetString (char *string, char strlen, char *line1, char *line2)
This function prompts user for entering a string of at most strlen
characters. It is returned
+in string
. The two given lines of text are shown above the input line. Please remember
+that there is also CANCEL
icon in the DialogBox and you should test if user confirmed his
+input or gave up. The string
is also shown so you can place default input there or remember
+to place NULL
at start.
char DlgBoxFileSelect (char *class, char filetype, char *filename)
This routine is the standard file selector. It can return OPEN
, CANCEL
or disk error
+on reading the directory or opening the disk.
+There is also DISK
icon shown, but it is handled internally. You pass as input parameters
+filetype
and pointer to string containing the first part of file's class. If this string is
+empty (NULL
at the start), then all files with given filetype will be shown.
At present this file selector handles only first 16 files of given type and supports only one +(current) drive.
+ +char MessageBox (char mode, const char *format, ...)
This function is a more general one. It works very much like printf
in a
+box. The only difference is mode
parameter which allows for placing
+default icons (see gdlgbox.h
for list of possible MB_
values).
+Any too wide text will be clipped to the size of the default window. If mode
+parameter is invalid or equal to MB_EMPTY
then the window will be closed
+after a click. Otherwise the user must choose an icon.
Note: use it if you really need (or if you will use it in many places) as +it adds quite amount of code to your program.
+Note: the formatted text cannot exceed 255 bytes in length, there is no check +for that.
+ +You will find here functions related to sprite and mouse drawing and handling.
+ +These cover mouse - as a general pointing device, but expect user to utilize as different devices +as digital or analog joystick, mouse, lightpen or koalapad (whatever it is).
+ +void StartMouseMode (void)
This function initializes mouse vectors - mouseVector
and mouseFaultVec
, and then
+calls MouseUp
.
void ClearMouseMode (void)
This function disables all mouse activities - icons and menus stop to respond to mouse events, +but they are not cleared from the screen.
+ +void MouseUp (void)
void MouseOff (void)
The first function turns the mouse pointer on. It will appear on next IRQ. The second one does +the opposite - it turns off the pointer, but its position is still updated by input driver.
+ +char IsMseInRegion (struct window *myWindow)
This function tests if mouse pointer is actually in given range of screen. See gsprite.h
for
+description of bits in return values - they describe the position in detail.
You are free to use any of the eight sprites, but keep in mind that sprite 0 is actually the mouse +pointer and sprite 1 can be overwritten when using text prompt. You don't have to worry about +40/80 column issues because GEOS128 has pretty good sprite emulator for VDC.
+ +void DrawSprite (char sprite, char *mySprite)
This function initializes the sprite data. mySprite
is a 63-byte table with bitmap data, which
+is copied to system sprite area (at sprpic
- see gsym.h
). Hardware sprite registers are
+not initialized and sprite is not yet visible.
void PosSprite (char sprite, struct pixel *myPixel)
This function positions the sprite on the screen. Given coordinates are screen ones - they are +converted to sprite coordinates by GEOS. Due to this you cannot use this function to position your +sprite off the left or top to the screen.
+ +void EnablSprite (char sprite)
void DisablSprite (char sprite)
These two functions are responsible for making the sprite visible or not.
+ +void InitTextPrompt (char height)
This function initializes sprite 1 for text prompt with given height
. This parameter can be in
+range 1-48.
void PromptOn (struct pixel *myPixel)
void PromptOff (void)
The first function places text prompt in given place and enables blinking. +The second one is pretty self-explanatory.
+ +char GetNextChar (void)
This function gets next character from the keyboard queue. If the queue is empty it returns
+NULL
, otherwise you receive true ASCII code of a character or value of special (function)
+key. See gsprite.h
for list of them.
This chapter covers slightly low-level disk routines. You should use them with care, because +you may easily corrupt data on disks. Also remember that contemporary GEOS supports many various +devices and sticking to 1541 track layout (e.g. expecting the directory on track 18) might be +dangerous.
+For some purposes you might consider using dio.h
interface to disk access. It is native.
All GEOS disk functions return error code in X register. In some cases this is returned by
+GEOSLib function (if its type is char
), but in all cases last error is saved in __oserror
+location. If it is nonzero - an error occured. See gdisk.h
for the list of possible errorcodes.
+You need to include errno.h
to get __oserror
, together with standard errno
. The
+latter gives less verbose, but still usable information and can be used with strerror
.
+Probably you will get more information using _stroserror
in similar way.
For passing parameters use almost always pointer to your data e.g. ReadBuff (&myTrSe)
.
These functions are taking single data sector (256 bytes) to read or write on a disk.
+ +char ReadBuff (struct tr_se *myTrSe)
char WriteBuff (struct tr_se *myTrSe)
These functions read and write sector placed at diskBlkBuf
.
char GetBlock (struct tr_se *myTrSe, char *buffer)
char ReadBlock (struct tr_se *myTrSe, char *buffer)
These two functions are reading a single block directly at 256 byte array placed at buffer
.
+The difference between them is that GetBlock
will initialize TurboDos in drive if it was not
+enabled. ReadBlock
assumes that it is already enabled thus being slightly faster.
char PutBlock (struct tr_se *myTrSe, char *buffer)
char WriteBlock (struct tr_se *myTrSe, char *buffer)
char VerWriteBlock (struct tr_se *myTrSe, char *buffer)
Similar to previous but needed for writing the disk. VerWriteBlock
verifies the data after
+writing. In case of error five tries are attempted before error code is returned.
Functions described here are operating on curDirHeader
where current disk header is stored.
+On larger capacity drives (than 1541) the second part of directory header in dir2Head
.
void GetPtrCurDkNm (char *diskName)
This function fills given character string with the name of current disk. It is converted to C
+standard - string is terminated with NULL
character instead of code 160 as in Commodore DOS.
+Note that passed pointer must point to an array of at least 17 bytes.
char GetDirHead (void)
char PutDirHead (void)
These functions are reading and writing the directory header. You should use GetDirHead
before
+using any functions described below, and you should use PutDirHead
to save the changes on the
+disk. Otherwise they will be lost. Operating area is the curDirHead
.
unsigned CalcBlksFree (void)
This function returns the number of free blocks on current disk. It is counted using data in
+curDirHead
so you must initialize the disk before calling it.
char ChkDskGEOS (void)
This functions checks curDirHead
for GEOS Format identifier. It returns either true or false,
+and also sets isGEOS
properly. You must initialize the disk before using this.
char SetGEOSDisk (void)
This function initializes disk for use with GEOS. It sets indicator in directory header and +allocates a sector for the directory of border files. You don't need to initialize the disk before +using.
+ +char FindBAMBit (struct tr_se *myTrSe)
This function returns the bit value from BAM (Block Allocation Map) for given sector. The bit is +set if the sector is free to use. Returned value is always zero if the sector is already allocated. +In fact, this function could be used in a following way: +
+
+#define BlockInUse FindBAMBit
+...
+if (!BlockInUse(&myTrSe)) {
+... block not allocated ...
+}
+
+
+
+Anyway, I feel that this function is too low-level.
+ +char BlkAlloc (struct tr_se output[], unsigned length)
char NxtBlkAlloc (struct tr_se *myTrSe, struct tr_se output[], unsigned length)
Both functions are allocating enough disk sectors to fit the number of length
in them. You
+will find output in output
which is table of struct tr_se
. The last entry will have the
+number of track equal to 0 and sector equal to 255. The simplest way of using them is to use
+predefined space in GEOS data space and pass fileTrScTab
, which is a predefined table.
The difference between those two is that NextBlkAlloc
will start allocating from given sector,
+and BlkAlloc
starts from the first nonused sector.
You need to use PutDirHead
later to save any changes in BAM.
char FreeBlock (struct tr_se *myTrSe)
Simply deallocates a block in BAM. You need to update BAM with PutDirHead
.
struct tr_se SetNextFree (struct tr_se *myTrSe)
This function finds the first free sector starting from given track and sector and allocates it.
+It might return the same argument if the given block is not allocated. I wanted it to be type
+clean, but it made usage a bit tricky. To assign a value to own struct tr_se
you have to
+cast both variables to unsigned
. E.g.
+
+
+struct tr_se myTrSe;
+...
+(unsigned)myTrSe=(unsigned)SetNextFree(&otherTrSe);
+
+
+
+In this example otherTrSe
can be replaced by myTrSe
.
Note: you must use casting to have correct values.
+ +Functions described here are more usable in kernal or drivers code, less common in applications, +but who knows, maybe someone will need them.
+ +void EnterTurbo (void)
void ExitTurbo (void)
void PurgeTurbo (void)
These functions are interface to GEOS TurboDos feature which makes slow Commodore drives a bit
+more usable. EnterTurbo
enables TurboDos unless it is already enabled. If not, then you will
+have to wait a bit to transfer TurboDos code into disk drive RAM. ExitTurbo
disables TurboDos.
+This is useful for sending some DOS commands for drive e.g. for formatting. Note that before any
+interaction with Kernal in ROM you have to call InitForIO
. You don't have to worry about speed.
+EnterTurbo
will only enable TurboDos (no code transfer) if TurboDos was disabled with
+ExitTurbo
. PurgeTurbo
acts different from ExitTurbo
- it not only disables TurboDos,
+but also removes it from drive RAM (not quite true, but it works like that). After using
+PurgeTurbo
the next call to EnterTurbo
will reload drive RAM.
char ChangeDiskDevice (char newDevice)
This function changes logical number of current device (in fact drives only) with given one. It is
+usable for swapping drives. There's no check if given newDevice
already exist, so if you want
+to change the logical number of drive 8 to 9 and you have drive number 9 then GEOS will probably
+hang on disk access. Use safe, large numbers. Note that safe IEC range is 8-31.
GEOS has two functions for initialization ('logging in' as they say on CP\M) the disk.
+char OpenDisk (void)
This function initializes everything for a new disk. It loads and enables TurboDos if needed.
+Then the disk is initialized with NewDisk
. Next, GetDirHead
initializes curDirHead
.
+Disk names are compared and if they differ then disk cache on REU is cleared. Finally format is
+checked with ChkDkGEOS
and disk name is updated in internal tables.
char NewDisk (void)
This function is similar to DOS command I. It clears REU cache and enables TurboDos if needed.
+ +This section cover GEOS file interface.
+ +Functions described here are common for SEQ and VLIR structures.
+ +struct filehandle *Get1stDirEntry (void)
struct filehandle *GetNxtDirEntry (void)
These two functions are best suited for scanning whole directory for particular files. Note that
+returned filehandles describes all file slots in the directory - even those with deleted files.
+The return value can be obtained by casting both sides to unsigned
- as in SetNextFree
+function or read directly after call to those two functions from r5
. Current sector number
+is in r1
and sector data itself is in diskBlkBuf
.
char FindFile (char *fName)
This function scans whole directory for the given filename. It returns either 0 (success) or 5
+(FILE_NOT_FOUND, defined in gdisk.h
) or any other fatal disk read error. After successful
+FindFile
you will have struct filehandle
at dirEntryBuf
filled with file's data and
+other registers set as described in GetNxtDirEntry
.
char FindFTypes (char *buffer, char fType, char fMaxNum, char *classTxt)
This function scans directory and fills a table at buffer
with char [17]
entries.
+fType
is GEOS type of searched files and classTxt
is a string for Class field in file
+header. Class will match if given will be equal or shorter than that found in file's header block.
+If you want just to find all files with given GEOS type you should pass empty string or NULL
as
+classTxt
. Be warned that for searching NON_GEOS
files must pass NULL
as classTxt
.
+fMaxNum
is the maximal number of found files, thus the buffer
must
+provide area of size equal to 17 * fMaxNum
.
+This function returns the number of found files, ranging from 0 to number passed as fMaxNum
.
+Return value can be also restored from r7H
.
char DeleteFile (char *fName)
This function deletes a file by its name. It works for SEQ and VLIR files.
+ +char RenameFile (char *oldName, char *newName)
I think it is obvious...
+ +char GetFHdrInfo (struct filehandle *myFile)
This function loads the file header into fileHeader
buffer. Using after e.g. FindFile
+you can pass address of dirEntryBuf
.
Functions described here are common for SEQ and VLIR structures because arguments passed are +starting track and sector which may point either to start of a chain for VLIR or data for SEQ.
+ +char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, const char *datafname)
This routine loads and runs a given file fname
. The file must be one of following types:
+SYSTEM, DESK_ACC, APPLICATION, APPL_DATA, PRINTER,
or INPUT_DEVICE
. The execution
+address is taken from file header. If it is zero, then file is only loaded. Only the first chain
+from VLIR files is loaded. If flag
has bit 0 set then load address is taken from loadaddr
+and not from file header. In this case APPLICATION
files will be only loaded, not executed.
+This does not apply to DESK_ACC
. If either bit 6 or 7 of flag
are set, then 16 bytes from
+datadname
is copied to dataDiskName
and 16 bytes from datafname
goes to dataFileName
+thus becoming parameters for the new application. Pass NULL
as any unused parameter.
char ReadFile (struct tr_se *myTrSe, char *buffer, unsigned fLength)
This function reads at most fLength
bytes into buffer
from chained sectors starting at
+myTrSe
.
char ReadByte (void)
This function returns next byte from a file. Before the first call to it you must load r5
+with NULL
, r4
with sector buffer address and r1
with track and sector of the
+first block of a file.
+Remember to not modify r1
, r4
and r5
. These registers must be preserved between
+calls to ReadByte
.
Returned value is valid only if there was no error. End of file is marked as BFR_OVERFLOW
+in __oserror
, this is set when trying to read one byte after the end of file, in this case
+returned value is invalid.
char SaveFile (char skip, struct fileheader *myHeader)
SaveFile
will take care of everything needed to create a GEOS file, no matter VLIR of SEQ
+structure. All you need to do is to place data in proper place and prepare a header which will
+contain all information about a file. The skip
parameter says how many directory pages you
+want to skip before searching for a free slot for directory entry. In most cases you will put
+0
there.
You have to declare a struct fileheader
and fill it with proper values. There is only one
+difference - the first two bytes which are link to nonexistent next sector are replaced by a
+pointer to the DOS filename of the file.
When saving sequential files two most important fields in struct fileheader
are fileheader.load_address
+and fileheader.end_address
.
char FreeFile (struct tr_se myTable[])
This function deallocates all sectors contained in passed table.
+ +char FollowChain(struct tr_se *myTrSe, char *buffer)
This function fills a struct tr_se
table at buffer
with sector numbers for chain of
+sectors starting with myTrSe
. You can pass such data (buffer
) to e.g. FreeFile
.
Here are informations about VLIR files (called later as RecordFile) and functions.
+VLIR is a file which consists of up to 127 SEQ-like files called records. Each record is like one
+SEQ structure file. Records are grouped together, described by common name - VLIR file name and
+own number. Each record pointed by its number is described by starting track and sector numbers.
+VLIR structures allow records to be empty (tr_se
of such record is equal to {NULL,$ff}
),
+or even non-exist ({NULL,NULL}
). Any other numbers represent starting track and sector of
+particular file.
In GEOS there can be only one file opened at a time. Upon opening VLIR file some information
+about it are copied into memory. You can retrieve records table at fileTrScTab
(table of
+128 struct tr_se
) and from VLIRInfo
(struct VLIR_info
.
+E.g. size of whole VLIR file can be retrieved by reading VLIRInfo.fileSize
.
char OpenRecordFile (char *fName)
This function finds and opens given file. An error is returned if file is not found or if it is not
+in VLIR format. Information in VLIRInfo
is initialized. VLIR track and sector table is
+loaded at fileTrScTab
and will be valid until call to CloseRecordFile
so don't modify it.
+You should PointRecord
before trying to do something with file.
char CloseRecordFile (void)
This function calls UpdateRecordFile
and clears internal GEOS variables.
char UpdateRecordFile (void)
This function will check VLIRInfo.fileWritten
flag and if it is set, then curDirHead
is
+updated along with size and date stamps in directory entry.
char PointRecord (char recordNumber)
This function will setup internal variables (and VLIRInfo.curRecord
) and return the track and
+sector of given record in r1
. Note that the data may not be valid (if record is non-existing
+you will get 0,0 and if it is empty - 255, 0).
char NextRecord (void)
char PreviousRecord (void)
These two work like PointRecord
. Names are self-explanatory.
char AppendRecord (void)
This function will append an empty record ( pair of 255,0 ) to current VLIR track and sector
+table. It will also set VLIRInfo.curRecord
to its number.
char DeleteRecord (void)
This function will remove current record from the table, and move all current+1 records one place
+back (in the table). Note that there's no BAM update and you must call UpdateRecordFile
to
+commit changes.
char InsertRecord (void)
This function will insert an empty record in place of VLIRInfo.curRecord
and move all following
+records in table one place forward (contents of VLIRInfo.curRecord
after call to InsertRecord
+can be found in VLIRInfo.curRecord + 1
).
char ReadRecord (char *buffer, unsigned fLength)
char WriteRecord (char *buffer, unsigned fLength)
This function will load or save at most fLength
bytes from currently pointed record into or from
+buffer
.
Functions covered in this section are common for whole C world - copying memory parts and
+strings is one of the main computer tasks. GEOS also has interface to do this. These functions
+are replacement for those like memset, memcpy, strcpy
etc. from standard libraries.
+If you are dealing with short strings (up to 255 characters) you should use these functions
+instead of standard ones. E.g. CopyString
instead of strcpy
. It will work faster.
However some of them have slightly different calling convention (order of arguments to be specific), +so please check their syntax here before direct replacing.
+Please note that the memory areas described here as strings are up to 255 characters (without
+counting the terminating NULL
), and regions can cover whole 64K of memory.
void CopyString (char *dest, char *src)
This function copies string from src
to dest
, until it reaches NULL
. NULL
+is also copied.
char CmpString (char *s1, char *s2)
This function compares string s1
to s2
for equality - this is case sensitive, and both
+strings have to have the same length. It returns either true
(non-zero) or false
(zero).
void CopyFString (char length, char *dest, char *src)
char CmpFString (char length, char *s1, char *s2)
These two are similar to CopyString
and CmpString
except the fact, that you provide
+the length of copied or compared strings. The strings can also contain several NULL
+characters - they are not treated as delimiters.
unsigned CRC (char *src, unsigned length)
This function calculates the CRC checksum for given memory range. I don't know if it is +compatible with standard CRC routines.
+ +void *FillRam (char *dest, char value, unsigned length)
void *ClearRam (char *dest, unsigned length)
Both functions are filling given memory range. ClearRam
fills with 0s
, while
+FillRam
uses given value
. Be warned that these functions destroy r0, r1 and
+r2L
registers. These are aliases for memset
and bzero
, respectively.
void *MoveData (char *dest, char *src, unsigned length)
This functions copies one memory region to another. There are checks for overlap and the
+non-destructive method is chosen. Be warned that this function destroys contents of
+r0, r1 and r2
registers. This is also alias for memcpy
void InitRam (char *table)
This function allows to initialize multiple memory locations with single bytes or strings.
+This is done with table
where everything is defined. See structures chapter for description of
+InitRam's
command string.
void StashRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)
void FetchRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)
void SwapRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)
char VerifyRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)
These functions are interface to REU - Ram Expansion Unit. I think that they are self-explanatory.
+You can check for REU presence by taking value of ramExpSize
. You have to do it before
+using any of these functions.
Weird? Not at all. GEOS has limited multitasking ability. You can set up a chain of functions +called in specified intervals and you can put the main program to sleep without disturbing other +tasks and making user interface unresponsive.
+ +void InitProcesses (char number, struct process *processTab)
This is the main initialization routine. After calling it processes are set up, but not
+enabled. The parameters for InitProcesses
are:
+
number
- number of processesprocessTab
- table of struct process
, with size equal to number
Single task is described by entry in processTab
, it contains two values - pointer
to
+task function and number of jiffies
which describe the delay between calls to task. On PAL
+systems there are 50 jiffies per second, while on NTSC there are 60.
The maximum number of tasks is 20. Be warned that GEOS doesn't check if parameters are valid and
+if processTab
would be too large it would overwrite existing data in GEOS space.
There's one important thing - the last entry in processTab
has to be NULL,NULL
, so the
+maximum size of processTab
is equal to 21.
See description of process
structure for more detailed discussion on this.
void RestartProcess (char processNumber)
void EnableProcess (char processNumber)
These two functions start the task counter. RestartProcess
for each process should be called
+after InitProcesses
, because it resets all flags and counters and it starts the counters.
RestartProcess
enables counters and sets their initial value to that given in processTab
.
EnableProcess
forces given process to execute by simulating the timer running out of time.
void BlockProcess (char processNumber)
void UnBlockProcess (char processNumber)
BlockProcess
disables the execution of given process, but this does not disable the timers.
+It means that if you call UnBlockProcess
before timer runs out, the process will be executed.
UnBlockProcess
does the opposite.
void FreezeProcess (char processNumber)
void UnFreezeProcess (char processNumber)
FreezeProcess
disables timer for given process. UnFreezeProcess
does the opposite.
+This is not equal to RestartProcess
as timers are not reloaded with initial value.
void Sleep (unsigned jiffies)
This function is multitasking sleep - the program is halted, but it doesn't block other functions
+e.g. callbacks from menus and icons.
+The only argument here is the number of jiffies to wait until app will wake up. It depends on
+video mode (PAL or NTSC) how many jiffies there are per second (50 or 60, respectively).
+If you don't want to worry about it and need only full second resolution, call standard
+sleep
function from unistd.h
.
void FirstInit (void)
This function initializes some GEOS variables and mouse parameters. This is called on GEOS boot +up. You shouldn't use this unless you know what you are doing.
+ +void InitForIO (void)
void DoneWithIO (void)
These functions are called by some disk routines. You should call them only if you want to +do something with IO registers or call one of Kernal ROM routines. Note that this is rather an +expensive way of turning off IRQs and enabling IO.
+ +void MainLoop (void)
Returns control to the system. Any code between call to MainLoop
and the end of current
+function will never be executed. When in MainLoop
systems waits for your action - using
+icons, keyboard or menus to force some specific action from program. You have to define
+proper handlers before that.
void EnterDeskTop (void)
This is an alias for exit(0)
so you will never burn yourself. Anyway, you should not
+use it. Always use exit()
instead. Library destructors and functions registered with
+atexit()
are called.
void ToBASIC (void)
This one is another way of finishing application - forcing GEOS to shutdown and exit to BASIC. +I was considering whether to include it or not, but maybe someone will need it. Which is I doubt.
+WARNING: library destructors and functions registered with atexit()
will not be called
+so it is quite unsafe way to finish your program.
void Panic (void)
This calls system's Panic
handler - it shows dialog box with message
+
+
+System error at:xxxx
+
+
+
+where xxxx
is last known execution address (caller). By default this is bound to BRK
+instruction, but it might be usable in debugging as kind of assert
. (Note that assert
+is available as a separate function and will give you more information than that).
+System is halted after call to Panic
which means that library destructors will not be
+called and some data may be lost (no wonder you're panicking).
void CallRoutine (void *myFunct)
This is system caller routine. You need to provide pointer to a function and it will be immediately
+called, unless the pointer is equal to NULL
. This is the main functionality of this function -
+you don't need to check if the pointer is valid.
unsigned GetSerialNumber (void)
This function returns the serial number of system. It might be used for copy-protection. +However, please remember that the Free Software is a true power and you are using it +right now.
+ +char GetRandom (void)
This function returns a random number. It can be also read from random
e.g.
+
+
+a=random;
+
+
+
+but by calling this function you are sure that the results will be always different.
+random
is updated once a frame (50Hz PAL) and on every call to GetRandom
.
+Note that it is not the same as rand
function from the standard library. GetRandom
+will give you unpredictable results (if IRQs would occur between calls to it) while
+rand
conforms to the standard and for given seed (srand
) it always returns with the
+same sequence of values.
void SetDevice (char device)
This function sets current device to given. It might be used together with InitForIO
,
+DoneWithIO
and some Kernal routines. Unless new device is a disk drive this only sets
+new value in curDevice
, in other case new disk driver is loaded from REU or internal RAM.
char get_ostype (void)
This function returns GEOS Kernal version combined (by logical OR) with machine type. Read
+gsys.h
for definitions of returned values.
char get_tv (void)
This function returns PAL/NTSC flag combined (by logical OR) with 40/80 columns flag. This is
+not the best way to check if screen has 40 or 80 columns since PAL/NTSC check is always
+performed and it can take as long as full raster frame. If you just want to know if
+screen has 40 or 80 columns use expression graphMode & 0x80
which returns 0
for
+40 columns and 0x80
for 80 columns. Remember that this parameter can be changed during
+runtime. It is unclear if this will work for GEOS 64 so you probably do not want to test
+anything if not running under GEOS128. Use get_ostype
to check it. Read gsys.h
for
+definitions of returned values.
To simplify usage and optimize passing parameters to functions I have declared several structures
+which describe most common objects. Some of these structures are bound to static addresses in
+GEOS data space ($8000-$8fff
), so you can use their fields directly in optimized way.
+Please see gsym.h
and find them. All structures are defined in gstruct.h
and you may
+find also some comments there.
One simple structure describing a point on the screen.
+ +This structure describes a font in one pointsize. There is current font - struct fontdesc
+bound to curFontDesc
. You can also force GEOS to use your own fonts by calling
+LoadCharSet
. You just need to open a VLIR font file and load one record - one pointsize -
+somewhere. At the start of this area you already have all data for fontdesc
so you can
+pass a pointer to the load address of that pointsize to LoadCharSet
. (Note that although
+it has 'Load' in the name, that function loads only GEOS internal data structures, not data
+from disk).
This widely used structure holds description of a region of the screen. It describes top-left and +bottom-right corners of a window.
+ +Maybe the name isn't the best - it has nothing with DoIcons
but with bitmap functions -
+BitmapUp
for example. This structure holds parameters needed to properly decode and show
+a bitmap on the screen. Bitmap has to be encoded - if you have some non-GEOS bitmaps simply
+convert them to Photo Scraps - this is the format used by all GEOS bitmap functions - DoIcons
+too.
These structures describe click boxes (icons) that can be placed on screen or in a dialog box.
+ +This is the definition of a single click box. Please see gstruct.h
for description of its fields.
This is toplevel description of icons to be placed and enabled on the screen. This structure +has following fields: +
char number
- total number of icons declared herestruct pixel mousepos
- after finishing DoIcons
mouse pointer will be placed in
+this point allowing you to have hint for user what is default actionstruct icondef tab[]
- this table of size equal to icontab.number
contains
+descriptions for all iconsThis simple structure holds track and sector number of something. Do not expect the track to be +in range 1-35, as GEOS can support many various and weird devices. For example my C128 256K +expansion is utilized as RAMDisk with layout of 4 tracks 128 sectors each. However assuming that +track number equal to 0 is illegal might be wise.
+ +This is placeholder for file datestamp. This structure is also present in struct filehandle
.
+GEOS is not Y2K compliant, so if current file has in filehandle.date.year
value less than 86
+you can safely assume that it is e.g. 2004 and not 1904.
This is main file descriptor. It is either entry in the directory (returned from file functions)
+or its copy in dirEntryBuf
. This is optimized so you can safely get to the file's year e.g.
+by testing dirEntryBuf.date.year
- it will be compiled to simple LDA, STA
.
This structure holds fileheader description. You can load file's header into fileHeader
+fixed area using GetFHdrInfo
. (note that fileHeader
is a place in memory while
+fileheader
is a structure).
+You will also need own fileheader for SaveFile
.
This structure is defined only for system_date
. It is slightly different from f_date
+so I prepared this one. You can e.g. get or set current time using system_date.s_hour
and
+system_date.s_minute
. Accesses to these will be optimized to simple LDA
and STA
+pair.
You should declare a table of that type to prepare data for InitProcesses
. The maximum number
+of processes is 20, and the last entry has to be equal to {NULL,NULL}
, so this table may hold
+only 21 entries. The first member of this structure (pointer
) holds the pointer to called
+function (void returning void), you will probably have to cast that pointer into unsigned int
.
+The second field jiffies
holds the amount of time between calls to that function.
+On PAL systems there are 50 jiffies per second, while NTSC have 60 of them.
GEOSLib uses cc65 non-ANSI extensions to easily initialize data in memory. This is done with a +kind of array of unspecified length and unspecified type. Here is how it goes: +
+
+void example = {
+ (char)3, (unsigned)3, (char)0 };
+
+
+
+Which will be compiled to following string of bytes:
+
+
+_example:
+ .byte 3
+ .word 3
+ .byte 0
+
+
+
+As you see this way it is possible to define data of any type in any order. You must remember to
+cast each member to proper type.
+
+DoMenu
is responsible for everything concerned with menu processing. Many, many GEOS programs
+are just initializing screen and menu and exit to MainLoop
. In GEOSLib it is the same as
+returning from main
function without using exit(0)
.
Menu is described by two types of data - menu descriptors and menu items. Descriptor contains +information about following menu items, and items are containing names of entries and either +pointers to functions to execute or, in case of nested menus, pointers to submenu descriptors. +Note that submenu descriptor can be top-level descriptor, there's no difference in structure, +just in the content.
+Here is how single descriptor looks like: +
+
+void myMenu = {
+ (char)top, (char)bottom, // this is the size of the menubox
+ (unsigned)left, (unsigned)right, // counting all items in current descriptor
+ (char)number_of_items | type_of_menu, // number of following items ORed with
+ // type of this menu, it can be either
+ // HORIZONTAL or VERTICAL if you will have also bit 6 set then menu won't be closed
+ // after moving mouse pointer outside the menubox. You can have at most 31 items.
+
+
+
+This is followed by number_of_items
of following item description.
+
+
+ ...
+ "menuitemname", (char)item_type, (unsigned)pointer,
+ "nextitemname", (char)item_type, (unsigned)pointer,
+ ...
+ "lastitemname", (char)item_type, (unsigned)pointer };
+ // Note that there isn't ending <tt/NULL/ or something like that.
+
+
+
+pointer
is a pointer to something, what it points for depends from item_type
. This one
+can have following values:
+MENU_ACTION
- a function pointed by pointer
will be called after clicking on menu item
SUB_MENU
- pointer
points to next menu descriptor - a submenu
Both of them can be ORed with DYN_SUB_MENU
and then the pointer
points to a function
+which will return in r0
needed pointer (to function to execute or a submenu).
For creating nested menus (you can have at most 8 levels of submenus) you need to declare such +structure for each submenu and top level menu.
+ +DoDlgBox
is together with DoMenu
one of the most powerful routines in GEOS. It is
+responsible for creating dialog boxes, that is windows which task is to interact with user.
+Format of the command string is following:
+
+
+ (window size and position)
+ (commands and parameters)
+ NULL
+
+
+
+There is custom type defined for the command string: dlgBoxStr
.
+
+The first element can be specified in two ways - by using default size and position or specifying +own. The first case results in +
+
+const dlgBoxStr example = {
+ DB_DEFPOS (pattern_of_shadow),
+ ... // commands
+ DB_END };
+
+
+
+And the own size and position would be:
+
+
+const dlgBoxStr example = {
+ DB_SETPOS (pattern, top, bottom, left, right)
+ ... // commands
+ DB_END };
+
+
+
+
+The next element of DoDlgBox
command string are commands themselves. First six commands are
+default icons and the number of selected icon will be returned from window processor. The icons are
+OK, CANCEL, YES, NO, OPEN
, and DISK
. You can use predefined macros for use them, e.g.:
+
+
+ ...
+ DB_ICON(OK, DBI_X_0, DBI_Y_0),
+ ...
+
+
+
+Note that the position is counted from top left corner of window, not entire screen and that the 'x'
+position is counted in cards (8-pixel) and not in pixels. This is true also for all following commands.
+DBI_X_0
and DBI_Y_0
are predefined (see gdlgbox.h
for more), default positions
+which will make icons to appear on default window exactly where you would expect them.
+DB_TXTSTR (x, y, text)
will cause to show given text in the window.
DB_VARSTR (x, y, ptr)
works as above, but here you are passing a pointer to a zero page location
+where the address of text is stored. This is useful for information windows where only text content
+is variable. Consider following:
+
+
+char text = "foo";
+ ...
+ r15=(unsigned)text; // in code just before call to DoDlgBox
+ ...
+ DB_VARSTR (TXT_LN_X, TXT_LN_1_Y, &r15),
+ ...
+
+
+
+will cause to appear the word ``foo'' in the window, but you may store the pointer to any text in
+r15
(in this case) before call to DoDlgBox.
+DB_GETSTR(x, y, ptr, length)
- will add input from keyboard feature. ptr
works as in
+previous example and points to place where text is to be stored. Note that the contents of this
+place will be shown upon creating window. length
is the maximum number of characters to input.
DB_SYSOPV(ptr)
- this sets otherPressVec
to given pointer. It is called on every keypress.
DB_GRPHSTR(ptr)
- data for this command is the pointer for GraphicsString
commands.
DB_GETFILES(x, y)
- for standard window you should pass 4 for both x and y. This function
+draws file selection box and searches current drive for files. Before call to DoDlgBox
you
+must load r7L
with GEOS filetype of searched files and r10
with class text. In r5
+you have to load pointer to a char[17]
where selected filename will be copied. It works
+like FindFTypes
but is limited to first 16 files.
DB_OPVEC(ptr)
- this sets the new pointer for button press function, if you pass
+RstrFrmDialogue
here you will cause the window to close after pressing mouse button.
DB_USRICON(x, y, ptr)
- places single user icon (click box) on window, ptr
points at a
+struct icondef
but fields x
and y
are not used here. You can have at most 8 click
+boxes in a window, this is internal limit of GEOS Kernal.
DB_USRROUT(ptr)
- this command causes to immediately call user routine pointed by ptr
.
GraphicsString
is a very powerful routine to initialize whole screen at once. There are
+predefined macros for all commands, names are self-explanatory, see them in ggraph.h
. Last
+command have to be GSTR_END
. There is custom type defined for the command string: graphicStr
.
Here is an example for clearing the screen: +
+
+const graphicStr example = {
+ MOVEPENTO(0,0),
+ NEWPATTERN(0),
+ RECTANGLETO(319,199)
+ GSTR_END };
+
+
+
+
+This type of data is used to initialize one or more bytes in many places at once. The format is +as following: +
+
+void example = {
+ (unsigned)address_to_store_values_at,
+ (char)number_of_bytes_that_follow,
+ (char)data,(char)data (...)
+ // more such definitions
+ (unsigned)NULL // address of 0 ends the table
+ };
+
+
+
+
+It is possible to intercept and hook in the GEOS Kernal using vectors. Here is a little example: +
+
+void_func oldVector;
+
+void NewVectorHandler(void) {
+ // do something and at the end call the old vector routine
+ oldVector();
+}
+
+void hook_into_system(void) {
+ oldVector = mouseVector;
+ mouseVector = NewVectorHandler;
+}
+
+void remove_hook(void) {
+ mouseVector = oldVector;
+}
+
+
+
+In your main
function you should call hook_into_system()
but after all calls to GEOS
+kernal (like DoMenu
, DoIcons
, etc.) - right before passing control to the MainLoop()
.
+Be warned that vectors are most likely to be changed by GEOS kernal also by other functions (like
+GotoFirstMenu
, DoDlgBox
and its derivatives etc.). It depends on what kernal functions
+you use and which vectors you altered. Unfortunately there is no exact list for GEOS 2.0, a complete
+list for GEOS 1.x can be found in A. Boyce's Programmers' Reference Guide mentioned before. Most of
+information contained there should be still valid for GEOS 2.0. When calling a function that restores
+the vector you should add a hook_into_system()
call right after it.
It is critical to restore old vector values before exiting the program. If you have more than one
+place where you call exit()
then it might be worth to register remove_hook
function to
+be called upon exiting with atexit(&remove_hook);
call. This way you will ensure that
+such destructor will be always called.
That little example above intercepts mouseVector
. The NewVectorHandler
function will be
+called every time the mouse button changes status. Other important vectors you should know about
+are:
+
appMain
- this is called from within MainLoop
system loopkeyVector
- called whenever a keypress occursintTopVector
- called at the start of IRQ routineintBotVector
- called at the end of IRQ routine+
+
+
+
grc is a part of cc65's GEOS support. The tool is necessary to +generate required and optional resources. A required resource for every GEOS +application is the header, that is: an icon, some strings, and some addresses. +Optional resources might be menu definitions, other headers (e.g., for data +files of an app.), dialog definitions, etc. Without an application's header, +GEOS is unable to load and start it.
+Currently, grc supports only menues and the required header definition, +along with support for building VLIR-structured files.
+grc generates output in three formats: C header, ca65 source (.s), +and, for linking VLIR, ld65 configuration script. That is because +application header data must be in assembly format, while menu definitions can +be translated easily into C. The purpose of the C file is to include it as a +header in only one project file. The assembly source should be processed by +ca65, and linked as the first object (read about +the building process). The VLIR structure currently +is supported for only projects that are written entirely in assembly code.
+grc can be used also as a handy VLIR linker -- used to build
+VLIR-structured .cvt
files out of prepared binary chains.
grc accepts the following options: +
+
+-f force the writing of the output files
+-o name name the .c output file
+-s name name the .s output file
+-l name name the ld65 output file
+-h show this help
+
+
+
+When used as a VLIR linker, the correct syntax is:
+
+
+ grc -vlir output.cvt header.bin vlir0.bin vlir1.bin ...
+
+
+
+Default output names are made from input names with extensions replaced by
+.h
and .s
. grc will not overwrite existing files unless forced
+to do so. That is done to avoid situations where you have test.c
and
+test.grc
files. Both would put their output into test.s
. For that
+reason, you should name your resource-files differently than sources, e.g.,
+resource.grc
or apphead.grc
.
+
+
+
+A resource file has the name extension .grc
. That is not required, but
+it will make for an easier recognition of the file's purpose. Also, cl65
+recognizes those files. grc's parser is very weak, at the moment; so,
+read the comments carefully, and write resources exactly as they are written
+here. Look out for CAPS. and small letters. Everything after a ';
',
+until the end of the line, is considered as a comment, and ignored. See the
+included
+commented example .grc file for a
+better view of the problem.
+
+
+MENU menuName leftx,topy <ORIENTATION> {
+ "item name 1" <MENU_TYPE> pointer
+ ...
+ "item name x" <MENU_TYPE> pointer
+}
+
+
+
+The definition starts with the keyword MENU
, then goes the menu's name,
+which will be represented in C as const void
. Then are the co-ordinates
+of the top left corner of the menu box. The position of the bottom right
+corner is estimated, based on the length of item names and the menu's
+orientation. It means that the menu box always will be as large as it should
+be. Then, there's the orientation keyword; it can be either HORIZONTAL
or
+VERTICAL
. Between {
and }
, there's the menu's
+content. It consists of item definitions. First is an item name -- it has to
+be in quotes. Next is a menu-type bit. It can be MENU_ACTION
or
+SUB_MENU
; either of them can be combined with the DYN_SUB_MENU
bit
+(see
+the GEOSLib documentation for descriptions of
+them). You can use C logical operators in expressions, but you have to do it
+without spaces. So, a dynamically created submenu will be something like:
+
+
+"dynamic" SUB_MENU|DYN_SUB_MENU create_dynamic
+
+
+
+The last part of the item definition is a pointer which can be any name that is
+present in the C source code that includes the generated header. It can point
+to a function or to another menu definition.
+If you are doing sub(sub)menu definitions, remember to place the lowest level +definition first, and the top-level menu as the last one. That way, the C +compiler won't complain about unknown names.
+ + ++
+
+HEADER <GEOS_TYPE> "dosname" "classname" "version" {
+ author "Joe Schmoe"
+ info "This is my killer-app!"
+ date yy mm dd hh ss
+ dostype SEQ
+ mode any
+ structure SEQ
+}
+
+
+
+The header definition describes the GEOS header sector which is unique to
+each file. Currently, there's no way to change the default grc icon
+(an empty frame). It will be possible in the next version. The definition
+starts with the keyword HEADER
, then goes the GEOS file-type. You can use
+only APPLICATION
here at the moment. Then, there are (each one in quotes)
+the DOS file-name (up to 16 characters), the GEOS Class name (up to 12
+characters), and the version info (up to 4 characters). The version should be
+written as "V
x.y", where x is the major, and y is
+the minor, version number. Those fields, along with both braces, are required.
+The lines between braces are optional, and will be replaced by default and
+current values. The keyword author
and its value in quotes name the
+programmer, and can be up to 63 bytes long. info
(in the same format) can
+have up to 95 characters. If the date
field is omitted, then the time of
+that compilation will be placed into the header. Note that, if you do specify
+the date, you have to write all 5 numbers. The dostype
can be SEQ
,
+PRG
, or USR
. USR
is used by default; GEOS usually doesn't care.
+The mode
can be any
, 40only
, 80only
, or c64only
; and,
+it describes system requirements. any
will work on both 64-GEOS and
+128-GEOS, in 40- and 80-column modes. 40only
will work on 128-GEOS in
+40-column mode only. 80only
will work on only 128-GEOS in 80-column mode,
+and c64only
will work on only 64-GEOS. The default value for
+structure
is SEQ
(sequential). You can put VLIR
there, too; but
+then, you also have to put in a third type of resource -- a VLIR-table
+description.
+
+
++
+
+VLIR headname address {
+ vlir0
+ blank
+ vlir2
+ blank
+ vlir4
+}
+
+
+
+The first element is the keyword VLIR
, then goes the name for the header
+binary file (read below), and the base address for all VLIR chains that are
+different from 0. It can be either decimal (e.g., 4096
) or hexadecimal
+with a 0x
prefix (e.g., 0x1000
). Then, between braces are the names
+of VLIR chain binaries or the keyword blank
which denotes empty chains.
+In the example, chains #1 and #3 are missing. The names between braces are
+the names of binaries that contain code for each VLIR part. They matter only
+for the generated ld65 configuration file, and will be the names of the
+resulting binary files after linking. Each one will contain one VLIR chain;
+and, they will have to be put together, in the correct order, into a VLIR
+.cvt
file, by grc in its VLIR linker mode.
+The headname
will be the name for the binary file which will contain only
+a GEOS .cvt
header made out of compiling the .s
header file that also
+was generated by grc. At the end of the resulting ld65 config. file
+(.cfg
), in comments, there will be information about what commands are
+required for putting the stuff together. Read
+this description for details.
Before proceeding, please read the +compiler, +assembler, and +linker +documentation, and find the appropriate sections about building programs, in +general.
+GEOS support in cc65 is based on the Convert v2.5 format, well-known in +the GEOS world. It means that each file built with the cc65 package has to be +deconverted, in GEOS, before it can be run. You can read a step-by-step +description of that in the GEOS section of the +cc65 Compiler Intro.
+Each project consists of four parts, two are provided by cc65. Those parts +are: +
The application header is defined in the HEADER
section of the .grc
+file, and processed into an assembly .s
file. You must assemble it, with
+ca65, into the object .o
format.
Assume that there are three input files: "test.c
" (a C
+source), "test.h
" (a header file), and
+"resource.grc
" (with menu and header definitions). Note the
+fact that I don't recommend naming that file "test.grc
",
+because you will have to be very careful with names (grc will make
+"test.s
" and "test.h
" out of
+"test.grc
", by default; and, you don't want that because
+"test.s
" is compiled from "test.c
", and
+"test.h
" is something completely different)!
One important thing -- the top of "test.c
" looks like:
+
+
+#include <geos.h>
+#include "resource.h"
+
+
+
+There are no other includes.
+
++
+$ grc resource.grc ++ +will produce two output files: "
resource.h
" and
+"resource.s
".
+Note that "resource.h
" is included at the top of
+"test.c
". So, resource compiling must be the first step.
+
+$ ca65 -t geos resource.s ++ +And, voilá -- "
resource.o
" is ready.
+
++
+$ cc65 -t geos -O test.c +$ ca65 -t geos test.s ++ +That way, you have a "
test.o
" object file which
+contains all of the executable code.
+
++
+$ ld65 -t geos -o test.cvt resource.o geos.o test.o geos.lib ++ +"
resource.o
" comes first because it contains the
+header. The next one is "geos.o
", a required starter-code
+file; then, the actual application code in "test.o
", and the
+last is the GEOS system library.
+The resulting file "test.cvt
" is an executable that's
+contained in the well-known GEOS Convert format. Note that it's name
+(test
) isn't important; the real name, after deconverting, is the DOS name
+that was given in the header definition.
At each step, a -t geos
was present on the command-line. That switch is
+required for the correct process of GEOS sequential app. building.
Currently, you can build VLIR applications only if your code is written in +assembly -- no C code allowed.
+In your sources, only the command .segment "
NAME"
+will decide which code/data goes where. File-names don't matter. Segments
+CODE
, RODATA
, DATA
, and BSS
go into VLIR part #0. Segment
+VLIR1
goes into VLIR part #1, VLIR2
goes into VLIR part #2, and so
+on.
The GEOS resource file's contents are similar to
+the sequential-file example, but there also is a
+VLIR
section and a structure VLIR
tag. Here is that part:
+
+
+VLIR vlir-head.bin 0x3000 {
+ vlir-0.bin ; CODE, RODATA, DATA, BSS
+ vlir-1.bin ; VLIR1
+ vlir-2.bin ; VLIR2
+}
+
+
+
+(Source files are only .s
.)
+OK, we have "cvthead.grc
", so let's allow grc to compile
+it:
+
+$ grc cvthead.grc ++ +Now, there are two new files: "
cvthead.cfg
" and
+"cvthead.s
" -- the first one is a config. file for ld65,
+and the second one contains the GEOS .cvt
header. It can be assembled:
++$ ca65 -t geos cvthead.s ++ +Now, we have "
cvthead.o
". The rest of the assembly
+sources can be assembled:
++$ ca65 -t geos vlir0.s +$ ca65 -t geos vlir1.s +$ ca65 -t geos vlir2.s ++ +Note that the file-names here, although similar to those from the +
VLIR
section of the .grc
file, are not significant. The only thing
+that matters is which code will go into which segment.
+Now, we can generate binaries. This time, the order of the arguments on the +command-line is not important. +
+$ ld65 -C cvthead.cfg vlir1.o cvthead.o vlir0.o vlir2.o ++ +As defined in the
.grc
file, we now have the binary parts of the
+VLIR file: "vlir-head.bin
", "vlir-0.bin
",
+"vlir-1.bin
", and "vlir-2.bin
".
+The last step is to put them together in the right order -- the order of the
+arguments is important this time! As suggested in the comments at the end
+of "cvthead.cfg
", we do:
+
+$ grc -vlir output.cvt vlir-head.bin vlir-0.bin vlir-1.bin vlir-2.bin ++ +That is the end. The file "
output.cvt
" can be
+deconverted under GEOS. Note that -C cvthead.cfg
was used on the
+ld65 command-line instead of the switch -t geos
.
+
+
+
+This is the first release of grc, and it contains bugs, for sure! I am
+aware of them; I know that the parser is weak, and if you don't follow the
+grammar rules strictly, then everything will crash. However, if you find an
+interesting bug, mail me. :-) Mail me also for help with writing your
+.grc
file correctly if you have problems with it. I would appreciate
+comments also, and help on this file because I am sure that it can be written
+better.
grc is covered by the same license as the whole cc65 package, so you +should see its documentation for more info. Anyway, if you like it, and want +to encourage me to work more on it, send me a postcard with a sight of your +neighbourhood, city, region, etc. Or, just e-mail me with info that you +actually used it. See +the GEOSLib documentation +for addresses.
+ + + ++
+
+; Note that MENU can define both menues and submenues.
+; If you want to use any C operators (such as "|", "&", etc.), do it WITHOUT
+; any spaces between the arguments (the parser is simple and weak).
+
+MENU subMenu1 15,0 VERTICAL
+; This is a vertical menu, placed at (15,0).
+{
+; There are three items, all of them will call functions.
+; The first and third ones are normal functions, see GEOSLib documentation for
+; information about what the second function should return (it's a dynamic one).
+ "subitem1" MENU_ACTION smenu1
+ "subitem2" MENU_ACTION|DYN_SUB_MENU smenu2
+ "subitem3" MENU_ACTION smenu3
+}
+
+;; Format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... }
+
+MENU mainMenu 0,0 HORIZONTAL
+; Here, we have our main menu, placed at (0,0), and it is a horizontal menu.
+; Because it is a top-level menu, you would register it in your C source by
+; using: DoMenu(&mainMenu);
+{
+; There are two items -- a submenu and an action.
+; This calls a submenu named subMenu1 (see previous definition).
+ "first sub-menu" SUB_MENU subMenu1
+; This will work the same as an EnterDeskTop() call in C source code.
+ "quit" MENU_ACTION EnterDeskTop
+}
+
+;; Format: HEADER <GEOS_TYPE> "dosname" "classname" "version"
+
+HEADER APPLICATION "MyFirstApp" "Class Name" "V1.0"
+; This is a header for an APPLICATION which will be seen in the directory as a
+; file named MyFirstApp with the Class-string "Class Name V1.0"
+{
+; Not all fields are required, default and current values will be used.
+ author "Maciej Witkowiak" ; always in quotes!
+ info "Information text" ; always in quotes!
+; date yy mm dd hh ss ; always 5 fields!
+; dostype seq ; can be: PRG, SEQ, USR (only all UPPER- or lower-case)
+; structure seq ; can be: SEQ, VLIR (only UPPER- or lower-case)
+ mode c64only ; can be: any, 40only, 80only, c64only
+}
+
+
+
++
+
+
+
+
+
+
+
+
Describes the ar65 archiver.
+ +Describes the ca65 macro assembler.
+ +Describes the ca65html assembler-source-to-HTML converter.
+ +Describes the cc65 C compiler.
+ +Describes the cl65 compile & link utility.
+ +Describes the co65 object-file converter.
+ +Describes the da65 6502/65C02 disassembler.
+ +Describes the GEOS resource compiler (grc).
+ +Describes the ld65 linker.
+ + ++
Describes the use of the tools, by building a short "hello world" +example.
+ +Contains hints on creating the most effective code with cc65.
+ +How to compile cc65 and the support tools.
+ +Debug programs, using the VICE emulator.
+ ++
A (currently incomplete) function reference.
+ +Low-level disk I/O API.
+ +The GEOSLib manual.
+ +A somewhat older text describing several cc65 internals.
+ +An overview over the cc65 runtime and C libraries.
+ +Describes the o65 file format that is used for dynamically loadable modules +and LUnix programs.
+ ++
Topics specific to the Apple ][.
+ +Topics specific to the Atari 8-bit machines.
+ +Topics specific to the Oric Atmos.
+ +Topics specific to the Commodore 128.
+ +Topics specific to the Commodore 16/116.
+ +Topics specific to the Commodore 64.
+ +Topics specific to the Commodore 610.
+ +Topics specific to the Atari Lynx Game Console.
+ +Topics specific to the Nintendo Entertainment System.
+ +Topics specific to the Commodore PET machines.
+ +Topics specific to the Commodore Plus/4.
+ +Topics specific to the Commodore VIC20.
+ ++
Somewhat outdated. Lists the differences between my cc65 releases +and the original Atari version that was created by J. R. Dunning.
+ +Known cc65 bugs.
+ +Here is who helped with the compiler and other tools.
+ +This is a short intro of how to use the compiler and the bin-utils. It contains +a step-by-step example of how to build a complete application from one C and +one assembly modules. This file does not contain a complete reference for +the tools used in the process. There are separate files describing those tools, +in detail (see +index.html).
+You are assumed to have downloaded and extracted the executables and the +target-specific files. For example: for Windows users targeting C64, you need +cc65-win32-2.10.1.zip and cc65-c64-2.10.1.zip (or, whatever the +current cc65 version is) extracted to the same directory. If you received the +files as a bzip2 archive (extension .bz2), you will need to get +the bzip2 package +to decompress it.
+Note: There is a much simpler way to compile this example, by using the +cl65 compile-and-link utility. However, it makes sense to understand how +the separate steps work. How to do the example with the cl65 utility is +described +later.
+ + +You will find a copy of the sample modules, used in the next section, in the
+"cc65/samples/tutorial
" directory. Please make sure that the compiler
+and linker can find the include and library files, by setting the environment
+variables CC65_INC
and CC65_LIB
, respectively.
To explain the development flow, I will use the following example modules:
+hello.c: +
+
+
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ extern const char text[]; /* In text.s */
+
+ int main (void)
+ {
+ printf ("%s\n", text);
+ return EXIT_SUCCESS;
+ }
+
+
+
+
+text.s: +
+
+
+ .export _text
+ _text: .asciiz "Hello world!"
+
+
+
+
+
+
+We assume that the target file should be named "hello", and the target system +is the C64.
++
+
+ +---------+
+ | hello.c |
+ +---------+
+ |
+ cc65
+ \/
+ +---------+ +---------+
+ | hello.s | | text.s |
+ +---------+ +---------+
+ | |
+ ca65 ca65
+ \/ \/
+ +---------+ +---------+ +----------+ +---------+
+ | hello.o | | text.o | | c64.o | | c64.lib |
+ +---------+ +---------+ +----------+ +---------+
+ | \ / |
+ | \ / |
+ | \ / |
+ +----------------------->ld65<-------------------------+
+ \/
+ hello
+
+
+
+c64.o
(the startup code) and c64.lib
(the C64 version of the runtime
+and C library) are provided in binary form in the cc65 package.
The compiler translates one C source into one assembly source, for each +invocation. It does not create object files directly, and it is not +able to translate more than one file per run.
+In the example above, we would use the following command line, to translate
+hello.c
into hello.s
:
+
+
+ cc65 -O -I ../../include -t c64 hello.c
+
+
+
+The -O
switch tells the compiler to do an additional optimizer run, which
+is usually a good idea, since it makes the code smaller. If you don't care
+about the size, but want to have slightly faster code, use -Oi
to inline
+some runtime functions.
The -I
switch gives a search path for the include files. You may also set
+the environment variable CC65_INC
to the search path.
The -t
switch is followed by the target system name.
If the compiler does not complain about errors in our "hello world" program, we
+will have a file named "hello.s
", in our directory, that contains the
+assembly source for the hello module.
For more information about the compiler, see +cc65.html.
+ + + +The assembler translates one assembly source into an object file, for each +invocation. The assembler is not able to translate more than one source +file per run.
+Let's translate the "hello.s" and "text.s" files from our example:
++
+
+ ca65 hello.s
+ ca65 -t c64 text.s
+
+
+
+The -t
switch is needed when translating the text.s
file, so the
+text is converted from the input character-set (usually ISO-8859-1) into the
+target character-set (PETSCII, in this example) by the assembler. The
+compiler-generated file hello.s
does not contain any character constants,
+so specification of a target is not necessary (it wouldn't do any harm,
+however).
If the assembler does not complain, we should now have two object files (named
+hello.o
and text.o
) in the current directory.
For more information about the assembler, see +ca65.html.
+ + + +The linker combines several object and library files into one output file. +ld65 is very configurable, but fortunately has a built-in configuration +for the C64, so we don't need to mess with configuration files, here.
+The compiler uses small functions to do things that cannot be done inline
+without a big impact on code size. Those runtime functions, together with the
+C library, are in an object-file archive named after the system, in this case,
+"c64.lib
". We have to specify that file on the command line, so that the
+linker can resolve those functions.
A second file (this time, an object file) needed is the startup code that +prepares the grounds for the C program to run. The startup file must be +executed first, so it must be the first file on the linker command line.
+Let's link our files to get the final executable:
++
+
+ ld65 -t c64 -o hello c64.o hello.o text.o c64.lib
+
+
+
+The argument after -o
specifies the name of the output file, the argument
+after -t
gives the target system. As discussed, the startup file must be
+the first input file on the command line (you may have to add a path here, if
+c64.o
is not in your current directory). Since the library resolves
+imports in hello.o
and text.o
, it must be specified after those
+files.
After a successful linker run, we have a file named "hello
", ready for
+our C64!
For more information about the linker, see +ld65.html.
+ + + +The cl65 utility is able to do all of the steps described above, in just +one command line, and it has defaults for some options that are very +well-suited for our example.
+To compile both files into one executable, enter:
++
+
+ cl65 -O -I ../../include -L ../../lib hello.c text.s
+
+
+
+(The -I
option is not needed if you are working under a Unix-like system
+with the include files in their default path, or if the CC65_INC
+environment variable is set correctly. The -L
option is not needed if the
+libraries are in their default path, or if the CC65_LIB
environment
+variable is set correctly. [Those two environment variables should be set to
+absolute paths.])
The cl65 utility knows how to translate C files into object files (it will +call the compiler, and then, the assembler). It does know also how to create +object files from assembly files (it will call only the assembler, for that). +It knows how to build an executable (it will pass all object files to the +linker). And finally, it has the C64 as a default target, and will supply the +correct startup file and runtime library names to the linker, so you don't +have to care about that.
+The one-liner above should give you a C64 executable named "hello
" in the
+current directory.
For more information about the compile & link utility, see +cl65.html.
+ + + +Note: this section is incomplete!
+Depending on the target, cc65 chooses several methods of making a +program available for execution. Here, we list sample emulators and +instructions for running the program. Unless noted, similar instructions +would also apply to a real machine. One word of advice: we suggest you clear +the screen at the start, and wait for a keypress at the end of your program, +as each target varies in it's start and exit conditions.
+ + +Available at +http://www.jantzer-schmidt.de/applewin/:
+Emulates Apple II+/IIe computers, with sound, video, joysticks, serial port, +and disk images. Includes monitor. Only for Windows. The package comes with +ROM and DOS 3.3 disk (called "master.dsk") images; however, you will need +a2tools (available at +http://hotel04.ausys.se/pausch/apple2/#a2tools).
+Compile the tutorial with
++
+
+cl65 -O -t apple2 hello.c text.s
+
+
+
+for the Apple II, or:
+
+
+cl65 -O -t apple2enh hello.c text.s
+
+
+
+for the Apple IIe.
+Then, insert the file into an Apple disk image, for use with an emulator. Copy
+the master.dsk
which comes with Applewin, and rename it to
+cc65.dsk
, then use a2tools:
+
+
+a2tools in -r b cc65.dsk TEST hello
+
+
+
+Note that a convention in the Apple world is that "hello" is the file which is
+run automatically upon booting a DOS disk, sort of like the "autoexec.bat" of
+the MSDOS/Windows world. We've avoided that in the example, however. Also,
+the TEST
parameter must be in caps., and is the name of the program as it
+will appear on the Apple disk.
Start the emulator, click on the Disk 1 icon, and point to cc65.dsk; +then, click the big Apple logo, to boot the system. Then, type this on the +Apple:
++
+
+BRUN TEST
+
+
+
+You will see the "Hello, World!" appear on the same line. Thanks to Oliver +Schmidt, +oliver@jantzer-schmidt.de for his help in completing this section.
+ + +Available at +http://www.a800win.atari-area.prv.pl:
+Emulates Atari 400/800/65XE/130XE/800XL/1200XL/5200, with stereo sound, disk +images, scanline-exact NTSC/PAL video, joysticks, mouse, cartridges, and RAM +expansions. Includes monitor. Unfortunately, only for Windows. You will need +the emulator, "atarixl.rom" or "atariosb.rom"/"ataribas.rom", and "dos25.xfd" +files (not supplied).
+Compile the tutorial with
++
+
+cl65 -O -t atari hello.c text.s
+
+
+
+Start the emulator, choose File>Autoboot image or File>Load +executable, and point to the "hello" executable. It is customary to +rename executables of that type to "hello.xex". The file has a 7-byte +header meant to be loaded directly from Atari DOS 2/2.5 or compatibles.
+On a real Atari, you would need a disk drive, and Atari DOS 2.5 or compatible. +Turn on the computer, type
++
+
+DOS
+
+
+
+at the BASIC prompt, then choose N. CREATE MEM.SAV,
+then choose L. BINARY LOAD, and enter HELLO
.
The emulation, also, supports that method. Look at Atari>Settings, and
+check Enable H: Patch for Hard Disk Devices, then Atari>Hard
+disks, and set the path of H1: to your executables directory, then use
+"H0:HELLO.XEX" in the above procedure (after pressing L
), to access
+your harddrive directly.
Note: There is no delay after the program exits, as you are returned +to the DOS menu. Your C program should wait for a keypress if you want to see +any output.
+ + +Available at
+http://www.zimmers.net/anonftp/pub/cbm/crossplatform/emulators/VICE/,
+and at
+http://www.ibiblio.org/pub/micro/commodore/crossplatform/emulators/VICE/:
Emulates Commodore 64/128/VIC-20/PET/CBM II/Plus 4 computers. Supports +printers, serial port and adapters, stereo sound, disk drives and images, RAM +expansions, cartridges, ethernet connection, cycle-exact NTSC/PAL video, mice, +and joysticks. Includes monitor. Runs on MSDOS/PCDOS, Win9x/ME/NT/2000/XP, OS2, +BeOS x86, Acorn RISC OS, and most Unixes.
+Compile the tutorial with +
+
+cl65 -O -t <sys> hello.c text.s
+
+
+
+Substitute the name of a Commodore computer for that <sys>
:
+c128
c16
c64
cbm510
cbm610
pet
plus4
vic20
Start the desired version of the emulator (CBM510 and CBM610 programs run on
+the CBM II [xcbm2
] emulator).
In the Windows versions of VICE, choose File>Autoboot disk/tape +image..., choose your executable, and click OK.
+In the Unix versions, hold down the mouse's first button. Move the pointer to +Smart-attach disk/tape..., and release the button. Choose your +executable, and click Autostart.
+The file has a 14-byte header which corresponds to a PRG-format BASIC program, +consisting of a single line, similar to this:
++
+
+
+1000 sys2061
+
+
+
+
+On a real Commodore with attached disk drive, you would type:
++
+
+LOAD "0:HELLO",8
+
+
+
+for VIC-20/C64, or:
++
+
+DLOAD "HELLO"
+
+
+
+on PET/CBM II/C128/C16/Plus 4; then, type
++
+
+RUN
+
+
+
+On a Commodore 128, you can combine those two commands: +
+
+RUN "HELLO"
+
+
+
+The output will appear on a separate line, and you will be returned to a BASIC +prompt.
+ + +Available at Click Here Software's +GEOS download page:
+Graphics Environment Operating System. +It provides a WIMP GUI (Windows, Icons, and Mouse-Pointer Graphical User +Interface) for Commodore's computer models 64 and 128. It can be +controlled by many different types of input devices: +
The tutorial files are different for GEOS. You will find them "next door," in
+"cc65/samples/geos
"; they are called "hello1.c
" and
+"apphello1.grc
".
Compile the tutorial with +
+
+cl65 -O -t geos hello1.c apphello1.grc
+
+
+
+Copy the resulting file "hello1
" onto a (GEOS-format) disk.
+Boot the GEOS master disk/image.
++
+When you want to run GEOS in an emulator, you must adjust that emulator so that +it does a "true drive" emulation. Each emulator has its own way of turning that +feature on. ++ +
+
+VICE even has different ways that depend on which operating system is running +the emulator. ++ ++
+- In Windows, you must click on Options (in an always visible menu). +Then, you must click on True drive emulation.
+- In Unix, you must hold down the second button on your mouse. Move +the pointer down to Drive settings. Then, move the pointer over to +Enable true drive emulation. (If there is a check-mark in front of +those words, that feature already is turned on -- then, move the pointer +off of that menu.) Release the mouse button.
+
Find the CONVERT program on the boot disk [tap the 6-key; then, you
+should see it's icon in the fourth position on the deskTop's directory
+notePad]. Move GEOS's pointer over to CONVERT's icon; double-click
+it to run that program. Click on the Disk icon; put the disk with
+"hello1
" into the drive; and, click the OK icon. Use the little
+icons under the list of file-names to move through that list until you find
+"hello1
". Click on it; and then, click on the Convrt icon.
+CONVERT will ask you to confirm that you choose the correct file; click
+YES if you did (or, click NO if you made a mistake). After the
+program has converted "hello1
" from a CBM file into a GEOS file, it will
+announce what it did -- click on OK. CONVERT will show the file list
+again. This time, click on Quit.
(You might need to put the boot disk back into the drive, in order to reload +deskTop. Then, you must swap back to the disk with the tutorial program +on it, and click on its disk icon [on the right side of the screen].)
+Now, you must find hello1. Click on the lower left-hand corner of the +directory notePad. Look at the eight file-positions on each page until you see +hello1. Double-click on its icon.
+The output is shown in a GEOS dialog box; click OK when you have finished +reading it.
+ + +We need your help! Recommended emulators and instructions for other targets +are missing. We suggest that you choose emulators with good compatibility. +Also, being able to run all computers in the target series is good for +target compatibility testing. A machine-language monitor is almost essential +for debugging, but a native debugger could be used, as well.
+Finally, emulators which run on Unix or Windows would help to reach a wider +audience.
+ ++
+
+
+
+
+
The ld65 linker combines several object modules created by the ca65 +assembler, producing an executable file. The object modules may be read +from a library created by the ar65 archiver (this is somewhat faster and +more convenient). The linker was designed to be as flexible as possible. +It complements the features that are built into the ca65 macroassembler:
++
The linker is called as follows:
++
+
+---------------------------------------------------------------------------
+Usage: ld65 [options] module ...
+Short options:
+ -( Start a library group
+ -) End a library group
+ -C name Use linker config file
+ -D sym=val Define a symbol
+ -L path Specify a library search path
+ -Ln name Create a VICE label file
+ -S addr Set the default start address
+ -V Print the linker version
+ -h Help (this text)
+ -m name Create a map file
+ -o name Name the default output file
+ -t sys Set the target system
+ -v Verbose mode
+ -vm Verbose map file
+
+Long options:
+ --cfg-path path Specify a config file search path
+ --config name Use linker config file
+ --dbgfile name Generate debug information
+ --define sym=val Define a symbol
+ --dump-config name Dump a builtin configuration
+ --end-group End a library group
+ --help Help (this text)
+ --lib file Link this library
+ --lib-path path Specify a library search path
+ --mapfile name Create a map file
+ --module-id id Specify a module id
+ --obj file Link this object file
+ --obj-path path Specify an object file search path
+ --start-addr addr Set the default start address
+ --start-group Start a library group
+ --target sys Set the target system
+ --version Print the linker version
+---------------------------------------------------------------------------
+
+
+
+
+
+Here is a description of all the command line options:
++
-(, --start-group
Start a library group. The libraries specified within a group are searched +multiple times to resolve crossreferences within the libraries. Normally, +crossreferences are only resolved within a library, that is the library is +searched multiple times. Libraries specified later on the command line +cannot reference otherwise unreferenced symbols in libraries specified +earlier, because the linker has already handled them. Library groups are +a solution for this problem, because the linker will search repeatedly +through all libraries specified in the group, until all possible open +symbol references have been satisfied.
+ + +-), --end-group
End a library group. See the explanation of the
+--start-group
option.
-h, --help
Print the short option summary shown above.
+ + +-m name, --mapfile name
This option (which needs an argument that will used as a filename for +the generated map file) will cause the linker to generate a map file. +The map file does contain a detailed overview over the modules used, the +sizes for the different segments, and a table containing exported +symbols.
+ + +-o name
The -o switch is used to give the name of the default output file. +Depending on your output configuration, this name may NOT be used as +name for the output file. However, for the builtin configurations, this +name is used for the output file name.
+ + +-t sys, --target sys
The argument for the -t switch is the name of the target system. Since this
+switch will activate a builtin configuration, it may not be used together
+with the
+-C
option. The following target
+systems are currently supported:
+
There are a few more targets defined but neither of them is actually +supported.
+ + +-v, --verbose
Using the -v option, you may enable more output that may help you to +locate problems. If an undefined symbol is encountered, -v causes the +linker to print a detailed list of the references (that is, source file +and line) for this symbol.
+ + +-vm
Must be used in conjunction with
+-m
+(generate map file). Normally the map file will not include empty segments
+and sections, or unreferenced symbols. Using this option, you can force the
+linker to include all this information into the map file.
-C
This gives the name of an output config file to use. See section 4 for more
+information about config files. -C may not be used together with
+-t
.
-D sym=value, --define sym=value
This option allows to define an external symbol on the command line. Value
+may start with a '$' sign or with 0x
for hexadecimal values,
+otherwise a leading zero denotes octal values. See also the
+SYMBOLS section in the configuration file.
-L path, --lib-path path
Specify a library search path. This option may be used more than once. It
+adds a directory to the search path for library files. Libraries specified
+without a path are searched in current directory, in the directory given in
+the LD65_LIB
environment variable, and in the list of directories
+specified using --lib-path
.
-Ln
This option allows you to create a file that contains all global labels and
+may be loaded into VICE emulator using the ll
(load label) command. You
+may use this to debug your code with VICE. Note: Older versions had some
+bugs in the label code. If you have problems, please get the latest VICE
+version.
-S addr, --start-addr addr
Using -S you may define the default starting address. If and how this +address is used depends on the config file in use. For the builtin +configurations, only the "none" system honors an explicit start address, +all other builtin config provide their own.
+ + +-V, --version
This option print the version number of the linker. If you send any +suggestions or bugfixes, please include this number.
+ + +--cfg-path path
Specify a config file search path. This option may be used more than once.
+It adds a directory to the search path for config files. A config file given
+with the
+-C
option that has no path in
+its name is searched in the current directory, in the directory given in the
+LD65_CFG
environment variable, and in the list of directories specified
+using --cfg-path
.
--dbgfile name
Specify an output file for debug information. Available information will be
+written to this file. Using the -g
option for the compiler and assembler
+will increase the amount of information available. Please note that debug
+information generation is currently being developed, so the format of the
+file and it's contents are subject to change without further notice.
--lib file
Links a library to the output. Use this command line option instead of just +naming the library file, if the linker is not able to determine the file +type because of an unusual extension.
+ + +--obj file
Links an object file to the output. Use this command line option instead +of just naming the object file, if the linker is not able to determine the +file type because of an unusual extension.
+ + +--obj-path path
Specify an object file search path. This option may be used more than once.
+It adds a directory to the search path for object files. An object file
+passed to the linker that has no path in its name is searched in current
+directory, in the directory given in the LD65_OBJ
environment variable,
+and in the list of directories specified using --obj-path
.
Starting with version 2.10 there are now several search paths for files needed +by the linker: One for libraries, one for object files and one for config +files.
+ + +The library search path contains in this order:
++
/usr/lib/cc65/lib
on
+Linux systems.LD65_LIB
if it is defined.CC65_LIB
if it is defined.
+Please note that use of this environment variable is obsolete and may
+get removed in future versions.
+--lib-path
option on the command line.The object file search path contains in this order:
++
/usr/lib/cc65/lib
on
+Linux systems.LD65_OBJ
if it is defined.CC65_LIB
if it is defined.
+Please note that use of this environment variable is obsolete and may
+get removed in future versions.
+--obj-path
option on the command line.The config file search path contains in this order:
++
/usr/lib/cc65/lib
on
+Linux systems.LD65_CFG
if it is defined.
+--cfg-path
option on the command line.The linker does several things when combining object modules:
+First, the command line is parsed from left to right. For each object file +encountered (object files are recognized by a magic word in the header, so +the linker does not care about the name), imported and exported +identifiers are read from the file and inserted in a table. If a library +name is given (libraries are also recognized by a magic word, there are no +special naming conventions), all modules in the library are checked if an +export from this module would satisfy an import from other modules. All +modules where this is the case are marked. If duplicate identifiers are +found, the linker issues a warning.
+This procedure (parsing and reading from left to right) does mean, that a +library may only satisfy references for object modules (given directly or from +a library) named before that library. With the command line
++
+
+ ld65 crt0.o clib.lib test.o
+
+
+
+the module test.o may not contain references to modules in the library +clib.lib. If this is the case, you have to change the order of the modules +on the command line:
++
+
+ ld65 crt0.o test.o clib.lib
+
+
+
+Step two is, to read the configuration file, and assign start addresses +for the segments and define any linker symbols (see +Configuration files).
+After that, the linker is ready to produce an output file. Before doing that, +it checks it's data for consistency. That is, it checks for unresolved +externals (if the output format is not relocatable) and for symbol type +mismatches (for example a zero page symbol is imported by a module as absolute +symbol).
+Step four is, to write the actual target files. In this step, the linker will +resolve any expressions contained in the segment data. Circular references are +also detected in this step (a symbol may have a circular reference that goes +unnoticed if the symbol is not used).
+Step five is to output a map file with a detailed list of all modules, +segments and symbols encountered.
+And, last step, if you give the
+-v
switch
+twice, you get a dump of the segment data. However, this may be quite
+unreadable if you're not a developer:-)
Configuration files are used to describe the layout of the output file(s). Two +major topics are covered in a config file: The memory layout of the target +architecture, and the assignment of segments to memory areas. In addition, +several other attributes may be specified.
+Case is ignored for keywords, that is, section or attribute names, but it is +not ignored for names and strings.
+ + + +Memory areas are specified in a MEMORY
section. Lets have a look at an
+example (this one describes the usable memory layout of the C64):
+
+
+ MEMORY {
+ RAM1: start = $0800, size = $9800;
+ ROM1: start = $A000, size = $2000;
+ RAM2: start = $C000, size = $1000;
+ ROM2: start = $E000, size = $2000;
+ }
+
+
+
+As you can see, there are two ram areas and two rom areas. The names +(before the colon) are arbitrary names that must start with a letter, with +the remaining characters being letters or digits. The names of the memory +areas are used when assigning segments. As mentioned above, case is +significant for these names.
+The syntax above is used in all sections of the config file. The name
+(ROM1
etc.) is said to be an identifier, the remaining tokens up to the
+semicolon specify attributes for this identifier. You may use the equal sign
+to assign values to attributes, and you may use a comma to separate
+attributes, you may also leave both out. But you must use a semicolon to
+mark the end of the attributes for one identifier. The section above may also
+have looked like this:
+
+
+ # Start of memory section
+ MEMORY
+ {
+ RAM1:
+ start $0800
+ size $9800;
+ ROM1:
+ start $A000
+ size $2000;
+ RAM2:
+ start $C000
+ size $1000;
+ ROM2:
+ start $E000
+ size $2000;
+ }
+
+
+
+There are of course more attributes for a memory section than just start and +size. Start and size are mandatory attributes, that means, each memory area +defined must have these attributes given (the linker will check that). I +will cover other attributes later. As you may have noticed, I've used a +comment in the example above. Comments start with a hash mark (`#'), the +remainder of the line is ignored if this character is found.
+ + +Let's assume you have written a program for your trusty old C64, and you would
+like to run it. For testing purposes, it should run in the RAM
area. So
+we will start to assign segments to memory sections in the SEGMENTS
+section:
+
+
+ SEGMENTS {
+ CODE: load = RAM1, type = ro;
+ RODATA: load = RAM1, type = ro;
+ DATA: load = RAM1, type = rw;
+ BSS: load = RAM1, type = bss, define = yes;
+ }
+
+
+
+What we are doing here is telling the linker, that all segments go into the
+RAM1
memory area in the order specified in the SEGMENTS
section. So
+the linker will first write the CODE
segment, then the RODATA
+segment, then the DATA
segment - but it will not write the BSS
+segment. Why? Enter the segment type: For each segment specified, you may also
+specify a segment attribute. There are five possible segment attributes:
+
+
+ ro means readonly
+ wprot same as ro but will be marked as write protected in
+ the VICE label file if -Lp is given
+ rw means read/write
+ bss means that this is an uninitialized segment
+ zp a zeropage segment
+
+
+
+So, because we specified that the segment with the name BSS is of type bss,
+the linker knows that this is uninitialized data, and will not write it to an
+output file. This is an important point: For the assembler, the BSS
+segment has no special meaning. You specify, which segments have the bss
+attribute when linking. This approach is much more flexible than having one
+fixed bss segment, and is a result of the design decision to supporting an
+arbitrary segment count.
If you specify "type = bss
" for a segment, the linker will make sure that
+this segment does only contain uninitialized data (that is, zeroes), and issue
+a warning if this is not the case.
For a bss
type segment to be useful, it must be cleared somehow by your
+program (this happens usually in the startup code - for example the startup
+code for cc65 generated programs takes care about that). But how does your
+code know, where the segment starts, and how big it is? The linker is able to
+give that information, but you must request it. This is, what we're doing with
+the "define = yes
" attribute in the BSS
definitions. For each
+segment, where this attribute is true, the linker will export three symbols.
+
+
+ __NAME_LOAD__ This is set to the address where the
+ segment is loaded.
+ __NAME_RUN__ This is set to the run address of the
+ segment. We will cover run addresses
+ later.
+ __NAME_SIZE__ This is set to the segment size.
+
+
+
+Replace NAME
by the name of the segment, in the example above, this would
+be BSS
. These symbols may be accessed by your code.
Now, as we've configured the linker to write the first three segments and +create symbols for the last one, there's only one question left: Where does +the linker put the data? It would be very convenient to have the data in a +file, wouldn't it?
+ +We don't have any files specified above, and indeed, this is not needed in a
+simple configuration like the one above. There is an additional attribute
+"file" that may be specified for a memory area, that gives a file name to
+write the area data into. If there is no file name given, the linker will
+assign the default file name. This is "a.out" or the one given with the
+
+-o
option on the command line. Since the
+default behaviour is ok for our purposes, I did not use the attribute in the
+example above. Let's have a look at it now.
The "file" attribute (the keyword may also be written as "FILE" if you like
+that better) takes a string enclosed in double quotes (`"') that specifies the
+file, where the data is written. You may specify the same file several times,
+in that case the data for all memory areas having this file name is written
+into this file, in the order of the memory areas defined in the MEMORY
+section. Let's specify some file names in the MEMORY
section used above:
+
+
+ MEMORY {
+ RAM1: start = $0800, size = $9800, file = %O;
+ ROM1: start = $A000, size = $2000, file = "rom1.bin";
+ RAM2: start = $C000, size = $1000, file = %O;
+ ROM2: start = $E000, size = $2000, file = "rom2.bin";
+ }
+
+
+
+The %O
used here is a way to specify the default behaviour explicitly:
+%O
is replaced by a string (including the quotes) that contains the
+default output name, that is, "a.out" or the name specified with the
+-o
option on the command line. Into this file, the
+linker will first write any segments that go into RAM1
, and will append
+then the segments for RAM2
, because the memory areas are given in this
+order. So, for the RAM areas, nothing has really changed.
We've not used the ROM areas, but we will do that below, so we give the file
+names here. Segments that go into ROM1
will be written to a file named
+"rom1.bin", and segments that go into ROM2
will be written to a file
+named "rom2.bin". The name given on the command line is ignored in both cases.
Assigning an empty file name for a memory area will discard the data written +to it. This is useful, if the a memory area has segments assigned that are +empty (for example because they are of type bss). In that case, the linker +will create an empty output file. This may be suppressed by assigning an empty +file name to that memory area.
+ + +Let us look now at a more complex example. Say, you've successfully tested +your new "Super Operating System" (SOS for short) for the C64, and you +will now go and replace the ROMs by your own code. When doing that, you +face a new problem: If the code runs in RAM, we need not to care about +read/write data. But now, if the code is in ROM, we must care about it. +Remember the default segments (you may of course specify your own):
++
+
+ CODE read only code
+ RODATA read only data
+ DATA read/write data
+ BSS uninitialized data, read/write
+
+
+
+Since BSS
is not initialized, we must not care about it now, but what
+about DATA
? DATA
contains initialized data, that is, data that was
+explicitly assigned a value. And your program will rely on these values on
+startup. Since there's no other way to remember the contents of the data
+segment, than storing it into one of the ROMs, we have to put it there. But
+unfortunately, ROM is not writable, so we have to copy it into RAM before
+running the actual code.
The linker cannot help you copying the data from ROM into RAM (this must be +done by the startup code of your program), but it has some features that will +help you in this process.
+First, you may not only specify a "load
" attribute for a segment, but
+also a "run
" attribute. The "load
" attribute is mandatory, and, if
+you don't specify a "run
" attribute, the linker assumes that load area
+and run area are the same. We will use this feature for our data area:
+
+
+ SEGMENTS {
+ CODE: load = ROM1, type = ro;
+ RODATA: load = ROM2, type = ro;
+ DATA: load = ROM2, run = RAM2, type = rw, define = yes;
+ BSS: load = RAM2, type = bss, define = yes;
+ }
+
+
+
+Let's have a closer look at this SEGMENTS
section. We specify that the
+CODE
segment goes into ROM1
(the one at $A000). The readonly data
+goes into ROM2
. Read/write data will be loaded into ROM2
but is run
+in RAM2
. That means that all references to labels in the DATA
+segment are relocated to be in RAM2
, but the segment is written to
+ROM2
. All your startup code has to do is, to copy the data from it's
+location in ROM2
to the final location in RAM2
.
So, how do you know, where the data is located? This is the second point,
+where you get help from the linker. Remember the "define
" attribute?
+Since we have set this attribute to true, the linker will define three
+external symbols for the data segment that may be accessed from your code:
+
+
+ __DATA_LOAD__ This is set to the address where the segment
+ is loaded, in this case, it is an address in
+ ROM2.
+ __DATA_RUN__ This is set to the run address of the segment,
+ in this case, it is an address in RAM2.
+ __DATA_SIZE__ This is set to the segment size.
+
+
+
+So, what your startup code must do, is to copy __DATA_SIZE__
bytes from
+__DATA_LOAD__
to __DATA_RUN__
before any other routines are called.
+All references to labels in the DATA
segment are relocated to RAM2
+by the linker, so things will work properly.
There are some other attributes not covered above. Before starting the +reference section, I will discuss the remaining things here.
+You may request symbols definitions also for memory areas. This may be +useful for things like a software stack, or an i/o area.
++
+
+ MEMORY {
+ STACK: start = $C000, size = $1000, define = yes;
+ }
+
+
+
+This will define three external symbols that may be used in your code:
++
+
+ __STACK_START__ This is set to the start of the memory
+ area, $C000 in this example.
+ __STACK_SIZE__ The size of the area, here $1000.
+ __STACK_LAST__ This is NOT the same as START+SIZE.
+ Instead, it it defined as the first
+ address that is not used by data. If we
+ don't define any segments for this area,
+ the value will be the same as START.
+
+
+
+A memory section may also have a type. Valid types are
++
+
+ ro for readonly memory
+ rw for read/write memory.
+
+
+
+The linker will assure, that no segment marked as read/write or bss is put +into a memory area that is marked as readonly.
+Unused memory in a memory area may be filled. Use the "fill = yes
"
+attribute to request this. The default value to fill unused space is zero. If
+you don't like this, you may specify a byte value that is used to fill these
+areas with the "fillval
" attribute. This value is also used to fill unfilled
+areas generated by the assemblers .ALIGN
and .RES
directives.
The symbol %S
may be used to access the default start address (that is,
+the one defined in the
+FEATURES section, or the
+value given on the command line with the
+-S
+option).
Segments may be aligned to some memory boundary. Specify "align = num
" to
+request this feature. Num must be a power of two. To align all segments on a
+page boundary, use
+
+
+ SEGMENTS {
+ CODE: load = ROM1, type = ro, align = $100;
+ RODATA: load = ROM2, type = ro, align = $100;
+ DATA: load = ROM2, run = RAM2, type = rw, define = yes,
+ align = $100;
+ BSS: load = RAM2, type = bss, define = yes, align = $100;
+ }
+
+
+
+If an alignment is requested, the linker will add enough space to the output
+file, so that the new segment starts at an address that is divideable by the
+given number without a remainder. All addresses are adjusted accordingly. To
+fill the unused space, bytes of zero are used, or, if the memory area has a
+"fillval
" attribute, that value. Alignment is always needed, if you have
+the used the .ALIGN
command in the assembler. The alignment of a segment
+must be equal or greater than the alignment used in the .ALIGN
command.
+The linker will check that, and issue a warning, if the alignment of a segment
+is lower than the alignment requested in a .ALIGN
command of one of the
+modules making up this segment.
For a given segment you may also specify a fixed offset into a memory area or
+a fixed start address. Use this if you want the code to run at a specific
+address (a prominent case is the interrupt vector table which must go at
+address $FFFA). Only one of ALIGN
or OFFSET
or START
may be
+specified. If the directive creates empty space, it will be filled with zero,
+of with the value specified with the "fillval
" attribute if one is given.
+The linker will warn you if it is not possible to put the code at the
+specified offset (this may happen if other segments in this area are too
+large). Here's an example:
+
+
+ SEGMENTS {
+ VECTORS: load = ROM2, type = ro, start = $FFFA;
+ }
+
+
+
+or (for the segment definitions from above)
++
+
+ SEGMENTS {
+ VECTORS: load = ROM2, type = ro, offset = $1FFA;
+ }
+
+
+
+The "align
", "start
" and "offset
" attributes change placement
+of the segment in the run memory area, because this is what is usually
+desired. If load and run memory areas are equal (which is the case if only the
+load memory area has been specified), the attributes will also work. There is
+also a "align_load
" attribute that may be used to align the start of the
+segment in the load memory area, in case different load and run areas have
+been specified. There are no special attributes to set start or offset for
+just the load memory area.
To suppress the warning, the linker issues if it encounters a segment that is
+not found in any of the input files, use "optional=yes
" as additional
+segment attribute. Be careful when using this attribute, because a missing
+segment may be a sign of a problem, and if you're suppressing the warning,
+there is no one left to tell you about it.
The FILES
section is used to support other formats than straight binary
+(which is the default, so binary output files do not need an explicit entry
+in the FILES
section).
The FILES
section lists output files and as only attribute the format of
+each output file. Assigning binary format to the default output file would
+look like this:
+
+
+ FILES {
+ %O: format = bin;
+ }
+
+
+
+The only other available output format is the o65 format specified by Andre +Fachat. It is defined like this:
++
+
+ FILES {
+ %O: format = o65;
+ }
+
+
+
+The necessary o65 attributes are defined in a special section labeled
+FORMAT
.
The FORMAT
section is used to describe file formats. The default (binary)
+format has currently no attributes, so, while it may be listed in this
+section, the attribute list is empty. The second supported format, o65, has
+several attributes that may be defined here.
+
+
+ FORMATS {
+ o65: os = lunix, version = 0, type = small,
+ import = LUNIXKERNEL,
+ export = _main;
+ }
+
+
+
+
+
+
+In addition to the MEMORY
and SEGMENTS
sections described above, the
+linker has features that may be enabled by an additional section labeled
+FEATURES
.
CONDES
is used to tell the linker to emit module constructor/destructor
+tables.
+
+
+ FEATURES {
+ CONDES: segment = RODATA,
+ type = constructor,
+ label = __CONSTRUCTOR_TABLE__,
+ count = __CONSTRUCTOR_COUNT__;
+ }
+
+
+
+The CONDES
feature has several attributes:
+
segment
This attribute tells the linker into which segment the table should be +placed. If the segment does not exist, it is created.
+ + +type
Describes the type of the routines to place in the table. Type may be one of
+the predefined types constructor
, destructor
, interruptor
, or
+a numeric value between 0 and 6.
label
This specifies the label to use for the table. The label points to the start +of the table in memory and may be used from within user written code.
+ + +count
This is an optional attribute. If specified, an additional symbol is defined +by the linker using the given name. The value of this symbol is the number +of entries (not bytes) in the table. While this attribute is optional, +it is often useful to define it.
+ + +order
Optional attribute that takes one of the keywords increasing
or
+decreasing
as an argument. Specifies the sorting order of the entries
+within the table. The default is increasing
, which means that the
+entries are sorted with increasing priority (the first entry has the lowest
+priority). "Priority" is the priority specified when declaring a symbol as
+.CONDES
with the assembler, higher values mean higher priority. You may
+change this behaviour by specifying decreasing
as the argument, the
+order of entries is reversed in this case.
Please note that the order of entries with equal priority is undefined.
+ +Without specifying the CONDES
feature, the linker will not create any
+tables, even if there are condes
entries in the object files.
For more information see the .CONDES
command in the
+ca65 manual.
STARTADDRESS
is used to set the default value for the start address,
+which can be referenced by the %S
symbol. The builtin default for the
+linker is $200.
+
+
+ FEATURES {
+ # Default start address is $1000
+ STARTADDRESS: default = $1000;
+ }
+
+
+
+Please note that order is important: The default start address must be defined
+before the %S
symbol is used in the config file. This does usually
+mean, that the FEATURES
section has to go to the top of the config file.
The configuration file may also be used to define symbols used in the link
+stage. The mandatory attribute for a symbol is its value. A second, boolean
+attribute named weak
is available. If a symbol is marked as weak, it may
+be overridden by defining a symbol of the same name from the command line. The
+default for symbols is that they're strong, which means that an attempt to
+define a symbol with the same name from the command line will lead to an
+error.
The following example defines the stack size for an application, but allows
+the programmer to override the value by specifying --define
+__STACKSIZE__=xxx
on the command line.
+
+
+ SYMBOLS {
+ # Define the stack size for the application
+ __STACKSIZE__: value = $800, weak = yes;
+ }
+
+
+
+
+
+
+The builtin configurations are part of the linker source. They are also
+distributed together with the machine specific binary packages (usually in the
+doc directory) and don't have a special format. So if you need a special
+configuration, it's a good idea to start with the builtin configuration for
+your system. In a first step, just replace -t target
by -C
+configfile
. The go on and modify the config file to suit your needs.
The builtin config files do contain segments that have a special meaning for +the compiler and the libraries that come with it. If you replace the builtin +config files, you will need the following information.
+ +The INIT segment is used for initialization code that may be reused once +executation reaches main() - provided that the program runs in RAM. You +may for example add the INIT segment to the heap in really memory +constrained systems.
+ +For the LOWCODE segment, it is guaranteed that it won't be banked out, so it +is reachable at any time by interrupt handlers or similar.
+ +This segment contains the startup code which initializes the C software stack +and the libraries. It is placed in its own segment because it needs to be +loaded at the lowest possible program address on several platforms.
+ +This segment defines the location of the memory heap used by the malloc +routine.
+ + + +If you have problems using the linker, 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 ( +uz@cc65.org).
+ + + +ld65 (and all cc65 binutils) are (C) Copyright 1998-2005 Ullrich von +Bassewitz. For usage of the binaries and/or sources the following +conditions do apply:
+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:
++
+
+
+
+
+
+
+
+
This file contains a short overview of the libraries available for the cc65 C +compiler. Please have a look at the +function reference for a list function by function. Since the function reference is +not complete (I'm working on that) it may happen that you don't find a +specific function. In this case, have a look into the header files. All +functions, that are not defined by the ISO C standard have a short comment in +the headers, explaining their use.
+ + + +The C library contains a large subset of the ISO C library. Functions are +usually missing in areas, where there is no support on typical 6502 systems. +Wide character sets are an example for this.
+I will not go into detail about the ISO functions. If a function is not +mentioned here explicitly, expect it to be available and to behave as defined +in the C standard.
+Functions that are not available:
++
tmpfile/tmpnam
+
+scanf
family of functions
+
+system
+
+ldiv
function (cc65 is currently not able to return structs
+with a size not equal to 1, 2 or 4 bytes by value).
+
+SIGSEGV
would be
+cool:-)
+
+setbuf/setvbuf/ungetc
Functions not available on all supported systems:
++
fopen/fread/fwrite/fclose/fputs/fgets/fscanf
: The functions
+are built on open/read/write/close. These latter functions are not available
+on all systems.
+
+ftell/fseek/fgetpos/fsetpos
: Support depends on the
+capabilities of the target machine.
+
+rename/remove/rewind
: Support depends on the capabilities of
+the target machine.
+
+time
: Since many of the supported systems do not have a real
+time clock, which means that the time
function is not available. Please
+note that the other functions from time.h
are available.Functions that are limited in any way:
++
strcspn/strpbrk/strspn
: These functions have a length
+limitation of 256 for the second string argument. Since this string gives a
+character set, and there are only 256 distinct characters, this shouldn't be
+a problem.
+
+getenv
: Since there is no such thing as an environment on all
+supported systems, the getenv
function will always return a NULL
+pointer.
+
+locale
: There is no other locale than the "C" locale. The
+native locale is identical to the "C" locale.In addition to these limitations, some more functions are limited if inlined +versions are requested by using -Os:
++
strlen
function only works for strings with a maximum length
+of 255 characters.
+
+isxxx
character classification functions from
+<ctype.h>
will give unpredictable results if the argument is not
+in character range (0..255). This limitation may be removed by #undef'ing
+the function name (when using -Os
, the functions are actually macros
+that expand to inline assembler code, but the real functions are still
+available if the macro definition is removed).The header file 6502.h contains some functions that make only sense with the +6502 CPU. Examples are macros to insert more or less useful instructions into +your C code, or a function to call arbitrary machine language subroutines, +passing registers in and out.
+ + + +For each supported system there's a header file that contains calls or defines +specific for this system. So, when programming for the C64, include c64.h, for +the C128, include c128.h and so on. To make the task for the Commodore systems +easier, there is also a header file named cbm.h that will define stuff common +for all CBM systems, and include the header file for the specific target +system.
+The header files contain
++
SID
. Writing to the fields of this struct will write to the SID device
+instead. Using these variables will make your program more readable and more
+portable. Don't fear ineffective code when using these variables, the
+compiler will translate reads and writes to these structs into direct memory
+accesses.
+conio.h
The conio.h
header file contains a large set of functions that do screen
+and keyboard I/O. The functions will write directly to the screen or poll the
+keyboard directly with no more help from the operating system than needed.
+This has some disadvantages, but on the other side it's fast and reasonably
+portable. conio implementations exist for the following targets:
+
The conio.h header file does also include the system specific header files +which define constants for special characters and keys.
+ + + +joystick.h
For systems that have a joystick, joystick.h
will define a subroutine to
+read the current value, including constants to evaluate the result of this
+function. To help in writing portable code, the header file will define the
+symbol __JOYSTICK__
on systems that have a joystick.
mouse.h
Some target machines support a mouse. Mouse support is currently available for +the following targets:
++
The available functions are declared in mouse.h
To help writing portable
+code, the header file will define the symbol __MOUSE__
in systems that
+support a mouse.
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 ( +uz@cc65.org).
+ + + +This C runtime library implementation for the cc65 compiler is (C) +Copyright 1998-2002 Ullrich von Bassewitz. For usage of the binaries +and/or sources the following conditions do apply:
+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:
++
+
+
+
+
+
conio.h
+
joystick.h
+
mouse.h
+
+
This file contains an overview of the Atari Lynx runtime system as it comes +with the cc65 C compiler. It describes the memory layout, Lynx specific header +files, available drivers, and any pitfalls specific to that platform.
+Please note that Lynx specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the Lynx target +is a machine language program with an executable header. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+You can also produce real carts with directory structures and encrypted
+headers by modifying the startup and linker config files. There is a simple
+example archive called lynx-cart-demo
in the
+contrib directory
+that shows how to create a complete bootable Lynx cart.
cc65 generated programs with the default setup run with the I/O area and the +kernal enabled, which gives a usable memory range of $400 - $BE3F. +All boot ROM entry points may be called directly without additional code.
+Special locations:
++
No conio support is currently available for the Lynx.
+ +The Lynx "flabode" keys, Opt 1, Pause and Opt 2 are implemented using the +conio interface. The only characters the keyboard is able to produce are +'R' for Restart (Opt 1 + Pause), 'F' for flip (Opt 2 + Pause), +'P' for pause, '1' for Opt 1, '2' for Opt 2, '3' for Opt 1 + Opt 2 and +'?' for all keys down at the same time.
+ +The C runtime stack is located at $BE3F and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing Lynx specific code may use the lynx.h
header file.
+
The following pseudo variables declared in the lynx.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.
+
MIKEY
The MIKEY
structure allows access to MIKEY chip. See the _mikey.h
+header file located in the include directory for the declaration of the
+structure.
SUZY
The SUZY
structure allows access to SUZY chip. See the _suzy.h
+header file located in the include directory for the declaration of the
+structure.
A TGI driver for the standard graphics mode (160×102 in 16 colors) is +available, but must be statically linked, because no file I/O is available. +See the documentation for the +co65 utility +for information on how to do that.
+The TGI driver is implemented as a dual buffering device. To use it as a +single-buffer device set draw page and view page to the same value 0 or 1;
+The TGI driver has a few Lynx-specific extensions.
+Calling tgi_ioctl(0, spr) will display a standard Lynx sprite on screen.
+Calling tgi_ioctl(1, 0) will do a flip screen. If you decide to flip the +screen then it may be a good idea to call the install-routine for the +joystick to get that flipped too.
+Calling tgi_ioctl(2, bgindex) will set the text background color to the index +defined by bgindex. If bgindex is 0 then the background color is transparent.
+ +No extended memory drivers are currently available for the Lynx.
+ + +A joystick driver for the standard buttons is available, but must be +statically linked, because no file I/O is available. See the documentation for +the +co65 utility for information on how to do +that.
+The joystick will check to see if the screen is flipped or not in the install +routine and adapt itself to the currect state.
+ +No mouse drivers are currently available for the Lynx.
+ + +No serial drivers are currently available for the Lynx.
+ + + +At this point in time there is no support for the cart filesystem yet. I have
+a lynx-cart-demo
example project that uses an interrupt driven display,
+has support for the cart filesystem and an abcmusic sound module.
At some point in time we may find a way to rewrite these to fit the way the
+cc65 drivers require. But for the time being you can create less portable
+applications using these Lynx specific modules in lynx-cart-demo
.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the NES runtime system as it comes +with the cc65 C compiler. It describes the memory layout, NES specific header +files, available drivers, and any pitfalls specific to that platform.
+Please note that NES specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the NES target +is a machine language program with an INES cartridge header. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ +cc65 generated programs with the default setup run with the I/O area and a +CHR bank enabled, which gives a usable memory range of $8000 - $FFF3. +All boot ROM entry points may be called directly without additional code.
+Special locations:
++
The text screen is located at VRAM $2000.
+ +The C runtime stack is located at $7FFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing NES specific code may use the nes.h
header file.
+
The following pseudo variables declared in the nes.inc
include file do
+allow access to hardware located in the address space.
+
PPU
The PPU
defines allow access to the PPU chip.
APU
The APU
defines allow access to the APU chip.
No graphics drivers are currently available for the NES.
+ +No extended memory drivers are currently available for the NES.
+ + +A joystick driver for the standard buttons is available, but must be +statically linked, because no file I/O is available. See the documentation for +the +co65 utility for information on how to do +that.
+ +No mouse drivers are currently available for the NES.
+ + +No serial drivers are currently available for the NES.
+ + + +The existing library for the NES doesn't implement C file
+I/O. There are no hacks for the read()
and write()
routines.
To be more concrete, this limitation means that you cannot use any of the +following functions (and a few others):
++
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the PET runtime system as it comes with the +cc65 C compiler. It describes the memory layout, PET specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that PET specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the PET target +is a machine language program with a one line BASIC stub. This means that a +program can be loaded as BASIC program and started with RUN. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ + +cc65 generated programs with the default setup run with the I/O area and the +kernal and BASIC ROM enabled, which gives a usable memory range of +$0400 - $7FFF (32KB machine). +All ROM entry points may be called directly without additional code.
+Special locations:
++
The text screen is located at $8000.
+ +The C runtime stack is located at $7FFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing PET specific code may use the pet.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes pet.h
and declares several functions
+common to all CBM platforms.
There are currently no special PET functions.
+ + + +Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the pet.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.
+
PIA1, PIA2
Access to the two PIA (peripheral interface adapter) chips is available via
+the PIA1
and PIA2
variables. The structure behind these variables
+is explained in _pia.h
.
VIA
The VIA
structure allows access to the VIA (versatile interface
+adapter). See the _6522.h
header file located in the include
+directory for the declaration of the structure.
No graphics drivers are currently available for the PET.
+ + +No extended memory drivers are currently available for the PET.
+ + +No joystick drivers are currently available for the PET.
+ + +No mouse drivers are currently available for the PET.
+ + +No serial drivers are currently available for the PET.
+ + + +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The extended memory at $9000 of the CBM 8x96 may be added to the heap by using +the following code:
++
+
+ /* Check for the existence of RAM */
+ if (PEEK(0x9000) == POKE(0x9000, PEEK(0x9000)+1)) {
+ /* Add it to the heap */
+ _heapadd ((void *) 0x9000, 0x2000);
+ }
+
+
+
+
+
+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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the Plus/4 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, Plus/4 specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that Plus/4 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+Since the Plus/4 and the Commodore 16/116 are almost identical (the latter are +missing the 6551 ACIA and do only have 16KB of memory), the +C16 documentation is also worth a look. The difference +between both cc65 targets is that the Plus/4 runtime uses banking to support +full 64K RAM, while the C16 does not use banking and supports up to 32K RAM. +Because banking is not needed, most C16 programs will be somewhat smaller than +the same program compiled for the Plus/4. However, programs compiled for the +C16 will always run on the Plus/4, while the reverse is not necessarily true.
+ + +The standard binary output format generated by the linker for the Plus/4 +target is a machine language program with a one line BASIC stub. This means +that a program can be loaded as BASIC program and started with RUN. It is of +course possible to change this behaviour by using a modified startup file and +linker config.
+ + +cc65 generated programs with the default setup run with the kernal and basic +banked out. This gives a usable memory range of $1000 - $FD00. +Having the kernal and basic ROMs banked out means, that no ROM entry points +may be called directly from user code.
+Special locations:
++
The text screen is located at $C00 (as in the standard setup).
+ +The color RAM is located at $800 (standard location).
+ +The C runtime stack is located at $FCFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing Plus/4 specific code may use the plus4.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes plus4.h
and declares several functions
+common to all CBM platforms.
Please note that most of the header file declarations from the plus4.h
+header file are shared between the C16 and Plus/4 configurations. For this
+reason, most of it is located in a common header file named cbm264.h
.
There are currently no special Plus/4 functions.
+ + +Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the plus4.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.
+
TED
The TED
structure allows access to the TED chip. See the
+_ted.h
header file located in the include directory for the
+declaration of the structure.
COLOR_RAM
A character array that mirrors the color RAM of the Plus/4 at $0800.
+ +No graphics drivers are currently available for the Plus/4.
+ + +No extended memory drivers are currently available for the Plus/4.
+ + + ++
plus4-stdjoy.joy
Supports up to two joysticks connected to the standard joysticks port of +the Plus/4.
+ +Currently no drivers available (in fact, the API for loadable mouse drivers +does not exist).
+ + ++
plus4-stdser.ser
Driver for the 6551 ACIA chip built into the Plus/4. Supports up to 19200 +baud, hardware flow control (RTS/CTS) and interrupt driven receives. Note +that because of the peculiarities of the 6551 chip transmits are not +interrupt driven, and the transceiver blocks if the receiver asserts flow +control because of a full buffer.
+You need an adapter to use the builtin port, since the output levels +available at the user port don't follow the RS232 standard.
+ +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The runtime for the Plus/4 uses routines marked as .CONDES
type 2 for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the interrupt handler code
+when they are linked into a program. See the discussion of the .CONDES
+feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+
This file contains an overview of the VIC20 runtime system as it comes with the +cc65 C compiler. It describes the memory layout, VIC20 specific header files, +available drivers, and any pitfalls specific to that platform.
+Please note that VIC20 specific functions are just mentioned here, they are +described in detail in the separate +function reference. Even functions marked as "platform dependent" may be available on +more than one platform. Please see the function reference for more +information.
+ + +The standard binary output format generated by the linker for the VIC20 target +is a machine language program with a one line BASIC stub. This means that a +program can be loaded as BASIC program and started with RUN. It is of course +possible to change this behaviour by using a modified startup file and linker +config.
+ + +cc65 generated programs with the default setup run with the I/O area and the +kernal and BASIC ROM enabled (RAM at $A000 - $BFFF may be used +for the heap), which gives a usable memory range of $1000 - $1DFF. +All ROM entry points may be called directly without additional code.
+Special locations:
++
The text screen is located at $1E00 (as in the standard setup).
+ +The C runtime stack is located at $1DFF and growing downwards.
+ +The C heap is located at the end of the program and grows towards the C +runtime stack.
+ +Programs containing VIC20 specific code may use the vic20.h
or cbm.h
+header files. Using the later may be an option when writing code for more than
+one CBM platform, since it includes vic20.h
and declares several functions
+common to all CBM platforms.
There are currently no special VIC20 functions.
+ + + +Some functions are available for all (or at least most) of the Commodore +machines. See the +function reference for +declaration and usage.
++
The following pseudo variables declared in the vic20.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.
+
VIC
The VIC
structure allows access to the VIC (the graphics
+controller). See the _vic.h
header file located in the include
+directory for the declaration of the structure.
VIA1, VIA2
Access to the two VIA (versatile interface adapter) chips is available via
+the VIA1
and VIA2
variables. The structure behind these variables
+is explained in _6522.h
.
COLOR_RAM
A character array that mirrors the color RAM of the VIC20 at $9600.
+ +No graphics drivers are currently available for the VIC20.
+ + +No extended memory drivers are currently available for the VIC20.
+ + ++
vic20-stdjoy.joy
Supports one standard joystick connected to the joysticks port of the VIC20.
+ +No mouse drivers are currently available for the VIC20.
+ + +No VIC1011 drivers are currently available for the VIC20.
+ + + +Command line arguments can be passed to main()
. Since this is not
+supported by BASIC, the following syntax was chosen:
+
+
+ RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5
+
+
+
++
main
is the program name.The program return code (low byte) is passed back to BASIC by use of the
+ST
variable.
The extended memory at $A000 may be added to the heap by using the following +code:
++
+
+ /* Check for the existence of RAM */
+ if (PEEK(0xA000) == POKE(0xA000, PEEK(0xA000)+1)) {<br>
+ /* Add it to the heap */
+ _heapadd ((void *) 0xA000, 0x2000);
+ }
+
+
+
+
+
+The runtime for the VIC20 uses routines marked as .CONDES
type 2 for
+interrupt handlers. Such routines must be written as simple machine language
+subroutines and will be called automatically by the interrupt handler code
+when they are linked into a program. See the discussion of the .CONDES
+feature in the
+assembler manual.
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 ( +uz@cc65.org).
+ + + +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:
++
+
+
+
+
+
+
+
+
+