Jump to content

Atari Lynx programming tutorial


Recommended Posts

Goodmorning all and thanks for the help so far!

I set the environment variables several times. Installed CC65 in c:\Program Files\CC65 and when that didn't work in c:\CC65, modified the variables and path references. Even edited Microsoft.Cpp.Win32.user.props.
Triple-checked the .mak files...
And I rebooted so often my pc told me to make up my mind ;)

Edited by toyamigo
Link to comment
Share on other sites

Deleted the Lib from the VC directory in RegEdit, repaired/reinstalled Visual Studio, moved the CC65 dir to my K-drive (in case CC65 doesn't like SD cards), rebooted, modified environment variables, paths, in Visual Studio modified the project-properties...still no luck...

When I right-click #include <6502.h> and choose "open document", it opens.
In my HelloWorld.log:

copy "K:\CC65"\include\..\tgi\lynx-160-102-16.tgi .
1 file(s) copied.
copy "K:\CC65"\include\..\joy\lynx-stdjoy.joy .
1 file(s) copied.
So my CC65\include directory is working except for "#including" when compiling.

It still says:

1>tutorial.c(1): error : Include file `6502.h' not found
1>tutorial.c(2): error : Include file `lynx.h' not found
1>tutorial.c(3): error : Include file `tgi.h' not found
Glad I'm already crazy, this should make me crazy for sure :o
Link to comment
Share on other sites

It's definitely no problem in Visual Studio.
Tried it in DOS with a little program.

First part of my path:
C:\Users\Tony\Documents\Hello>cl65 -t lynx -o game.lnx main.c
main.c(1): Error: Include file `lynx.h' not found
main.c(2): Error: Include file `tgi.h' not found
main.c(3): Error: Include file `6502.h' not found
main.c(12): Fatal: Too many errors
Any suggestions left?
Link to comment
Share on other sites


My environment variables were:

  • CA65_INC: C:\Program Files\CC65\asminc
  • CC65_INC: C:\Program Files\CC65\include
  • CC65_HOME: C:\Program Files\CC65
  • LD65_CFG: C:\Program Files\CC65\cfg
  • LD65_LIB: C:\Program Files\CC65\lib
  • LD65_OBJ: C:\Program Files\CC65\obj

They SHOULD be:

  • CA65_INC C:\Program Files\CC65\asminc
  • CC65_INC C:\Program Files\CC65\include
  • CC65_HOME C:\Program Files\CC65
  • LD65_CFG C:\Program Files\CC65\cfg
  • LD65_LIB C:\Program Files\CC65\lib
  • LD65_OBJ C:\Program Files\CC65\obj

I knew it was a stupid little thing like this...it just takes 2 days before you find it ;)
Finally ready to rumble...again...
Thanks everybody for the help!


Link to comment
Share on other sites

Subtle: Took me a while to spot. I will definitely spend some time improving all of the getting started in the tutorial. Also, I am looking into adopting the latest CC65 version. It says it doesn't need the env variables anymore and I found that to be true. Only problem I ran into was that using a directory and an encrypted header other than the microloader gave me problems. Something for a different thread.

Link to comment
Share on other sites

Madness isn't it? Glad I got it solved..
Also curious bout the latest CC65. I think I tried that as well but since it didn't worked either I got back to the default one on your tutorial. Guess now I can try Visual Studio 2015 and the new CC65 again :)
Good luck & thanks!

Link to comment
Share on other sites

Thanks to everyone's invaluable help my first Lynx prototype is running on real hardware via Lynxman's awesome flash card! I was scared it was going to run terribly since I had only played it in the emulator and it didn't feel particularly great, but I was pleasantly surprised to find that it's running super smooth on the real thing. Hopefully in the next few weeks I will have something worthy of presenting for feedback. I still need to finish some gameplay programming then onto UI stuff, and of course real graphics and sound. Thanks again guys!


now on hardware

Link to comment
Share on other sites

Gz on the progress pixelperfect! :)


I have a couple of questions if someone kindly could push me in the right direction. Any help appreciated.


I was tinkering/"haxxing" away on shaken and pegsolitaire last night trying to get a hang of the tools again, and those two compile fine on my raspi but I was wondering if anyone knows how to compile the tutorial examples from this tutorial on the raspberry pi? I know it's pretty basic stuff but I got a bit confused. For example if I just want to compile the hello world tutorial, can I alter the mak files a little bit and turn them into linux make files? The examples here seem to have been taken down :( http://atariage.com/forums/topic/174250-cc65-c-compiler-can-now-create-carts-directly/


Or might there even be available a reasonably up to date empty game-creation template like in ye olden days? Shaken is a bit big as first come-back-attempt to sink my teeth in. Peg solitaire was very small and pretty easy to understand, but that one is already a few years old so I was thinking maybe a lot has changed since then?

Link to comment
Share on other sites

After some thought I think it would be wise for me to create makefile files for the projects, so it can be built with make.exe instead of nmake.exe from Visual Studio. It will also allow you to use other code editors and cross-platform.

Right now you will not be able to compile the tutorial samples on Linux, as you need nmake.exe that uses a different makefile format.

Link to comment
Share on other sites

That would obviously be very nice of you! That would hopefully help some more people getting into Lynx programming as the compiler seemed to be easier to get up and running on raspberry pi than on windows (and I had never used linux before).


I've been staring at lynx make files for years so I should really be able to put something together myself too. At the moment I'm trying to get the PegSolitaire intro makefile to create .o files from .pcx with sp65 instead from .bmp with sprpck but haven't quite succeeded yet.

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

  • 2 months later...


thanks for your tutorial. I've made my first Hello World on my Lynx.


I have a problem with the Sprite tutorial.I use the command line mode for Windows. And I certainly forgot an Include or something else as you see with error message.

main.c(22): Error: Undefined symbol: `BPP_4'
main.c(22): Error: Undefined symbol: `TYPE_NORMAL'
main.c(22): Error: Constant expression expected
main.c(23): Error: Undefined symbol: `REUSEPAL'
main.c(23): Error: Constant expression expected
main.c(25): Error: Incompatible pointer types
main.c(27): Error: Non constant initializers

I added a picture robot.bmp, I used sprock and I added the file robot.s

.global _robot
.segment "RODATA"

.incbin "robot.spr"

The main source

#include <6502.h>
#include <lynx.h>
#include <tgi.h>
#include <stdlib.h>
extern char lynxtgi[];

typedef struct SCB_RENONE {
  unsigned char sprctl0;
  unsigned char sprctl1;
  unsigned char sprcoll;
  char *next;
  unsigned char *data;
  signed int hpos;
  signed int vpos; 

extern unsigned char robot[];

SCB_RENONE robotsprite =  {
  REUSEPAL, 0x01,
  20, 50
void show_screen()
	tgi_outtextxy(0, 0, "Sprite basics");
	//while (tgi_busy());
void initialize()
  while (tgi_busy());
  tgi_setbgcolor(COLOR_BLACK);  tgi_setpalette(tgi_getdefpalette());
void main(void)  {	
  while (1)
    if (!tgi_busy())

And my make batch file :

@rem The variable CC65_HOME should point to the cc65 directory
@set CC65_HOME=c:\cc65


@REM Clean
@del *.lnx

@REM Images
sprpck -t6 -p2 -a000000 robot.bmp

@REM Compile
ca65 -t lynx robot.s
cc65 --code-name CODE --rodata-name RODATA --bss-name BSS --data-name DATA -t lynx main.c
ca65 -t lynx main.s
cl65 -t lynx -o game.lnx robot.o main.o %CC65_HOME%\lib\lynx-160-102-16.o lynx.lib
Link to comment
Share on other sites

#define BPP_4		    0xC0
#define TYPE_NORMAL	  0x04

I've found the define for bpp_4 and TYPE_NORMAL but not for REUSEPAL.


Where can I find this value, some doc ?


I also change the the value &robot by robot for the pointer error.



!!! Ok, I finally found the include missing after searching into cc65 sources.


#include <_suzy.h>
Edited by tonma
Link to comment
Share on other sites

Now, problem with the sprite importer and image format.


I use sprpck with a 4 bit bmp picture (16 colors). I have take a sprite from rygar on colecovision.

sprpck -t6 -p2 -v rygar.bmp

the information in making file :

Lynx Sprite Packer Ver 1.98
(c) 1997,1998 42Bastian Schick
              Matthias  Domin
Read: rygar.bmp
BMP recognized!
Bitmap file header:
filesize: 2234
offset to pixels: 186
Bitmap info header:
linesize in pixels: 108
Width in pixels: 64
Height in pixels: 64
Planes: 1
BitCount: 4
Compression: 0 (0 = BI_RGB, 1 = BI_RLE8, 2 = BI_RLE4)
SizeImage: 2048
XPelsPerMeter: 2834
YPelsPerMeter: 2834
ColorsUsed: 16
ColorsImportant: 16
BMP-size : w = 64 h = 64 (1 planes)
org_w 64, pad 0
Tile nr: 1
rygar.pal written.
Written: rygar.spr

And the .pal file :

redir:	dc.b $01,$23,$45,$67,$89,$AB,$CD,$EF
pal:	DP 445,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000

Only 2 colors, while I should have 3. I certainly made a mistake again in converting picture.


import image bmp 4bits



Result on emulator :


Link to comment
Share on other sites

You could check the palette of your sprite in the sprite definition of your program, white and blue on the sprite might both be "pointing" at pink in the palette since the Lynx uses indexed colours. In my experience there's often some manual fiddling to get the sprites colours to point at the correct colors on the palette. It's like the image conversion tools don't put the color indexes in order, or maybe I've just misunderstood how to use them properly.

Link to comment
Share on other sites

Thanks, I'll look at this.


Ok, so I make my palette with 4 colors :

static int palette[] =  {
  0x0000, 0x0007, 0x0070, 0x0700,	//black, Red, Blue, Green
  0x000F, 0x000F, 0x0F00, 0x0F00,
  0x0F00, 0x0F00, 0x000F, 0x000F, 
  0x0F00, 0x0F00, 0x000F, 0x0F00

And when I draw my sprite, I specify the number of the palette for every color of my sprite.

SCB_REHV_PAL robot_with_palette = 
  10, 20, 0x0100, 0x0100,
  { 0x03,0x21,0x45,0xF6,0xF6,0xF6,0xF6,0xF6 }

0x03 => color 0 = palette 0

Color 1 = palette 3


0x21 => color 2 = palette 2

color 3 = palette 1

Edited by tonma
Link to comment
Share on other sites

I'm not completely familiar with the four digit palette version but I have a theory, I think all the sixes in the sprite palette is pointing to pink:


the sixth color in your palette shows 0x000F which in GBR is 0F00 which is pink. If you check LX.NET's answer here:




Also, don't forget that the RGB values must be written as GBR in the pallette bytes. So, you have to swap the nibbles of 038D to 08D3 for them to show up as blue instead of pink.




So I'd try to switch the sprite palette to:


Then you can sort out the correct colors from there.


One other hint about using the Lynx's palette is to change out color zero for something else than black, because black is pretty much always needed, but using pen zero turns black invisible in transparent sprites, so better have some less used color there in my opinion.


Don't give up, you'll figure it out eventually! :) I have to re-learn the damn thing everytime I start something new on the Lynx.

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

The BPP is a bit confusing as it means Bits per pixel.


BPP_1 = 2 colours

BPP_2 = 4 colours

BPP_3 = 8 colours

BPP_4 = 16 colours


So you need to define the sprite with BPP_2 if using 4 colours.

SCB_REHV_PAL robot_with_palette = 
10, 20, 0x0100, 0x0100,
{ 0x03,0x21 }

Edit: Sorry, I did not read the original post. The sprpck produces erroneous palettes sometimes like the one in your .pal file. There is not really any good way to map colours from the bmp to the spr structure automatically.

The way I use it is to define the Lynx palette in Gimp with the correct order and create the graphics from the start with the pens in the same order as in the Lynx palette.

Edited by karri
Link to comment
Share on other sites

I have a question. We have less than 64 kB of memory (ram) but we have direct access to the game cartridge to load the sprites as desired.


I'm trying to make a game with a lot of different screen. I use arrays for displaying sprites for the background.

Can I directly read the level arrays on the cartridge? Or do I have to put everything in ram from the beginning?



Link to comment
Share on other sites

You have to put everything in RAM from the beginning. The very low amount of RAM is a real pain.


I have solved this by making tiles that are a bit larger than the screen.


The screen is 160 pixels wide. If I split it in four 54x102 pixel tiles my background becomes 220 pixels wide. When I move more than 2 pixels left or right I can read in the next 54 pixel wide tile to left or right.


To use different sprites for the same place you can use segments. You could allocate buffers to keep your 4 tiles of 54 pixels to buffers A, B, C, D. With a little logic you can always pre-allocate certain sprites to certain positions in RAM to make a smooth scroll.


There is another topic where I have an image from Pandaria being scrolled on a Lynx using this technique. http://atariage.com/forums/topic/256680-what-tool-for-choosing-12-bit-colours-that-work-on-the-lynx/?p=3587013

Link to comment
Share on other sites

Yes. 64ko ram, it's low.


I have expressed myself badly but the problem is the same. I wish to make screen/room without scrolling.

With other consoles, I use static array to leave them in rom.


So I wish to load all sprite of the players, tiles for all screen and load an integer array for the screen map. So I only want to load the array of integer for a screen when I enter a new screen. I hoped we could load it as a file.



So, I obligatory use the segment like this tuto :





I make a first segment for level 1 (player, monster and 10 static rooms)

And I make an another segment for level 2 ...


I need to understand how segment works.


From your links you explain for the 360° viewer, "When you turn you can load in a new tile over the discarded tile that is not needed anymore", so I can load directly in game in the right segment. How can I see the segment size value and position, with a parameter in the makefile?



I have found your link : http://atariage.com/forums/topic/207105-pong-with-segments/ . I think it's what I'm searching.

Edited by tonma
Link to comment
Share on other sites

My version is at https://bitbucket.org/atarilynx/lynx


There is a readme that tries to describe setting it up. The Windows binaries at the beginning of the tutorial should also work. But it is years since I used Windows so I have not tried them out.


I know that this works for Ubuntu and Raspbian.

sudo apt-get install git checkinstall mednafen

The installation is basically

git clone https://bitbucket.org/atarilynx/lynx.git
cd lynx/tools
sudo make -f Makefile.deb

For compiling pong3 you do

cd pong3
make clean

The "make clean" is just to clean up my compilation as I forgot to do it before I uploaded the code.


The image itself is in pong3/cart/pong.lnx

The game itself is crap as it never stops. The collision detection also lets the ball escape the playing field. As well as the opponents paddle. So you are bound to lose. Obviously I only wrote this and never playtested it :(


Edit: the problem with pong2 was that at that time Chipper was included in the compiler libraries. Due to some problems we stepped back in time to a place where chipper was not yet in the compiler. So I added chipper sources to pong3 so it compiles (lynx-snd == chipper).

Edited by karri
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...