2014-02-04 21:18:58 +00:00
|
|
|
<!doctype linuxdoc system>
|
|
|
|
|
|
|
|
<article>
|
|
|
|
|
|
|
|
<title>Atari Lynx specific information for cc65
|
2014-04-08 19:36:39 +00:00
|
|
|
<author>
|
|
|
|
<url url="mailto:karri@sipo.fi" name="Karri Kaksonen">,<newline>
|
|
|
|
<url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
2014-04-14 09:54:13 +00:00
|
|
|
<date>2014-04-12
|
2014-02-04 21:18:58 +00:00
|
|
|
|
|
|
|
<abstract>
|
|
|
|
An overview over the Atari Lynx runtime system as it is implemented for the
|
|
|
|
cc65 C compiler.
|
|
|
|
</abstract>
|
|
|
|
|
|
|
|
<!-- Table of contents -->
|
|
|
|
<toc>
|
|
|
|
|
|
|
|
<!-- Begin the document -->
|
|
|
|
|
|
|
|
<sect>Overview<p>
|
|
|
|
|
|
|
|
This file contains an overview of the Atari 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
|
2014-04-14 09:54:13 +00:00
|
|
|
described in detail in the separate <url url="funcref.html" name="function
|
2014-02-04 21:18:58 +00:00
|
|
|
reference">. Even functions marked as "platform dependent" may be available on
|
|
|
|
more than one platform. Please see the function reference for more
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Building your first Hello World application<p>
|
|
|
|
|
|
|
|
Here is a small traditional Hello World program for the Atari Lynx.
|
|
|
|
|
|
|
|
<tscreen><verb>
|
|
|
|
#include <lynx.h>
|
|
|
|
#include <tgi.h>
|
|
|
|
#include <6502.h>
|
|
|
|
|
|
|
|
void main(void) {
|
|
|
|
tgi_install(tgi_static_stddrv);
|
|
|
|
tgi_init();
|
|
|
|
CLI();
|
|
|
|
while (tgi_busy())
|
|
|
|
;
|
|
|
|
tgi_clear();
|
|
|
|
tgi_setcolor(COLOR_GREEN);
|
|
|
|
tgi_outtextxy(0, 0, "Hello World");
|
|
|
|
tgi_updatedisplay();
|
|
|
|
while (1)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
The lynx.h contains all kind of system dependent things.
|
|
|
|
|
|
|
|
The tgi.h contains the graphics driver functions.
|
|
|
|
|
|
|
|
The 6502.h is needed for executing the CLI() command.
|
|
|
|
|
|
|
|
As the Atari Lynx does not have ASCII characters available you need to use
|
|
|
|
the Tiny Graphics Interface library for producing letters on the screen.
|
|
|
|
|
|
|
|
The cc65 compiler suite has a graphics library called "Tiny Graphics
|
|
|
|
Interface". This interface has some relocatable code. In order to use this
|
|
|
|
in your own program you need to load it at run time.
|
|
|
|
|
|
|
|
Unfortunately the Lynx does not have a disk drive from where to load it.
|
|
|
|
Therefore you must already load it at compile time. The easiest way is to
|
|
|
|
automatically link it in statically from the Lynx C library.
|
|
|
|
|
|
|
|
<tscreen><verb>
|
|
|
|
cl65 -t lynx -o game.lnx main.c
|
|
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
This will create a bootable cart image called game.lnx
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Binary format<p>
|
|
|
|
|
|
|
|
The standard binary output format generated by the linker for the Lynx target
|
|
|
|
is a cart image. By specifying the config file lynx-bll.cfg the linker will
|
|
|
|
generate BLL download compatible binary files.
|
|
|
|
|
|
|
|
It is of course possible to change this behaviour by using a modified startup
|
|
|
|
file and linker config.
|
|
|
|
|
|
|
|
The bootloader used in the cc65 lynx library uses a very minimal bootloader
|
|
|
|
that does not check the cart or show a title screen.
|
|
|
|
|
|
|
|
The advantage of this bootloader is that it allows creation of cart images to
|
|
|
|
many common formats.
|
|
|
|
|
|
|
|
Cart sizes
|
|
|
|
<tscreen><verb>
|
|
|
|
Block size Rom size Description
|
|
|
|
512 bytes 128k Standard old games like Warbirds
|
|
|
|
1024 bytes 256k Most common format for homebrew. Also newer games like Lemmings
|
|
|
|
2048 bytes 512k Largest games like EOTB
|
|
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
<sect>Memory layout<p>
|
|
|
|
|
|
|
|
cc65 generated programs with the default setup run with the I/O area and the
|
|
|
|
kernal enabled, which gives a usable memory range of $200 - $C037.
|
|
|
|
|
|
|
|
Special locations:
|
|
|
|
<tscreen><verb>
|
|
|
|
0000 - 00FF Zero page
|
|
|
|
0100 - 01FF Machine stack
|
|
|
|
|
|
|
|
A058 - C037 Collision buffer
|
|
|
|
C038 - E017 Screen buffer 1
|
|
|
|
E018 - FFF7 Screen buffer 0
|
|
|
|
FFF8 - FFFF Hardware vectors
|
|
|
|
</verb></tscreen>
|
|
|
|
|
|
|
|
<descrip>
|
|
|
|
<tag/Text screen/
|
|
|
|
No conio support is currently available for the Lynx.
|
|
|
|
|
|
|
|
<tag/Keyboard/
|
|
|
|
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.
|
|
|
|
|
|
|
|
<tag/Stack/
|
|
|
|
The C runtime stack is located at $C037 (or $A057 if collision
|
|
|
|
detection is enabled) and growing downwards.
|
|
|
|
|
|
|
|
<tag/Heap/
|
|
|
|
The C heap is located at the end of the program and grows towards the C
|
|
|
|
runtime stack.
|
|
|
|
|
|
|
|
<tag/Screen/
|
|
|
|
The collision detection screen is at $A058 if it is enabled. The
|
|
|
|
double buffered screens are at $C038 and $E018.
|
|
|
|
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Platform specific header files<p>
|
|
|
|
|
|
|
|
Programs containing Lynx specific code may use the <tt/lynx.h/ header file.
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Lynx specific functions<p>
|
|
|
|
|
|
|
|
<itemize>
|
|
|
|
<item>lynx_eeprom_erase
|
|
|
|
<item>lynx_eeprom_read
|
|
|
|
<item>lynx_eeprom_write
|
|
|
|
<item>lynx_eeread
|
|
|
|
<item>lynx_eewrite
|
|
|
|
<item>lynx_exec
|
|
|
|
<item>lynx_load
|
|
|
|
</itemize>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Hardware access<p>
|
|
|
|
|
|
|
|
The following pseudo variables declared in the <tt/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.
|
|
|
|
|
|
|
|
<descrip>
|
|
|
|
|
|
|
|
<tag><tt/MIKEY/</tag>
|
|
|
|
The <tt/MIKEY/ structure allows access to MIKEY chip. See the <tt/_mikey.h/
|
|
|
|
header file located in the include directory for the declaration of the
|
|
|
|
structure.
|
|
|
|
|
|
|
|
<tag><tt/SUZY/</tag>
|
|
|
|
The <tt/SUZY/ structure allows access to SUZY chip. See the <tt/_suzy.h/
|
|
|
|
header file located in the include directory for the declaration of the
|
|
|
|
structure.
|
|
|
|
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Loadable drivers<p>
|
|
|
|
|
|
|
|
The names in the parentheses denote the symbols to be used for static linking of the drivers.
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Graphics drivers<p>
|
|
|
|
|
|
|
|
<descrip>
|
|
|
|
|
2014-02-04 21:51:39 +00:00
|
|
|
<tag><tt/lynx-160-102-16.tgi (lynx_160_102_16_tgi)/</tag>
|
2014-02-04 21:18:58 +00:00
|
|
|
A TGI driver for the standard graphics mode (160×102 in 16 colors).
|
|
|
|
|
|
|
|
The TGI driver is implemented as an interrupt driven 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_sprite(spr) or tgi_ioctl(0, spr) will display a standard Lynx
|
|
|
|
sprite on screen.
|
|
|
|
|
|
|
|
Calling tgi_flip() or tgi_ioctl(1, 0) will do a flip screen.
|
|
|
|
|
|
|
|
Calling tgi_setbgcolor(bgcolor) or 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.
|
|
|
|
|
|
|
|
To set the framerate of the display hardware call tgi_setframerate(rate) or
|
|
|
|
tgi_ioctl(3, rate). The supported framerates are 50, 60 and 75 frames per
|
|
|
|
second. Actually there is no real reason to use anything else than 75 frames
|
|
|
|
per second.
|
|
|
|
|
|
|
|
To check if the drawing engine is busy with the previous swap you can
|
|
|
|
call tgi_busy or tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy
|
|
|
|
|
|
|
|
To update displays you can call tgi_updatedisplay() or tgi_ioctl(4, 1) it
|
|
|
|
will wait for the next VBL interrupt and set the draw buffer to the
|
|
|
|
view buffer. The draw buffer is also changed to (drawbuffer xor 1).
|
|
|
|
|
|
|
|
You can also enable or disable collision detection by a call to
|
|
|
|
tgi_setcollisiondetection(active) or tgi_ioctl(5, active). The collision
|
|
|
|
result is located before the sprite structure by default in this driver.
|
|
|
|
|
|
|
|
In order to reserve memory for the collision detection buffer you need to
|
|
|
|
specify lynx-coll.cfg as the configuration file to the linker.
|
|
|
|
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Extended memory drivers<p>
|
|
|
|
|
|
|
|
No extended memory drivers are currently available for the Lynx.
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Joystick drivers<p>
|
|
|
|
|
|
|
|
<descrip>
|
|
|
|
|
2014-02-04 21:51:39 +00:00
|
|
|
<tag><tt/lynx-stdjoy.joy (lynx_stdjoy_joy)/</tag>
|
2014-02-04 21:18:58 +00:00
|
|
|
A joystick driver for the standard buttons.
|
|
|
|
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>Mouse drivers<p>
|
|
|
|
|
|
|
|
No mouse drivers are currently available for the Lynx.
|
|
|
|
|
|
|
|
|
|
|
|
<sect1>RS232 device drivers<p>
|
|
|
|
|
|
|
|
<descrip>
|
|
|
|
|
2014-02-04 21:51:39 +00:00
|
|
|
<tag><tt/lynx-comlynx.ser (lynx_comlynx_ser)/</tag>
|
2014-02-04 21:18:58 +00:00
|
|
|
A serial driver for the ComLynx port.
|
|
|
|
|
|
|
|
The ComLynx port has Tx and Rx wired together. Every byte is sent
|
|
|
|
to all connected Lynxes. Only one Lynx can send at a time. There is no
|
|
|
|
protocol created for communication. You are on your own.
|
|
|
|
|
|
|
|
If the Lynx returns framing error then it is likely that another Lynx is
|
|
|
|
sending data at the same time.
|
|
|
|
|
|
|
|
The Lynx can also send a break and receive a break. The Lynx break is
|
|
|
|
recognized if the bit is down for 24 bit cycles or more.
|
|
|
|
|
|
|
|
To send a break you just set the break bit. The length of the break depends
|
|
|
|
on how long this bit is down.
|
|
|
|
|
|
|
|
The driver supports the baudrates:
|
|
|
|
<itemize>
|
|
|
|
<item>62500
|
|
|
|
<item>31250
|
|
|
|
<item>9600
|
|
|
|
<item>7200
|
|
|
|
<item>4800
|
|
|
|
<item>3600
|
|
|
|
<item>2400
|
|
|
|
<item>1800
|
|
|
|
<item>1200
|
|
|
|
<item>600
|
|
|
|
<item>300
|
|
|
|
<item>150
|
|
|
|
<item>134.5
|
|
|
|
<item>110
|
|
|
|
<item>75
|
|
|
|
</itemize>
|
|
|
|
The parity bit supports MARK and SPACE. It also supports EVEN and ODD parity
|
|
|
|
but the parity bit is included in the calculation. Most of us don't want it
|
|
|
|
this way. But there is nothing we can do about it.
|
|
|
|
|
|
|
|
The Lynx hardware will always check parity on incoming traffic. Currently
|
|
|
|
the driver cannot receive data from standard PC's due to this parity bug.
|
|
|
|
For working with Lynx to Lynx communication use EVEN parity.
|
|
|
|
|
|
|
|
To send data to standard PC's use MARK or SPACE as parity setting.
|
|
|
|
|
|
|
|
There is always only one stop bit. And the data length is always 8 bits.
|
|
|
|
|
|
|
|
We have no handshaking available. Even software handshake is impossible
|
|
|
|
as ComLynx has only one wire for the data.
|
|
|
|
|
|
|
|
Both transmit and receive are interrupt driven.
|
|
|
|
|
|
|
|
</descrip><p>
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Limitations<p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<sect>Cart access<p>
|
|
|
|
|
|
|
|
At this point in time there is no support for the cart filesystem yet. I have
|
|
|
|
a <tt/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 <tt/lynx-cart-demo/.
|
|
|
|
|
|
|
|
|
|
|
|
<sect>License<p>
|
|
|
|
|
|
|
|
This software is provided 'as-is', without any expressed or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
<enum>
|
|
|
|
<item> The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
<item> Altered source versions must be plainly marked as such, and must not
|
|
|
|
be misrepresented as being the original software.
|
|
|
|
<item> This notice may not be removed or altered from any source
|
|
|
|
distribution.
|
|
|
|
</enum>
|
|
|
|
|
|
|
|
</article>
|