Programming tutorial: Part 3–Analyzing Hello World

Atari Lynx programming tutorial series:

In the previous two parts you have learned what is involved for writing a Lynx game and how to setup your development environment. This part focuses on the Hello World application using the CC65 suite.

If you haven’t done so, download the Hello World project archive. Open the game.c file in your editor.

The big assumption on my part is that you are familiar with the C programming language. Check out these tutorials if you are not.

The main function

Every C program has a main entry point that gets executed when the program starts. The programs written using CC65 are no exception. The entry point is the main function and it usually takes no arguments and returns nothing.

void main(void)  {	
  initialize();
 
  while (1)
  {
    if (!tgi_busy())
    {
      show_screen();
    }
  };
}

There are three important things in this function:

  1. The initialize function that performs the necessary initialization.
  2. An infinite loop where we remain forever. This is the while loop.
  3. Logic inside the infinite loop for rendering the screen.

Initializing the Lynx

The initialize function is not necessary by itself. The piece of logic for initialization can be inside the main loop. I tend to put these kinds of logic in separate functions to keep it all together and to show its purpose.

void initialize()
{
  tgi_install(&lynxtgi);
  tgi_init();
  CLI();
	
  while (tgi_busy())  {  };
 
  tgi_setpalette(tgi_getdefpalette());
  tgi_setcolor(COLOR_WHITE);
  tgi_setbgcolor(COLOR_BLACK);
tgi_clear(); }

In this function a little more goes on. Running this from the top, the first two lines are about installing a driver for the Tiny Graphics Interface (TGI). The TGI library is a cross-system graphics engine, that allows for 2D graphics primitives like drawing and text output.

Each system (e.g. C65, Apple2, Lynx) has its own implementation for the TGI library. The core is system-agnostic, but the actual implementation is separated out and provided as a linkable file. The Lynx file is called lynx-160-102-16.tgi and is part of the Lynx specific CC65 files that you downloaded in part 2. We will get back to this file and how it is included in a later part. For now suffice to say that we need to call tgi_install and pass it a pointer to an externally declared byte array:

extern char lynxtgi[]; 

After loading this array will contain a string “tgi” that indicates that the loading of the driver was successful.

The tgi_init function performs the initialization of the loaded drivers of which the TGI graphics driver is just one. There are two additional drivers (joystick and comlynx) that you can load as well. For a simple program such as this these two are not necessary.

The next call is to CLI and it represents the CLI assembly instruction for the 65SC02 processor. The function call allows you to clear the Interrupt Disable flag of the processor, so interrupts get serviced.

// enable Mikeys interrupt response
#define
CLI asm("\tcli")

The definition of CLI is inside the 6502.h header file. It is included at the top of the game.c file with some other headers:

#include <6502.h>
#include <lynx.h>
#include <tgi.h>

I am pretty sure these three header includes make sense to you. They are related to the processor family, the Lynx and the TGI libraries.

The while loop checks whether TGI is still busy and waits until it is done.

The last four calls set the palette to the default palette, and the color for the front and back color of fonts. Setting the colors to white and black means text will be white on a black background (where the text is output). Since the screen will also be black it simply means that you have white text on a black screen. The final tgi_clear call will clear the screen for you with the zeroth color in the palette. Because we loaded the default palette, the first color in the palette is black and the screen will be made black.

That’s it for initializing the Lynx. There is a lot more going on than we can see now. For example, when the code gets compiled, it will have a boot header included that does some initialization as well. There is no need to go into that right now. Simply relax and have it taken care of for you.

Rendering the screen

Inside the main infinite loop we keep calling the show_screen function. This means that we are continuously drawing the screen. For a real game there is a lot more to be done inside the loop, like reading the controls, updating the administration, playfield and the sprites.

void show_screen()
{
  tgi_clear();
	
  tgi_setcolor(COLOR_WHITE);
  tgi_outtextxy(30, 48, "Hello, World!");
 
  tgi_updatedisplay();
}

What you see is that a rendering of the screen starts with clearing the screen. At some point this could be optimized whenever you know that you do not need to wipe the screen and render just a small part of it again. Until there is a special purpose for doing so, I would stick with simply clearing the screen and redrawing all.

The next two lines set the color for text (again, just like inside the initialization function) and output some text at a specific x and y coordinate. Setting the color before working with text makes sure that you are rendering text in that exact color and do not rely on assumed color state. The text is rendered at the (x,y) coordinates of (30, 48) where x is across from 0 (left) to 160 (right) and y is from 0 (top) to 102 (bottom).

Finally, the display is updated. The tgi_updatedisplay function is a Lynx-only tgi function that is a convenience wrapper around an underlying tgi_ioctl function. In this particular case updating the display means that “it will wait for the next VBL interrupt and swap draw and view buffers.” (from the lynx-160-102-16.s source code). That is an exciting way to describe that the code will wait for an interrupt for the vertical blank (set up by the tgi_install of the TGI graphics library) that occurs at the bottom of a screen rendering. At that point the double buffers are swapped around, so the view buffer becomes the draw buffer and vice versa.

The final result

When all this code is compiled it gives you a game.lnx rom image that you can execute directly in an emulator that support this Handy image format. Handy or Mednafen will do just fine (see part 1).

In case you do not have your development environment with you, this is what the end result looks like:

image

Next time

In the next part we will take a look at how the game is compiled and what the make files are all about. Stay tuned once more.

Advertisements
This entry was posted in Tutorial. Bookmark the permalink.

8 Responses to Programming tutorial: Part 3–Analyzing Hello World

  1. Pingback: Programming tutorial: Part 4–Creating a project | Diary of an Atari Lynx developer

  2. Pingback: Programming tutorial: Part 5–Exploring TGI | Diary of an Atari Lynx developer

  3. Pingback: Programming tutorial: Part 6–Colors | Diary of an Atari Lynx developer

  4. Pingback: Programming tutorial: Part 7–The basics of sprites | Diary of an Atari Lynx developer

  5. Pingback: Programming tutorial: Part 8–Changing appearances | Diary of an Atari Lynx developer

  6. Pingback: Programming tutorial: Part 9–Advanced sprites | Diary of an Atari Lynx developer

  7. Pingback: Programming tutorial: Part 10–Collisions | Diary of an Atari Lynx developer

  8. Pingback: Programming tutorial: Part 11–Pens and more collisions | Diary of an Atari Lynx developer

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s