Batari Basic Users Guide and Command Reference

Welcome to Batari Basic!  You are using the first basic to assembly language complier for the Atari 2600 game system.  (VCS)  Unlike many other game and computer systems, the VCS is sharply limited in what it can do.  While clever programming and additional hardware can mitigate many limitations, these limitations do have implications on the types of programs you can write. 

Getting started

Before you can use this to make programs for the 2600, you need to understand how things work and obtain some additional software and documentation.  Your basic Batari Basic development kit is composed of:

–the Batari Basic package
–DASM cross assembler
–Atari Hardware Reference Guides
–an emulator to run your compiled programs on.
–this rough introduction.

Resources for the above:

Batari Basic can be downloaded:  http://alienbill.com/2600/basic/

DASM is available at:  http://www.atari2600.org/DASM/

Emulators:  Stella -- http://sourceforge.net/projects/stella/
                    Z26   -- http://www.whimsey.com/z26/

Programming Guides:   http://stella.sourceforge.net/download/stella.txt
                                      http://www.atariage.com/forums/index.php?showtopic=47479

I'm not going to detail installation issues here as each of these has their own documentation.  Please refer to those documents and adapt for your computing platform as necessary.

You can test your emulator with the sample executable machine language files found on the Semi Official Batari Basic page that lives at:  http://alienbill.com/2600/basic/.

DASM can be tested with the sample assembly programs that come with the package and the basic compiler includes a sample program to compile as well.  

Make sure it all works

Before you attempt any real programming, it's a good idea to verify the tools and your work flow before continuing.  The following instructions are for Linux users and reflect the steps I used to get started:

(Perhaps someone can add win32 and Mac at some point in the future.)

Make a new directory to contain the compiler, download it and unzip it into this directory.  For Linux, Unix, Mac you will need to build the program.  All I had to do was:
make all

and the thing compiled just fine.  For some reason, my compiled executable did not have the execute bit set.  To fix this:

chmod +x 2660bas

That should be all it takes to get your Batari Basic compiler up and running.

Download DASM, and unzip it here as well.  You will end up with a sub-folder full of example files, headers, sample assembly code and executables for many platforms.  Add the appropriate DASM executable to your path, or copy it to this working directory.  (A link works well too!)

Install the Stella 2600 emulator and test it by typing “stella”at the command line.  You should get the help screen showing lots of different options.  

You now have just enough to test things out.

The compiler comes with a sample program that will serve nicely to test your programing tool chain, summarized below.

The compiler takes a text file containing the basic language statements and produces an assembly language file.  Be sure you are using a text editor, not a word processor.  

This file by itself is not enough to assemble into a working 2600 executable binary file.  You need to combine this file, along with a header and footer file together before assembling with DASM.  If successful, DASM will produce a working binary file that can be run with whatever 2600 emulator you have installed.

1.Compile sample.bas

./2600bas<sample.bas>sample.asm

This runs the compiler, feeds it the sample.bas text file on standard in and it outputs the compiled assembly language text file as sample.asm

You should see the following after doing this:

2600 Basic compilation complete.

2.Combine compiled assembly language source (text file) with necessary header and footer.

cat 2600basic.asm sample.asm 2600basicfooter.asm > test.asm

This will output nothing, but you can check to see that test.asm exists and that its size should equal the three files combined.  (2600basic.asm, sample.asm, 2600basicfooter.asm)

3.Assemble your program and produce executable.

./dasm test.asm -f3 -otest.bin(Assuming you copied dasm to your working directory)

You should see the following:

DASM V2.20.09, Macro Assembler (C)1988-2003
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Warning: Unable to open 'vcs.h'
Warning: Unable to open 'macro.h'
Warning: Unable to open '2600basic.h'
Complete.

Ignore the warnings, they are not significant at this stage.

A new file called test.bin should now exist in your working directory.

4.Run completed program with emulator.

Stella test.bin

You should get a new window showing the graphics generated by the sample program.  One of the graphics can be moved with joystick 0 to verify proper emulator configuration.

Done!

Now you are ready to begin writing your own programs using the work flow described to compile and assemble them for execution in the emulator.

Writing programs is done with your favorite text editor.  It's a good idea to save them with the .bas extension, but not required.  If you specify the name of your program correctly on the command line, detailed above, it will be compiled.

Understanding how the display kernel affects your program

The 2600 has no bitmapped display.  Everything is done with the CPU.  In order to make things easier for new programmers, the Batari Basic programming environment makes a few assumptions in order to manage the display and allow your program to run.   These assumptions are:

Two player graphics, AKA Sprites, one color 32 x 11 playfield, and a score display form the display kernel under which your basic program will run.

You can define the shapes of the two sprites and turn the playfield pixels on and off.  It's possible to manipulate the score too, but I have not yet explored that.   Changing colors, detecting hardware collisions (where things overlap), making sounds and processing user input is done through the 2600 hardware registers, or simple basic commands in most cases.

While this seems limited, it does allow for complete games to be made with some creative programming, which is what the 2600 is all about.

It is also possible to compile a game, then edit the assembly language file directly to accomplish things not yet possible with the basic programming language commands alone.  In this way, the Batari Basic compiler can act as a rough prototyping and learning tool for more advanced 2600 programming.  

Different display kernels, or your own custom display kernel may be options in the near future.  For now however, we are going to focus on making use of the kernel that comes with the Batari Basic compiler package.  

Command Reference

This section documents the commands I have used, their syntax and limits.  Other commands are available, but I'm going to stick with the ones I know.  Perhaps others can expand on this guide as more information and development become a reality.

Spaces and line numbers

Right now, each element of a program statement must be separated, from the others, by one and only one white space.  This is likely to change, but that's not the way it is today.  Given the overall simplicity of the statements and their syntax, this is not as difficult as it seems.

Line numbers start each line and tell the compiler the order of program instructions to be compiled.  It's wise to separate commands by at least 10 numbers to allow for easy insertions without having to renumber things.

Here is an example program statement:

47 a = a + 1
This adds 1 to whatever value the variable 'a' currently is, with the line number being 47.
Another, more complex example:
30 COLUP0 = 120 : player0x = x : player0y = y
Multiple commands can be placed on one line, using a colon to separate between them. These will execute from left to right.  The value 120 decimal is written to the player 0 color hardware register, thus defining the color of that player when displayed on the screen.  The next two statements assign the values of x and y to the location variables that control the player screen position.  How this works depends on the kernel.  The location variables are not hardware position registers, but locations in the limited 128 bytes of ram that comes with the 2600 game machine.  The kernel uses these numbers to place the player at the desired screen location for you automatically as if the 2600 did actually have hardware position registers.

Variables and RAM
The 2600 has only a very limited amount of system RAM.  (128 Bytes)  Each basic language variable is an 8 bit unsigned integer number that is stored in one of the available bytes of RAM.  This means each variable can hold a number between 0 and 255 ($00 - $ff).  The playfield graphics are also located in this ram, consuming a total of 40 bytes with each bit being one specific pixel.  There are commands to manipulate pixels for you.  This simulates a coarse bitmap display that covers the usable screen area.  It is a good idea to keep the number of variables you want to use in your program to a minimum or you risk running out of RAM.
Variables are single letters, at the moment, with the compiler taking care of their actual memory locations for you automatically.  

Hardware Registers
These registers are specific locations in the 2600 memory space that are used to communicate with the hardware chips in the 2600.  Many of the basic commands make use of them as part of their function.  You may also refer to them, as demonstrated above, to either set values or read values.  Changing the background color is an example, shown above, of setting a value.  Reading the joystick trigger state would be an example of reading a value.  
In general, the registers you write to, do not return the value written.  This means you need to keep values in variables if you plan to make repeated use of them.  The names of the registers are contained in the vcs.h header file used for assembly.  You can refer to these by their name as shown in the example above.  It would be a good idea to consult the stella programming guide, linked above, for better understanding of what these registers do as not all of their functions have been converted into basic language keywords yet.

Math operators
Since each variable is an 8-bit unsigned integer number, the math you can perform is very limited.  Variables will not overflow, but will wrap around to zero again.  If this is not clear, maybe this example will be:
10 a = 5(Of course, a = 5)
20 a = a + 1(a now = 6)
30 a = a + 255 (a now equals 5 again due to wraparound occuring)
40 a = a + 400 (not wise in that this value exceeds the range permitted, I'm not sure what would happen in this case because the constant 400 is a two byte number being added to a one byte one.)
Subtraction is permitted as well:
50 a = a - 1
Division (by two only)
60 a = a / 2
Multiply (by two only)
70 a = a * 2
Boolean operators are permitted:
80 a = a & 45
Complex expressions are not yet part of the language.  Keep things simple and it will just work.  Eg:
90 a = a + 31 : a = a / 2 : a = a / 2
The above means add 31 to a, then divide a by 2, then do it again to get a divided by 4.
You can't do such things like:
95 a = (( b / 2) + (c * 2)) + 32
, but you probably will someday.
There is more, but this should give you the idea of how math is done.  The reality is that you don't need much to write games and the limited operations map directly to the operators built into the 2600 6502 CPU.

Comparisons
The usual stuff is permitted here, but only for simple if – then constructs.  If you need more complex logic, chain comparisons together with gotos.  Eg:
30 if a > x then 50
40 x = x + 1
50 x = x + 2
These three lines will add 2 to x, if a is greater than x; otherwise add 3.
eg:  if a > x then x = x + 2 else x = x + 3
Again, Batari Basic does not have if then else constructs just yet, I wrote the above to clarify how this is done within the constraints of the compiler.
You can chain statements together to get more than one thing done per comparison however:
40 if a = x then x = x + 5 : b = 50 : goto 60
50 x = x + 3
60 c = 5 : AUDV0 = 0
A zero is considered false and anything else is considered to be true.  You can write:
50 if x then 60
This line takes advantage of a couple shortcuts.  If the variable x holds anything but a zero, program execution will begin at line 60.  No equals sign and no goto keyword is necessary for this to all work.  

Code limits
The 2600 has a limited 4K ROM space for your program instructions.  Bank switching schemes have greatly extended this, but Batari basic is a 4K environment for now.  Do as much as you can with as few statements and variables as possible to keep things within the 4K ROM and 128 Byte RAM limits.
If you exceed 4K of program instruction size, you will get a compile error.
On the topic of code size, you must understand the basic statements are being converted into assembly language.  This is where the 4Kbyte limit comes into play.  Using short cut statements, like the last comparison example shown above, does nothing to reduce final code size because the assembly language generated would be the same, shortcut or not.  

Program structure and flow
Your program can be broken into 4 distinct parts because of how the display must be drawn each video frame.  For NTSC systems, one frame is drawn 60 times per second.  This will be reflected as a loop in your program.  Before this loop is init code. The loop itself can be broken down into two parts.  Drawing the display and performing game logic.  The two parts are separated by the drawscreen command.  After the loop comes special subroutines to be executed as needed during the vertical blank time, if needed thus:
05 rem init to happen once on start or reset (goto 5)
10 x = 0 : y = 5 : COLBK = 30
20 pfhline 2 3 20 

30 rem display loop (Happens every frame)
40 player0x = x : player0y = y : l = l - 1
45 player0:
%01000010
%11111111
%11111111
%00000000
end
46 player1:
%00011000
%00111100
%01111110
%00111100
%00011000
end
90 drawscreen
91 rem This ends the display section and a frame has been drawn ?
92 rem entering VBI period where you have a fair number of cycles to do game logic.  Anything below the drawscreen command will be executed once a full video frame has been displayed.  

170 rem game logic, move player positions, check collisions, etc...
180 if joy0left then x = x - 1
190 if joy0right then x = x + 1
200 if something then goto 400 
210 do something else
230 goto 30
231 rem without this goto and the one on line 420, your game does nothing but display 1 frame and crash.

400 rem subroutine
410 COLBK = 5
420 goto 230
Lines 5-20 are init code.  They only happen once when the whole things starts running.  Set your initial variable values here.  Timing is not critical here.
Lines 30 – 90 are executed while the screen display is being drawn.  The actual mechanics are more complex than that, but keep commands to a minimum here because the available CPU time must be shared between on-screen graphics and your program commands.
Lines 170 to 231 are game logic code.  You have plenty of time, but not too much time before the screen must be drawn again.  Do what you need to, but be aware of wasteful codes.  This is where the bulk of your calculations and comparisons will occur.
Lines 400 – 420 represent a subroutine that will execute after the drawscreen command.  Subroutines are good for tasks that only need to be done when a condition is met.  There is no requirement they be placed in the highest number space, but it does make things easier to understand later.
To summarize:  Program flow looks like this:
init 
draw the screen
perform logic
loop back to draw screen again.
If this remains confusing, read the introductory material found in the Atari Age newbie programming forum.  If you forget everything you just read, remember your program needs to be a loop.  If it's not, nothing is going to happen on the 2600.

Command syntax and limits
let{variable} = {constant} or {variable}
Assigns value to RAM variable.  Limit of 8 bits. (0 – 255)  Optional really, one could just use a = 5, for example.  Eg:
10 let a = 5

{hardware register} = {variable} or {constant}
Writes value to hardware register.  Eg:
410 COLBK = 5

If{expression is true} then {statements and expressions}
In general, single comparisons are ok, more complext and, or, not, else, etc... not yet implemented.  Eg:
30 if a > x then 50

Player sprite definition table as shown below:
45 player0:
%01000010
%11111111
%11111111
%00000000
end
No spaces, other than the one between the line number and the player0 command are allowed.  Players can be any practical length.  Right now, player0 and player1 are implemented.  I'm not totally sure where these should be placed.  Both the example program and my breakout clone put them in the display section of the code.  Given the limited indexing capability of the CPU, maybe this is a good idea.  Feel free to futz around with this (like putting it in with other init code).  If your program fails, follow the examples.

Player0x = {value or variable}
Assigns the value to the player position so that it may be drawn at the desired screen position.  Player0x, player0y, player1x, player1y are implemented.  Eg:
20 player0x = a

Scorecolor = {value or variable}
Sets the color of the on-screen score display.  Eg:
30 scorecolor = 50

Pfvline {x} {y} {length} {on, off, flip}
Draws vertical line, using playfield graphics.  Pfhline also implemented for horizontal lines.  Eg:
30 pfvline 5 4 4 on

Pfpixel {x} {y} {off, on, flip}
Controls playfield graphics pixel at specified location.  Eg:
112 pfpixel j 3 off
66 pfhline 0 0 31 on

Drawscreen
Sets the display kernel in motion.  This command seperates your display kernel code, from your game logic code, subroutines and init code.  Eg:
100 drawscreen

Goto {value or variable}
Causes program execution to jump to designated line number and continue.  Eg:
30 goto 40 

Predefined variables used for comparisons.  Eg:
joy0left {right, up, down, etc..}
if joy0left then goto 30

rand
Generates 8 bit random number to be assigned to variable.  Eg:
20 a = rand

Send changes, additions, comments to:

Doug Dingus
doug@opengeek.org
07/05
http://www.opengeek.org
This document is licensed under the creative commons license found at www.creativecommons.org.  In plain english, you may do what you like with this work, provided derivative works are licensed the same way and this notice is preserved intact, including original author credits and website along with additional credits that may be appropriate for future works.  Please see the Creative Commons website for more details on how this license works and it's social implications.