co65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <date>12.02.2003 <abstract> co65 is an object file conversion utility. It converts o65 object files into the native object file format used by the cc65 tool chain. Since o65 is the file format used by cc65 for loadable drivers, the co65 utility allows (among other things) to link drivers statically to the generated executables instead of loading them from disk. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> 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. <sect>Usage<p> 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. <sect1>Command line option overview<p> The converter may be called as follows: <tscreen><verb> --------------------------------------------------------------------------- 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 --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Here is a description of all the command line options: <descrip> <tag><tt>--bss-label name</tt></tag> 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. <tag><tt>--bss-name seg</tt></tag> Set the name of the bss segment. The default name is "BSS" which is compatible with the standard ld65 linker configurations. <tag><tt>--code-label name</tt></tag> 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. <tag><tt>--code-name seg</tt></tag> Set the name of the code segment. The default name is "CODE" which is compatible with the standard ld65 linker configurations. <tag><tt>--data-label name</tt></tag> 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. <tag><tt>--data-name seg</tt></tag> Set the name of the data segment. The default name is "DATA" which is compatible with the standard ld65 linker configurations. <tag><tt>-d, --debug</tt></tag> 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 <tt/-d/. <tag><tt>-g, --debug-info</tt></tag> This will cause the converter to insert a <tt/.DEBUGINFO/ command into the generated assembler code. This will cause the assembler to include all symbols in a special section in the object file. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <tag><tt>-m model, --o65-model model</tt></tag> 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: <itemize> <item>lunix <item>os/a65 <item>cc65-module </itemize> The default is to autodetect the model to use from the input file, so there's rarely a need to use this option. <tag><tt>-n, --no-output</tt></tag> Don't do the actual conversion, just read in the o65 file checking for problems. This option may be used in conjunction with <tt/--verbose/ to view some information about the input file. <tag><tt>-o name</tt></tag> 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". <tag><tt>-v, --verbose</tt></tag> 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 <tt/--no-output/ to just get the o65 info. <tag><tt>-V, --version</tt></tag> Print the version number of the compiler. When submitting a bug report, please include the operating system you're using, and the compiler version. <tag><tt>--zeropage-label name</tt></tag> 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. <tag><tt>--zeropage-name seg</tt></tag> Set the name of the zeropage segment. The default name is "ZEROPAGE" which is compatible with the standard ld65 linker configurations. </descrip> <sect>Input and output<p> 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. <sect>Converting loadable drivers<p> <sect1>Differences between static linking and runtime loading<p> 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: <itemize> <item> Without changing the segment names, all segments take the default names used by the standard linker configurations. This means that the driver code is no longer contingous in memory, instead the code segment is placed somewhere in between all other code segments, the data segment is placed with all other data segments and so on. If the driver doesn't do strange things this shouldn't be a problem. <item> With statically linked code, data and bss segments will get intialized once (when the application is loaded), while a loadable driver will get its initialization each time the driver is loaded into memory (which may be more than once in the lifetime of a program). It depends on the driver if this is a problem. Currently, most drivers supplied with cc65 behave correctly when linked statically. </itemize> <sect1>Additional requirements<p> 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 <em/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 <tt/--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! <sect1>Example - Convert and link a graphics driver<p> 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. <tscreen><verb> co65 --code-label _c64_hi c64-hi.tgi ca65 c64-hi.s </verb></tscreen> Next, change your C code to declare a variable that is actually the address of the driver: <tscreen><verb> extern void c64_hi[]; </verb></tscreen> Instead of loading and unloading the driver, change the code to install and uninstall the driver, which will be already in memory after linking: <tscreen><verb> /* Install the driver */ tgi_install (c64_hi); ... /* Uninstall the driver */ tgi_uninstall (); </verb></tscreen> 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. <sect>Copyright<p> 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: <enum> <item> The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. <item> Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. <item> This notice may not be removed or altered from any source distribution. </enum> </article>