Useful
Inventions
Favorite
Quotes
Game
Design
Atari
Memories
Personal
Pages

batari Basic Commands

By Fred "batari" Quimby (adapted by Duane Alan Hahn)

 

Useful Page Links

Page last updated on: 2015y_08m_22d_0116t

 

 

 

What is batari Basic?

The amazing batari Basic (bB) is a BASIC-like language for creating Atari 2600 games. The original beta version was released in 2005. Version 1.0 was released in 2007.

 

The average person who wants to make an Atari 2600 game no longer has to spend years trying to figure out assembly language thanks to batari Basic. And people who can grasp BASIC, but have learning disabilities that keep them from understanding things like assembly language can finally make Atari 2600 games too. [Note from Random Terrain: I have Asperger's Syndrome, memory problems, and learning disabilities, but I managed to make an Atari 2600 game (with a lot of help), so there's a good chance that you can too.]

 

 

 

Read the Getting Started Section

If you are new to batari Basic or you've been using the Tinkernut installer, be sure to read the Getting Started section.

 

 

Table of Contents, Index, and Frequently Used Links

This page has a table of contents, an index and frequently used page links to help you find what you are looking for as quickly as possible. Below the frequently used page links are various helpful sections. Be sure to at least glance over them.

 

[Note from RT: Since I started working on this page, I've been trying to make the index less like a boring index from a book and more like a reverse dictionary mixed with an index. Anything you can think of should be in the list and if it isn't there, you need to tell me so I can add it to the index. As the index grows, it will become quicker and easier for you and others to find things.]

 

 

Link Colors and Info Hover Boxes

Links that jump to other places on this page are blue. Links that lead to other pages online are red. Whenever you see a word or phrase on this page that is underlined with dashes or dots (tooltip/infotip/hint), you can hover your mouse pointer over it and a definition or explanation of some kind will pop up in a hover box.

 

 

 

The Magical Red Rectangle

Inside Game Loop

If you see a red rectangle with the words "Inside Game Loop" in it, that means the variable or register it is near needs to be inside of your main loop because it will be reset after drawscreen is used. See Ephemeral Variables & Registers for more information.

 

 

 

About This Page

Probably over 90 percent of the text on this page was written by batari. Some text is from AtariAge members such as SeaGtGruff, RevEng, and Robert M. Random Terrain only maintains this page: adapts existing text, adds a bit of new text when needed, and corrects errors when they are pointed out. Random Terrain also adds example programs, interactive charts and other goofy stuff.

 

 

 

 

 

Getting Started

Click here and download the latest version of batari Basic. It includes the DPC+ kernel, bug fixes, and various improvements. STOP! Did you download the latest version of bB? If you don't download the latest version, you could have various problems when you try to compile a program. Remember to unzip the folder and put it where you want it. Be sure to check out the install_win.bat subsection below. It's important.

 

Remember, if you are using Visual batari Basic (VbB), it isn't a separate language and batari Basic isn't built into it. VbB is an IDEIntegrated Development Environment
(Just about everything a bB programmer needs in one place.)
; a tool that makes batari Basic easier to use.

 

 

 

Use Save As

Every time I make a significant change to a program I'm working on, I use Save As to save it as a new file so I can go back to a previous working version if I mess something up. If you use Save As before making any major changes, then something stops working correctly, you can use a program like WinMerge to compare the latest two versions of your program and the differences will be highlighted.

 

To make things much easier, I end my program names with the year, month, day and military time. Here's an example:

 

space_monkey_2015y_06m_15d_0132t

 

Doing that means each file will automatically have a different name and the files will be listed in the order they were created. You can read more about it at AtariAge. Also remember that your hard drive will probably die one day, so be sure to make backups of your files using an external hard drive or thumb drive or something else that humans have invented for storing data.

 

 

 

Make bB More Fun with Visual batari Basic

If you are able to run Windows software, you'll probably also want to download Visual batari Basic (VbB). You can read more about it in the next section below which is called IDE for batari Basic. In case it's not clear, VbB isn't a separate language, it's an IDEIntegrated Development Environment
(Just about everything a bB programmer needs in one place.)
; a tool that makes batari Basic easier to use.

 

 

 

install_win.bat

Double click on the file "install_win.bat" that is in the latest batari Basic folder that you have downloaded and unzipped. It will set bB's path and environment variable for you. If you don't do this, you'll still be using the previous version of bB. Selecting the latest version of 2600basic.exe on the VbB settings page doesn't automatically mean that you'll be using that latest version. You must also double click on "install_win.bat" because that's what makes it go.

 

 

 

Don't Use the Tinkernut Installer

If you downloaded batari Basic from any other source, such as the horribly outdated Tinkernut, get the version linked to above. And please do not use the original Tinkernut World batari Basic program. Please use Tinkernut World Deluxe instead. Again, do not use the Tinkernut installer. It is out-of-date. Click the link below instead and do what it says:

How to 'Install' Visual batari Basic on a Windows PC

 

 

Atari 2600 Emulator

If you don't already have the latest version of Stella installed, download it and install it (Stella is the most popular Atari 2600 emulator). Stella isn't a substitute for testing your games on a real Atari 2600 using the Harmony cart, but it's great for quick and dirty testing.

 

You might also want to check out JAVATARI. It's a very good emulator and it can also be embedded on your own web site so people can play the games you make online (if you like the idea of people playing your games online).

 

 

If you need more help, check out the batari Basic forum at AtariAge.

Back to Top

 

 

 

 

 

IDE for batari Basic

Visual batari Basic (VbB) is an IDEIntegrated Development Environment
(Just about everything a bB programmer needs in one place.)
that makes it easier to create bB games. VbB is not the same as Crimison Editor. Besides the Code Editor, VbB has a Sprite Editor, a Playfield Editor, a Score Editor, a Music and Sound Editor, a Sprite Animator, a Title Screen Kernel Editor, and a lot more.

 

Visit the Visual batari Basic Guide for more information. Especially check out this section:

How to 'Install' Visual batari Basic on a Windows PC

Back to Top

 

 

 

 

Useful AtariAge Links

Official batari Basic Forum at AtariAge

Posting Tips for New bB Users

How to Attach Files and Images

Easy Software Versioning

Keeping Track of the Scanline Count with Stella

Back to Top

 

 

 

 

 

Download the Manual

Download the ZIP file below once in a while to be sure you'll always have the latest version of the official offline HTML manual. The ZIP file includes the HTML manual and a folder that contains files the manual needs. The Zip file is usually updated about once a month. Right click on the link below and select Save Link As or Save Target As to download the ZIP file:

Right click here to download the latest version of the official manual and updated folder containing images and example programs

Back to Top

 

 

 

 

 

Test Your Games on a Real Atari

If you'd like to test your games on a real Atari 2600, the Harmony Cartridge by batari is one of the easiest ways to do that. You don't have to plug or unplug anything. Just leave the Harmony CartridgeHarmony Cartridge
Harmony Cartridge
plugged into your console and the USB cable plugged into the cart, then download your work in progress for testing any time you want. It's as hassle-free as you can get. The Harmony cartridge also lets you use an SD card. Drop your own games on it or hundreds of your favorite classic Atari 2600 game files. Bankswitch type is auto-detected.

 

The deluxe edition includes a USB to mini-B programming cable and a formatted SD card. If you don't want to go hunting for the correct SD card and cable, the deluxe edition seems like the best choice.

 

Emulators can be great for testing, but among other things, your game colors will be darker and sprites can look surprisingly different on a real Atari. If you're even slightly serious about making Atari 2600 games, you'll want to buy a Harmony Cartridge as soon as possible.

Back to Top

 

 

 

 

 

Sell Your Games

Once your game is tested, polished, and bug-free, be sure to check out the Melody boards at AtariAge. Melody boards are stripped-down Harmony boards that can be distributed on their own dedicated cartridges. As it says at AtariAge, the Melody board "provides several advantages to the typical circuit boards used for new Atari 2600 homebrew games. Most notably, the Melody can be reprogrammed without being removed from the cartridge . . ."

 

You can also have a single Custom Atari 2600 Cartridge made, if that's all you want.

 

 

 

 

 

New to BASIC and Game Making?

This page assumes the user knows at least a little about BASIC in general. If you know very little about BASIC and know almost nothing about designing a game, the following links might be helpful:

 

If you need help, check out the batari Basic forum at AtariAge. The bB users there will not create a game for you, but they will help you in other ways. Before diving in, you might want to read these two posts first:

Back to Top

 

 

 

 

 

Parts of a Program

Text by Random Terrain

I'm just an amateur BASIC programmer, so experts may not agree with everything below, but it still might be helpful to new users who don't have the parts of a game set in their minds. To me, every section of a BASIC program is like a little box or module. Remember, not every game will follow this exact pattern. It's just an outline that can give you guidance if you feel like a plastic bag blowing in the wind.

 

 

 

Program Setup

This is the area where you put things such as kernel options, set commands, romsize, includes, variable aliases using dim, def statements, constants, and so on.

 

 

 

Start/Restart

This is where you make the program jump to when the game is reset and after the game over loop. The volume is muted and object positions are moved off screen. Most variables are cleared and a few variables are left alone so things can be remembered after a game is over (such as the high score and the game over bit). If the game over bit is turned on, the game goes to the main loop setup instead of the title screen setup.

 

 

 

Title Screen Setup

Some colors are set. Some variables are set to certain values so they'll be ready for the title screen loop. If objects are used, they'll need to be set up here. A reset switch/fire button repetition restrainer bit is set to keep one section of the game from contaminating another if the player holds down the reset switch or fire button.

 

 

 

Title Screen Loop

Certain colors may need to be set in the loop. If you are making your own title screen instead of a fancy one using the Titlescreen Kernel by RevEng, you'll need to use drawscreen.

 

If you want the game to play by itself when the player doesn't start the game within a certain amount of time, a counter can be used that will turn on auto play. During auto play, the score should flip between the current score and the high score every 2 seconds.

 

The title screen loop should check the reset switch and the fire button. If either one is pressed, the program should jump the the main loop setup.

 

 

 

Main Loop Setup

Everything for the actual game needs to be set up here, including any variable values, object locations, object shapes, playfield data, and so on. The repetition restrainer bit for the reset switch and the repetition restrainer bit for the fire button must be turned on to keep one section of the game from contaminating another if the player holds down the reset switch or fire button.

 

 

 

Main Loop

This is the engine, or the heart, or the brain of your game. It's the part of the code that makes things go. Your ifthens, collision detection, and other important things go here.

 

 

 

Game Over Setup

The high score is checked, variable values are set, the game over playfield is drawn, the game over bit is turned on, a reset switch/fire button repetition restrainer bit is set to keep one section of the game from contaminating another if the player holds down the reset switch or fire button, and so on.

 

 

 

Game Over Loop

Certain colors may need to be set in the loop. If you are making your own game over screen instead of a fancy one using the Titlescreen Kernel by RevEng, you'll need to use drawscreen.

 

The score flips between the current score and the high score every 2 seconds.

 

The loop ignores fire button and reset switch input for 2 seconds. After that, the loop checks to see if the reset switch or fire button has been pressed. If either is pressed, the program jumps to the start/restart section.

 

 

 

Subroutines

If a significantly large piece of code needs to be used in many places in your program, you'll probably want to use gosub/return to save space. If the code is fairly small, it's usually better to just repeat the code instead of using a subroutine to avoid wasting cycles.

 

 

 

Code Blocks

Large pieces of code that aren't used by more than one area in your program can be placed outside of your main loop and jumped to using goto or ongoto. You can have your block of code jump back to a label that you have placed right after the goto that jumped to that block of code.

 

Jumping to large blocks of code can make your main loop easier for you to handle and it really becomes necessary if your program grows so large that it will have to be spread out over multiple banks.

 

 

 

Data

Regular data should be outside of your main loop. Your code doesn't need to run over regular data statements for them to work. There's no need to jump to them with goto or gosub.

Back to Top

 

 

 

 

 

Basic Questions

Most of the information below is either directly from or adapted from Wikipedia. Some info is from SeaGtGruff and GroovyBee at AtariAge.

 

 

 

How does an Atari 2600 work?

Check this out:

How does an Atari VCS work?

 

 

 

What is a programming language?

A programming language is an artificial language designed to communicate instructions to a computer.

 

 

 

What is BASIC?

BASIC is a high-level programming language that was designed to be easy to use. BASIC is an acronym that stands for "Beginner's All-purpose Symbolic Instruction Code."

 

 

 

What is a program?

A program is a sequence of instructions that tells the Atari 2600 what to do. Without a program, there is no game.

 

 

 

What is a CPU?

CPU stands for "Central Processing Unit." It's the brains of the Atari 2600. The CPU carries out the instructions of a program.

 

 

 

What is a "value"?

In batari Basic, a value is a number within a specific range.

See Glossary: Constants, Variables, and Values for more information.

 

 

 

What is binary?

Binary is a base-2 number system. It's either off or on (zero or one).

 

 

 

What is a bit?

The word bit is a contraction of binary digit. A bit can be thought of as a tiny box that can hold the value of either 0 or 1 (zero or one).

 

 

 

What is a byte?

A byte is most commonly made up of eight bits. It can be thought of as a larger box that can hold a value of 0 through 255.

 

 

 

What is a variable?

The word variable means something that is likely to vary (something that can change). In batari Basic, a variable can be thought of as a box with a name that can hold a value ranging from 0 to 255. The standard bB variable names are the letters of the alphabet: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z.

See Variables and Glossary: Constants, Variables, and Values for more information.

 

 

 

What is an alias?

A variable alias is a more understandable name that you can think up to use in place of a standard variable name. For example, instead of using a = a + 1, you could use _Alien_Shot_Count = _Alien_Shot_Count + 1.

See dim for more information about variable aliases.

 

 

 

What is ROM?

ROM stands for "Read-Only Memory." The ROM in a normal game cartridge contains program instructions and data that cannot be changed by the Atari's CPU. The information in ROM is always there, even when power to the console is switched off.

See Glossary: Memory for more information.

 

 

 

What is RAM?

RAM stands for "Random Access Memory." RAM is used to store data that can change during a game, such as variables, the score, or positions of the objects on the screen. Any values written to RAM are lost when the console's power is switched off.

See Glossary: Memory for more information.

Back to Top

 

 

 

 

 

FAQ

 

 

 

 

 

 

 

  1. They want to do something hard to challenge themselves, so they use assembly language.
  2. They're doing it for school.
  3. They had an Atari 2600 as a kid and always wanted to make their own Atari 2600 games because there's something special and magical about the graphics and sound effects that other consoles don't have.

 

The third type of person will usually want and need every tool, trick, and shortcut they can get. That's why they use batari Basic, Visual batari Basic, and various kernels, minikernels, modules and enhancements.

 

Back to Top

 

 

 

 

 

Keywords, Constants, and Registers

Below is a quick list of keywords, special constants, and registers.

 

asm

AUDC0

AUDC1

AUDF0

AUDF1

AUDV0

AUDV1

ballheight

ballx

bally

bank

callmacro

COLUBK

COLUP0

COLUP1

COLUPF

const

const noscore = 1

const pfres = #

const pfrowheight = #

const pfscore = 1

const scorefade = 1

CTRLPF

currentpaddle

data

dec

def

dim

dpcspritemax (DPC+)

drawscreen

else

end

for

function

gosub

goto

if

include

includesfile

inline

joy0down

joy0fire

joy0left

joy0right

joy0up

joy1down

joy1fire

joy1left

joy1right

joy1up

let

lives

lives:

macro

missile0height

missile1height

missile0x

missile1x

missile0y

missile1y

next

NUSIZ0

NUSIZ1

ongosub

ongoto

PF0

pfclear

pfhline

pfpixel

pfread

pfscore1

pfscore2

pfscorecolor

pfscroll

pfvline

player0color:

player1color:

playerxcolor: (DPC+)

player0:

player1:

player0x

player1x

player0y

player1y

player#height

playfield:

playfieldpos

pop

pull (DPC+)

push (DPC+)

rand

reboot

REFP0

REFP1

rem

return

return otherbank

return thisbank

score

scorecolor

scorecolors: (DPC+)

sdata

set

sread

stack (DPC+)

statusbarcolor

statusbarlength

switchbw

switchleftb

switchreset

switchrightb

switchselect

then

vblank

vblank (DPC+)

 

 

Colors

COLUBK

COLUP0

COLUP1

COLUPF

Sounds

AUDC0

AUDC1

AUDF0

AUDF1

AUDV0

AUDV1

Missiles/Sprites

NUSIZ0

NUSIZ1

Reflect Sprites

REFP0

REFP1

Ball/Playfield

CTRLPF

Playfield Border

PF0

Joysticks

joy0down

joy0fire

joy0left

joy0right

joy0up

joy1down

joy1fire

joy1left

joy1right

joy1up

Switches

switchbw

switchleftb

switchreset

switchrightb

switchselect

 

 

Advanced TIA Registers

 

CXBLPF

CXCLR

CXM0FB

CXM0P

CXM1FB

CXM1P

CXP0FB

CXP1FB

CXPPMM

ENABL

ENAM0

ENAM1

GRP0

GRP1

HMBL

HMCLR

HMM0

HMM1

HMOVE

HMP0

HMP1

INPT0

INPT1

INPT2

INPT3

INPT4

INPT5

INTIM

PF1

PF2

RESBL

RESM0

RESM1

RESMP0

RESMP1

RESP0

RESP1

RSYNC

SWACNT

SWBCNT

SWCHA

SWCHB

T1024T

TIA_BASE_ADDRESS

TIA_BASE_READ_ADDRESS

TIA_BASE_WRITE_ADDRESS

TIM1T

TIM64T

TIM8T

TIMINT

VBLANK

VDELBL

VDELP0

VDELP1

VERSION_VCS

VSYNC

WSYNC

 

Back to Top

 

 

 

 

 

Quick Reference

Text by kisrael (adapted by Random Terrain)

 

General Core

const set constant

dim/def extra name for variable (or var. expression)

ifthenelse conditional logic

end (unindented) block end notation

forstepnext loop construction

goto jump code execution

gosubreturn jump code execution, jump back

pop cancel gosub return ability

ongoto/ongosub comparison based jump code execution

let deprecated variable setting

rand random number generation

rem comment

read/dataend block of raw data

sdata/sreadend sequentially readable blocks of data

 

 

 

General Display Loop

drawscreen let kernel run

score score to display, must be BCD!

const noscore = 1 hide score

scorecolor color for score

player0:/player1: set player graphics

player0x/player0y/player0color: player 0 controls

player1x/player1y/player1color: player 0 display settings

missile0x/missile0y/missile0height missile 0 display settings

missile1x/missile1y/missile1height missile 0 display settings

ballx/bally/ballheight ball display settings

playfield: set playfield graphics

pfclear/pfhline/pfvline bulk playfield operations

pfpixel/pfread set/check playfield rectangles

pfscroll/playfieldpos playfield scrolling/jumping

reboot warm boot game (avoid if using rand)

pfscore1/pfscore2 binary content of scorebars

const pfscore = 1 enable scorebars

pfscorecolor scorebar color

switchreset/switchbw/switchselect/switchleftb/switchrightb switch reading

joy0up/joy0down/joy0left/joy0right/joy0fire joystick 0 inputs

joy1up/joy1down/joy1left/joy1right/joy1fire joystick 1 inputs

 

 

 

General TIA

AUDV0/AUDC0/AUDF0 Audio 0

AUDV1/AUDC1/AUDF1 Audio 1

COLUBK Background Color

COLUP0/COLUP1 Player/Missile Colors

REFP0/REFP1 mirror image for player

COLUPF Playfield/Ball Colors

CTRLPF ball and playfield/player effects

NUSIZ0/NUSIZ1 player missile effects

PF0 modify sides of PF directly

 

 

 

Advanced Core

asm insert inline assembly

bank/romsize managing memory banks

return thisbank/return otherbank cross banking subroutines

macro/callmacro use of shortcuts

dec decimal math (BCD) expression

function callable code bock with return value

include/inline insert asm module

includesfile include in batch

set compiler directives

 

 

 

Advanced Display Loop/Kernel

const pfres = # playfield number of rows

const pfrowheight = # height of pf rolls

player#height override player height (meltaway)

vblank indicate block in tv picture timing

readpaddle/currentpaddle get paddle info

 

 

 

DPC+ Display Loop/Kernel

set dpcspritemax # fewer sprites (reclaim memory)

player0color:/player1color: set up player colors

stack/pull/push variable stack manipulation

scorecolors: block of color for score

 

 

 

Life Counter/Status Bar Loop/Kernel

inline 6lives_statusbar.asm context sensitive enabling

inline 6lives.asm context sensitive enabling

lives life indicator graphic and count

lives: icon definition

lifecolor color

statusbarlength length of statusbar

statusbarcolor color of status bar

 

 

 

General Variables

az regular variables

az, var0var8, and killed off sprites DPC+ variables

temp# additional local variables

var# additional variables freeable with playfield

Back to Top

 

 

 

 

 

Things You Should Know

Back to Top

 

 

 

 

 

Miscellaneous

Back to Top

 

 

 

 

 

Variables

Template

For your convenience, here is a fill-in-the-blank dim template:

   dim _ = a
   dim _ = b
   dim _ = c
   dim _ = d
   dim _ = e
   dim _ = f
   dim _ = g
   dim _ = h
   dim _ = i
   dim _ = j
   dim _ = k
   dim _ = l
   dim _ = m
   dim _ = n
   dim _ = o
   dim _ = p
   dim _ = q
   dim _ = r
   dim _ = s
   dim _ = t
   dim _ = u
   dim _ = v
   dim _ = w
   dim _ = x
   dim _ = y
   dim _ = z

If you haven't used variables before, see What is a variable? and Glossary: Constants, Variables, and Values before you dive in.

 

You have 26 general purpose variables in batari Basic, fixed as a-z. Although they are fixed, you can use the dim command to map an alias to any of these variables.

There are only 26 variables, so you will use them up quickly. Therefore, it's recommended that you use the bit operations to access single bits when using variables for flags or game state information wherever possible. Sometimes bit operations are too limited, but if you have some variables that never go over 15, you can use one variable as two. See Nybble Variables for more information.

If you're using the standard kernel and run out of variables, you can use four bytes from the playfield if you're not scrolling it (var44 through var47). You can also use temporary variables temp1 through temp6 as temporary storage, but these are obliteratedDestroyed, erased. when drawscreen is called, and some are used for playfield operations as well, so use these at your own risk. If you're not using the Life Counter or Status Bar minikernels, you can use the variable statusbarlength and if you're also not using pfscore bars, you can use the variables lives and lifecolor. As with the regular 26 variables, aliases can be assigned to the playfield variables, statusbarlength, lives, and lifecolor.

 

Another option to get more variables is to use Superchip RAM which gives you 48 extra variables (from the old playfield) and more variables that can only be read and written to in a special way.

Although there might be unused bytes in the stack space, it is not recommended that you use these in your program since later versions of batari Basic will probably use these for something else.

 

 

Did You Know?

Bit operations do not use an equal sign in ifthen statements.

 

So don't do this:

  if a{0} = 1 then goto Shot2

Do this instead:

  if a{0} then goto Shot2

And don't do this:

   if a{0} = 0 then gameover

Do this instead:

  if !a{0} then gameover

Back to Top

 

 

 

 

 

Labels and Line Numbers

Alphanumeric labelsCan be made up of letters, numbers, and underscores. are supported by batari Basic. You may use line numbers if you prefer. Some old-school programmers like line numbers, or at least use them as a matter of comfort since they were necessary in early Basics. In any case, labels and line numbers are optional. Typically you will only need them when you want to specify a goto or gosub target.

Labels, line numbers, and end must not be indented, while all program statements must be. You may use labels with or without program statements after them. A label can have any combination of letters, numbers, or underscores, even as the first character. A label must not match or begin with a known keyword or any labels internal to bB (like end, kernel, and so on). For example, you cannot name a label next or pfpixel. Although you could not use 'scorechange' you could use 'changescore'. To avoid any problems, you could always start a label with one or two underscores. [Note from RT: I put one underscore in front of variable aliases and two underscores in front of labels. Then I don't have to worry if I'm using a keyword by mistake and I don't have to worry if a label has the same name as a variable alias.]

Example of the various ways you can use labels and line numbers:

10 pfpixel 2 3 on

20

   drawscreen

   player0x = player0x + 1 : goto __My_Location

   player0y = 29 : goto __My_Location_2

__My_Location

   x = x + 1

__My_Location_2 x = x - 1

Back to Top

 

 

 

 

 

Jumping Around

Back to Top

 

 

 

 

 

Decision Making (Brains of a Game)

Did You Know?

You are allowed only one OR for each ifthen statement. You can use more than one AND in a line, but you cannot mix AND with OR.

 

The NOT operator can only be used with statements that do not include OR or a comparison token (<, >, =). See Boolean Operators for more information.

 

Multiple ifthens in a single line might not work correctly if you are using AND, OR, or NOT.

 

 

AND/OR/NOT Chart

AND

More than one can be used.

 

Cannot be used with OR.

 

Safe to use with:

 

NOT

 

< > =

 

 

OR

Only one can be used.

 

Cannot be used with AND.

 

Cannot be used with NOT.

 

Safe to use with:

 

< > =

 

 

NOT

More than one can be used.

 

Cannot be used with OR.

 

Cannot be used with < > =.

 

Safe to use with:

 

AND

 

 

 

AND = &&    OR = ||    NOT = !

Back to Top

 

 

 

 

 

Loops

A common form of a loop is a for-next loop, but a loop in general is any program that repeats. In this sense, all batari Basic programs must be loops, in that the programs never exit.

 

In batari Basic, you should limit your use of loops that do not include the drawscreen function somewhere. Too many loops take time which is somewhat limited. See drawscreen for more information.

Back to Top

 

 

 

 

 

Random Numbers

Randomness will help make your games replayable and more fun. Players will get a fresh experience every time they play your games and they'll really be playing instead of memorizing an exact way to 'beat' your game that is set in stone. Unrestrained randomness would make your games impossible to play, so you need to control it. You can use Controlled Randomness to place non-player characters, bonus items, bonus areas, rooms, and more in a certain number of predetermined positions or general areas where you stay in control and nothing will come up in unexpected places. Your games will have replay value and most players will appreciate it.

 

 

Did You Know?

If you need a quick random number within a certain range, you can use AND (&) with the numbers 1, 3, 7, 15, 31, 63, or 127 (shown in the chart below). You can read more about it in a post by RevEng at AtariAge.

 

Warning: Using only division or only AND seems to create visible patterns. Mixing up division with AND seems to get rid of the patterns.

 

Faster Way

Binary

Range

Slower Way

a = (rand&1)

00000001

0 to 1

a = (rand/128)

a = (rand&1) + 1

 

1 to 2

a = (rand/128) + 1

a = (rand&3)

00000011

0 to 3

a = (rand/64)

a = (rand&3) + 1

 

1 to 4

a = (rand/64) + 1

a = (rand&7)

00000111

0 to 7

a = (rand/32)

a = (rand&7) + 1

 

1 to 8

a = (rand/32) + 1

a = (rand&15)

00001111

0 to 15

a = (rand/16)

a = (rand&15) + 1

 

1 to 16

a = (rand/16) + 1

a = (rand&31)

00011111

0 to 31

a = (rand/8)

a = (rand&31) + 1

 

1 to 32

a = (rand/8) + 1

a = (rand&63)

00111111

0 to 63

a = (rand/4)

a = (rand&63) + 1

 

1 to 64

a = (rand/4) + 1

a = (rand&127)

01111111

0 to 127

a = (rand/2)

a = (rand&127) + 1

 

1 to 128

a = (rand/2) + 1

 

It seems AND (&) uses the fewest cycles compared to other techniques that have been posted at AtariAge. For example, a = (rand&7) is faster than a = (rand/32).

 

Notice that adding a number changes the minimum and maximum numbers. For example, a = (rand&7) + 8 would give you a random number between 8 (0 + 8 = 8) and 15 (7 + 8 = 15).

 

If you need a random number that is either -1 or 1, try this:

a = 255 + (rand&2)

 

Randomizing a bit is easy thanks to RevEng. Check it out.

Back to Top

 

 

 

 

 

Data Statements and Arrays (read-only)

Did You Know?

All data tables, regular or sequential, must be located in the same bank where they are read. If you try to access data in another bank, there will be no errors, but the data you get will certainly be incorrect.

For convenience, you may specify a list of values that will essentially create a read-only array in ROM. You create these lists of values as data tables using the data statement. Although the data statement is similar in its method of operation as in other Basic languages, there are some important differences. Most notably, access to the data does not need to be linear as with the read function in other Basics, and the size is limited to 256 bytes.

 

If you prefer to use a data statement similar to that in other Basics and don't want to be limited to 256 bytes, see Sequential Data below.

 

In a regular data statement, any element of the data statement can be accessed at any time. In this vein, it operates like an array. To declare a set of data, use data at the beginning of a line, then include an identifier after the statement. The actual data is included after a linefeed and can continue for a number of lines before being terminated by end. Suppose you declare a data statement as follows, with array name _My_Data:

   data _My_Data
   200, 43, 33, 93, 255, 54, 22
end

To access the elements of the data table, simply index it like you would an array in RAM. For example, _My_Data[0] is 200, _My_Data[1] is 43, ... and _My_Data[6] is 22. The maximum size for a data table is 256 elements. Note that there is no checking to see if you have accessed values beyond the table. Doing so will not cause any errors, but the values you get probably won't be very useful.

 

The example below has two data tables. Press the joystick left to read from one data table and press the joystick right to read from the other. Repeatedly press and release the joystick in either direction to move through the data.

   ;***************************************************************
   ;
   ;  Variable aliases go here (DIMs).
   ;

   ;```````````````````````````````````````````````````````````````
   ;  Data counter.
   ;
   dim _D_Counter = m

   ;```````````````````````````````````````````````````````````````
   ;  Remembers data.
   ;
   dim _D_Mem = n

   ;```````````````````````````````````````````````````````````````
   ;  Converts 6 digit score to 3 sets of two digits.
   ;
   ;  The 100 thousands and 10 thousands digits are held by sc1.
   ;  The thousands and hundreds digits are held by sc2.
   ;  The tens and ones digits are held by sc3.
   ;
   dim sc1 = score
   dim sc2 = score+1
   dim sc3 = score+2

   ;```````````````````````````````````````````````````````````````
   ;  Joy0 restrainer bit.
   ;
   dim _Bit6_Joy0_Restrainer = y



   ;***************************************************************
   ;
   ;  Sets score color.
   ;
   scorecolor = $9C





   ;***************************************************************
   ;***************************************************************
   ;
   ;  MAIN LOOP (MAKES THE PROGRAM GO)
   ;
   ;
__Main_Loop



   ;***************************************************************
   ;
   ;  Joystick section.
   ;
   ;```````````````````````````````````````````````````````````````
   ;  If joystick not moved, clear the joystick restrainer bit
   ;  and skip this subsection.
   ;
   if !joy0left && !joy0right then _Bit6_Joy0_Restrainer{6} = 0 : goto __Skip_Joy0

   ;```````````````````````````````````````````````````````````````
   ;  If joystick already moved, skip this subsection.
   ;
   if _Bit6_Joy0_Restrainer{6} then goto __Skip_Joy0

   ;```````````````````````````````````````````````````````````````
   ;  Turns on the joystick restrainer bit.
   ;
   _Bit6_Joy0_Restrainer{6} = 1

   ;```````````````````````````````````````````````````````````````
   ;  If joystick moved left, get data.
   ;
   if joy0left then _D_Mem = _Data_Baked_Potato[_D_Counter]

   ;```````````````````````````````````````````````````````````````
   ;  If joystick moved right, get other data.
   ;
   if joy0right then _D_Mem = _Data_Toenail_Fungus[_D_Counter]

   ;```````````````````````````````````````````````````````````````
   ;  Increments and limits data counter.
   ;
   _D_Counter = _D_Counter + 1 : if _D_Counter > 6 then _D_Counter = 0

__Skip_Joy0



   ;***************************************************************
   ;
   ;  Puts _D_Mem in the three score digits on the right side.
   ;   
   temp4 = _D_Mem
   sc2 = sc2 & 240 : sc3 = 0
   if temp4 >= 100 then sc2 = sc2 + 1 : temp4 = temp4 - 100
   if temp4 >= 100 then sc2 = sc2 + 1 : temp4 = temp4 - 100
   if temp4 >= 50 then sc3 = sc3 + 80 : temp4 = temp4 - 50
   if temp4 >= 30 then sc3 = sc3 + 48 : temp4 = temp4 - 30
   if temp4 >= 20 then sc3 = sc3 + 32 : temp4 = temp4 - 20
   if temp4 >= 10 then sc3 = sc3 + 16 : temp4 = temp4 - 10
   sc3 = sc3 | temp4



   ;***************************************************************
   ;
   ;  Displays the screen.
   ;
   drawscreen



   goto __Main_Loop





   ;***************************************************************
   ;
   ;  Data table 01.
   ;
   data _Data_Baked_Potato
   11, 22, 33, 44, 55, 66, 77
end



   ;***************************************************************
   ;
   ;  Data table 02.
   ;
   data _Data_Toenail_Fungus
   1, 2, 3, 4, 5, 6, 7
end

 

 

To help prevent the reading of values beyond data tables, a constant is defined with every data statementthis constant contains the length, or the number of elements, in the data. The constant will have the same name as the name of the data statement, but it will have _length appended to it.

 

For example, if you declare:

   data _My_Data
   1,2,3,4,5,6,7,8,9 
end

you can then access the length of the data with _My_Data_length. You can assign this to variables or use anywhere else you would use a number.

 

Example:

   a = _My_Data_length

These data _length constants will not work correctly if they are used before you declare the corresponding data statement. If you need to use a data _length constant before its data statement, declare the data _length constant near the beginning of your program (using the name of the constant as the value).

 

Example:

   const _My_Data_length=_My_Data_length

Note again that these data tables are in ROM. Attempting to write values to data tables with commands like _My_Data[1]=200 will compile but will perform no function.

 

 

Back to Top

 

 

 

 

 

Colors

Did You Know?

You might think you have chosen the perfect colors when testing your games using an emulator, but Atari 2600 colors are darker on televisions and some of the darker grays may appear to be black. For example, if you are using 2, 4, and 6; bump it up to 6, 8, and 10 if you want a picture that will display brightly enough on most televisions.

The Atari 2600 can display up to 128 unique colors — that is, 16 unique hues and 8 luminosityBrightness. levels for each hue for NTSCNational Television Systems Committee
(Or jokingly, Never The Same Color.)
consoles (see tv directive.) PALPhase Alternation Line
(Or jokingly, Picture Always Lousy or Pay Another Licence.)
consoles can display 104 unique colors (13 hues with 8 luminosity levels.)

Each player object can be colored independently, as can the playfield, background, score, and objects drawn in a minikernel. Also, you can make multicolored objects by using kernel options. The missiles, however, must share their colors with their respective player objects, and the ball will generally be the same color as the playfield.

 

 

██      

██      

██      

██

NTSC  (128 unique colors)

Color Value:  ██     

 

0

2

4

6

8

A

C

E

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

PAL  (104 unique colors)

Color Value:  ██     

 

0

2

4

6

8

A

C

E

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

SECAM  (8 unique colors)

Color Value:  ██     

 

0

2

4

6

8

A

C

E

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

Back to Top

 

 

 

 

 

Objects

Did You Know?

You will not be able to precisely duplicate sprites from classic games because bB uses double-height pixels. The double-height pixels were used because it gives more time in the kernel for features such as the asymmetric playfield.

 

The good news is that the new DPC+ kernel uses single-height sprite pixels, so you'll be able to recreate the more detailed classic look.

 

 

Enemy AI Links

Enemy AI

Tips from AtariAge members.

 

Artificial Brilliance - Television Tropes & Idioms

Artificial Brilliance is, quite simply, the ability of the computer characters to make the player think "Hey, these guys are actually pretty smart!"

 

A* Pathfinding for Beginners

The A* (pronounced A-star) algorithm can be complicated for beginners. While there are many articles on the web that explain A*, most are written for people who understand the basics already. This article is for the true beginner.

 

The Secrets Of Enemy AI In Uncharted 2

Most games have some form of AI and regardless of the genre of game, there are fairly common requirements that have to be met.

 

Enemy AI by Annie Dickerson

The first time I heard of a game designer working on enemy AI, I thought, pfft, how hard could it be?

 

A Study in Stealth: How AI Shapes the Genre

Twelve men were stationed on that boat; one-by-one, I dragged them to their doom. Even the last one strolled around an empty boat devoid of fellow guards and remained utterly oblivious until my hand snaked up and caught his belt.

Back to Top

 

 

 

 

 

The Playfield

Did You Know?

The width of a playfield pixel is the same as a sprite that is 4 pixels wide. The height of the standard playfield pixel before changing any row heights is about the same as a sprite that is 8 pixels tall.

 

 

Did You Know?

The second and fourth playfield variables of each row have a reversed bit order. If you don't know they are reversed, you'd expect that

"var0=1 : var1=1 : var2=1 : var3=1"

or

"var0=$01 : var1=$01 : var2=$01 : var3=$01"

or

"var0=%00000001 : var1=%00000001 : var2=%00000001 : var3=%00000001"

would give you this:

. . . . . . . X . . . . . . . X . . . . . . . X . . . . . . . X

But you wouldn't get that. You'd really get this:

. . . . . . . X X . . . . . . . . . . . . . . X X . . . . . . .

As long as you remember that the second and fourth playfield variables of each row have a reversed bit order, you won't rip your hair out in frustration or wonder if you have lost your mind.

In the standard kernel, by default, you get a 32 x 11 bitmapped, asymmetric playfield (32 x 12 if you count the hidden row that is only seen if scrolled). Below is a standard kernel playfield variable chart for advanced users. There are 4 variables for each row (8 bits x 4 = 32).

Row 0   var0 var1 var2 var3
Row 1   var4 var5 var6 var7
Row 2   var8 var9 var10 var11
Row 3   var12 var13 var14 var15
Row 4   var16 var17 var18 var19
Row 5   var20 var21 var22 var23
Row 6   var24 var25 var26 var27
Row 7   var28 var29 var30 var31
Row 8   var32 var33 var34 var35
Row 9   var36 var37 var38 var39
Row 10   var40 var41 var42 var43
Row 11   var44 var45 var46 var47


The multisprite kernel gives you a 16-wide playfield, which is mirrored about the center of the screen. Plotting commands such as pfpixel, pfvline and pfhline do not work in this kernel. However, pfread does work if you include a special module. HorizontalLeft-Right
Left and Right
scrolling is not possible, but support for verticalUp-Down
Up and Down
scrolling is planned.

The playfield resides in the full vertical length of the screen except for the area reserved for the score. Horizontally, the playfield only uses the center 80% of the screen due to timing constraints. You have only limited access to left or right 10% of the screen, namely you can only draw vertical lines there, and they take the full length of the screen. For example, you can put a vertical border around the drawable portion of the playfield by PF0=128 (PF0 = %10000000) See PF0 for more information. You can use COLUBK to set the background color and COLUPF to set the playfield color. See the color chart for available colors.

 

You can specify an entire playfield in one command by using the playfield: command. The syntax of the command is:

 

  playfield: <off> <on>
  (pixels)
end

Because of a bug in the preprocessor, <off> and <on> do not work at this time, but when the problem is fixed in a future update of bB, they will be optional and allow you to change the off/on symbols for the playfield pixels. Default: . and X

Example:

   playfield:
   X.X...X..XX..X.XX.X....XX..X.X..
   X.X....XX..X.X..X.X...X..XX..X.X
end

You can specify as many lines high as you want, but some may not display if you specify too many.

In the standard kernel, use 32 characters for each line.

In the multisprite kernel, the above only accepts 16 characters wide, and these 16 are reflected on the right.

Please see pfpixel, pfvline, pfhline, and pfscroll for more information about drawing to the playfield.

 

Note: You don't need to have your playfield data in the main loop. Whatever you tell the playfield to look like before the main loop starts is what it will look like forever until you tell it to look differently.

 

The playfield in the standard kernel is no longer fixed at 11+1 pixels high. It can be varied using the pfres setting. The default value for the vertical resolution is 12. If you wish, you can set pfres to values from 3-11. This will shrink the vertical resolution of the playfield and sometimes the visible screen as well. Doing so has advantages, such as freeing up space for more variables and possibly giving more time for each frame in your bB code or minikernels.

If you are using Superchip RAM, you can use a pfres value up to 32, and all variables from var0-var47 are always free for general use. See Superchip RAM for more information.

You set the value using const. Example:

   const pfres=10

The playfield uses 4 bytes for each row, so setting the height to 10 would free up 8 bytes that could then be used as variables. These variables are available as var0-var7.

Also, note that reducing the number of rows may or may not shrink the size of your screen since bB tries to fill as much of the screen as possible by varying the height of the pixel rows. The default row heights and free variables corresponding to the overall playfield height (pfres) is:

pfres

Row Height

Variables Freed

12  8 none
11  8 var0-var3
10  9 var0-var7
 9 10 var0-var11
 8 12 var0-var15
 7 13 var0-var19
 6 16 var0-var23
 5 19 var0-var27
 4 24 var0-var31
 3 32 var0-var35


If you don't like the default row heights, you can specify your own by setting pfrowheight. Note that if pfres*pfrowheight exceeds 96, the screen size will increase and cut into your bB program's time, or in extreme cases, will make the screen jitter, shake or roll.

To set pfrowheight, use const:

   const pfrowheight=7

If you do not want to be stuck using a single, shared row height, you can specify the height of individual playfield rows by setting the pfheights kernel option.

Did You Know?

Although vblank looks similar to a normal subroutine, you shouldn't try to jump to it using gosub. It is placed at the end of your program or in the last bank of a bankswitched game (outside of any loops) and runs automatically every time a drawscreen is called. If you're using bankswitching, remember that vblank is special, so don't replace vblank's return with return otherbank.

Back to Top

 

 

 

 

 

TIA Registers

There are a few TIA registers that may be useful in batari Basic. This is not a complete list. I'm only mentioning the registers and functions therein that you will most likely find useful. You can learn more by visiting the Stella Programmer's Guide.

 

 

Back to Top

 

 

 

 

 

Collision Detection

Did You Know?

You need to place your drawscreen before the section of code that checks for collisions (the Atari 2600 has to draw the frame for the collision registers to get triggered).

Back to Top

 

 

 

 

 

Display Kernel

The display kernelThe fundamental part of an operating system. (usually just "the kernel") is a carefully-written software routine that renders the television display. The Atari 2600's television signal is controlled largely by software because the hardware is so primitive. Although programming a 2600 kernel is quite difficult, the primitive hardware also affords a good deal of flexibility, in that custom kernels can exploit the primitive hardware to suit particular needs.

The original bB kernel was modeled as one-size-fits-all. This allowed for a decent variety of games, but some games were not possible. Furthermore, some of the games that were possible did not look as good as games written in pure assembly.

Therefore, the latest version of bB has not one, but actually 29 possible kernels to choose from. 27 of those 29 are based on the standard kernel, optionally adding bells and whistles as needed (sometimes for free, sometimes at a cost). See kernel options under compiler directives for more information about what these options are and how to use them. The DPC+ kernel only uses one kernel option and that's to help with collisions.

 

 

 

Did You Know?

DPC+ is based on the Display Processor Chip that was designed by David Crane for Pitfall II: Lost Caverns. The DPC+ kernel is hardware assisted and only works with Melody/Harmony cartridges and any version of Stella released after October of 2012.

 

In March of 2010, SpiceWare did some experiments with DPC. He liked what he saw, but thought something better could be done, so he asked if it would be possible to expand DPC. SpiceWare, batari, and cd-w hashed out what eventually became DPC+. They decided not to implement unused DPC functions and replaced them with other features.

 

They developed DPC+ in Stella first (with stephena's help), then batari wrote the DPC+ driver for Harmony/Melody. You can learn more at AtariAge.

Did You Know?

Variables liberated with dpcspritemax can be used with dim. Below is a template list that might be helpful. Only copy and paste the section of the list that has numbers that are larger than the number used with dpcspritemax.

   dim _ = player2x
   dim _ = player2y
   dim _ = NUSIZ2
   dim _ = player2height
   dim _ = player3x
   dim _ = player3y
   dim _ = NUSIZ3
   dim _ = player3height
   dim _ = player4x
   dim _ = player4y
   dim _ = NUSIZ4
   dim _ = player4height
   dim _ = player5x
   dim _ = player5y
   dim _ = NUSIZ5
   dim _ = player5height
   dim _ = player6x
   dim _ = player6y
   dim _ = NUSIZ6
   dim _ = player6height
   dim _ = player7x
   dim _ = player7y
   dim _ = NUSIZ7
   dim _ = player7height
   dim _ = player8x
   dim _ = player8y
   dim _ = NUSIZ8
   dim _ = player8height
   dim _ = player9x
   dim _ = player9y
   dim _ = NUSIZ9
   dim _ = player9height

 

And for your convenience, here is a template for the rest of the variables:

   dim _ = a
   dim _ = b
   dim _ = c
   dim _ = d
   dim _ = e
   dim _ = f
   dim _ = g
   dim _ = h
   dim _ = i
   dim _ = j
   dim _ = k
   dim _ = l
   dim _ = m
   dim _ = n
   dim _ = o
   dim _ = p
   dim _ = q
   dim _ = r
   dim _ = s
   dim _ = t
   dim _ = u
   dim _ = v
   dim _ = w
   dim _ = x
   dim _ = y
   dim _ = z
   dim _ = var0
   dim _ = var1
   dim _ = var2
   dim _ = var3
   dim _ = var4
   dim _ = var5
   dim _ = var6
   dim _ = var7
   dim _ = var8

 

Back to Top

 

 

 

 

 

Compiler Directives (set command)

The set command tells the compiler or the assembler to build your code a certain way. The syntax is:

 

set <directive> <option>

 

Currently, the following directives are supported:

 

Typically you will use the directives near the beginning of your program. However, smartbranching and optimization were originally designed to be set, reset, and/or turned on and off throughout your code (though I'm not sure if this actually works :| )

 

 

Back to Top

 

 

 

 

 

Bankswitching (Up to 32K of ROM for your games!)

Did You Know?

Banks have a space between bank and the number.

 

Example:

   bank 2

   bank 3

   bank 4

When jumping to a label in another bank using goto or gosub, you must specify the bank without a space between bank and the number.

 

Example:

   gosub __Limburger bank3

   goto __Frog bank2

The Atari 2600 can only address 4K at a time. Games larger than 4K are possible by additional hardware on the cartridge that can swap in two or more banks of 4K. Since the 2600 can only 'see' 4K at once, the 2-8 banks also can't see each other; that is, one bank cannot access data in another bank. Also, since an entire bank needs to be swapped in all at once, normally this would make programming somewhat more difficult.

Bankswitching in bB cannot get past one limitation — One bank still cannot access data from another bank, so data tables can only be accessed from within the same bank in which they are located.

However, the fact that banks must be swapped in all at once doesn't pose any serious technical problems for bB. You can use goto to jump to any routine in another bank, and you can also use gosub for a subroutine, and a return will automatically return to the bank that called the subroutine. This is because bB uses a clever little routine that automatically knows what bank it is in at any time and what bank called a subroutine. This routine does require some overhead in terms of cycles and space, so you should limit bankswitching to a few times each frame.

To activate bankswitching, you just need to set the size of the binary using "set romsize", with a value of 8K or larger (see compiler directives).

You do not need to specify where sprite graphics go, as they all will be automatically placed in the last bank no matter where you define them (you can just leave all of your animation frames in the same bank that contains your main loop). Also, the kernel will always be placed in the last bank. Typically, bB modules and functions will as well. You don't need to do anything differently with drawscreen, and you typically don't with built-in functions or modules either.

 

For the standard kernel, playfield graphics data gets stored in whatever bank you place it in. For the multisprite kernel, playfield graphics data automatically gets stored in the last bank. For the DPC+ kernel, playfield graphics data automatically gets stored in the "graphics" bank.

 

In most cases, you must specify where new banks begin. You do not need to specify where the first bank starts, as it must start at the beginning of your code. Strictly speaking, you don't need to specify where additional banks start, but if you don't, you won't be able to put your code in other banks. This might not be a huge problem for an 8K binary (where a good portion of both banks will be used, regardless) but it doesn't make much sense for a 16K or 32K binary.

To specify the beginning of a new bank, use the "bank" keyword, followed by the bank you wish to begin. 8K binaries contain two banks, 16K has four, and 32K has eight.

 

 
   set romsize 8k
   bank 2
   set romsize 8kSC
   bank 2
   set romsize 16k
   bank 2
   bank 3
   bank 4
   set romsize 16kSC
   bank 2
   bank 3
   bank 4
   set romsize 32k
   bank 2
   bank 3
   bank 4
   bank 5
   bank 6
   bank 7
   bank 8
   set romsize 32kSC
   bank 2
   bank 3
   bank 4
   bank 5
   bank 6
   bank 7
   bank 8

 

 

 

Remember, specifying "bank 1" is unnecessary.

See goto, gosub and return for more information about jumping from one bank to another.

 

 

 

 

 

 

12 Rows pfres not used (8 pixels high)

12 x 4 = 48

128 - 48 = 80 (r/w080)

You get 80 extra variables (r/w000-r/w079).

 

Row 0   r/w080 r/w081 r/w082 r/w083
Row 1   r/w084 r/w085 r/w086 r/w087
Row 2   r/w088 r/w089 r/w090 r/w091
Row 3   r/w092 r/w093 r/w094 r/w095
Row 4   r/w096 r/w097 r/w098 r/w099
Row 5   r/w100 r/w101 r/w102 r/w103
Row 6   r/w104 r/w105 r/w106 r/w107
Row 7   r/w108 r/w109 r/w110 r/w111
Row 8   r/w112 r/w113 r/w114 r/w115
Row 9   r/w116 r/w117 r/w118 r/w119
Row 10   r/w120 r/w121 r/w122 r/w123
Row 11   r/w124 r/w125 r/w126 r/w127
 

18 Rows const pfres=18 (5 pixels high)

18 x 4 = 72

128 - 72 = 56 (r/w056)

You get 56 extra variables (r/w000-r/w055).

 

Row 0   r/w056 r/w057 r/w058 r/w059
Row 1   r/w060 r/w061 r/w062 r/w063
Row 2   r/w064 r/w065 r/w066 r/w067
Row 3   r/w068 r/w069 r/w070 r/w071
Row 4   r/w072 r/w073 r/w074 r/w075
Row 5   r/w076 r/w077 r/w078 r/w079
Row 6   r/w080 r/w081 r/w082 r/w083
Row 7   r/w084 r/w085 r/w086 r/w087
Row 8   r/w088 r/w089 r/w090 r/w091
Row 9   r/w092 r/w093 r/w094 r/w095
Row 10   r/w096 r/w097 r/w098 r/w099
Row 11   r/w100 r/w101 r/w102 r/w103
Row 12   r/w104 r/w105 r/w106 r/w107
Row 13   r/w108 r/w109 r/w110 r/w111
Row 14   r/w112 r/w113 r/w114 r/w115
Row 15   r/w116 r/w117 r/w118 r/w119
Row 16   r/w120 r/w121 r/w122 r/w123
Row 17   r/w124 r/w125 r/w126 r/w127
 
 

23 Rows const pfres=23 (4 pixels high)

23 x 4 = 92

128 - 92 = 36 (r/w036)

You get 36 extra variables (r/w000-r/w035).

 

Row 0   r/w036 r/w037 r/w038 r/w039
Row 1   r/w040 r/w041 r/w042 r/w043
Row 2   r/w044 r/w045 r/w046 r/w047
Row 3   r/w048 r/w049 r/w050 r/w051
Row 4   r/w052 r/w053 r/w054 r/w055
Row 5   r/w056 r/w057 r/w058 r/w059
Row 6   r/w060 r/w061 r/w062 r/w063
Row 7   r/w064 r/w065 r/w066 r/w067
Row 8   r/w068 r/w069 r/w070 r/w071
Row 9   r/w072 r/w073 r/w074 r/w075
Row 10   r/w076 r/w077 r/w078 r/w079
Row 11   r/w080 r/w081 r/w082 r/w083
Row 12   r/w084 r/w085 r/w086 r/w087
Row 13   r/w088 r/w089 r/w090 r/w091
Row 14   r/w092 r/w093 r/w094 r/w095
Row 15   r/w096 r/w097 r/w098 r/w099
Row 16   r/w100 r/w101 r/w102 r/w103
Row 17   r/w104 r/w105 r/w106 r/w107
Row 18   r/w108 r/w109 r/w110 r/w111
Row 19   r/w112 r/w113 r/w114 r/w115
Row 20   r/w116 r/w117 r/w118 r/w119
Row 21   r/w120 r/w121 r/w122 r/w123
Row 22   r/w124 r/w125 r/w126 r/w127

See 32 x 23 Maze with Animated Sprite and Roaming Sprite for a working example that uses const pfres=23.

 

32 Rows const pfres=32 (3 pixels high)

32 x 4 = 128

128 - 128 = 0 (r/w000)

You get 0 extra variables.

 

Row 0   r/w000 r/w001 r/w002 r/w003
Row 1   r/w004 r/w005 r/w006 r/w007
Row 2   r/w008 r/w009 r/w010 r/w011
Row 3   r/w012 r/w013 r/w014 r/w015
Row 4   r/w016 r/w017 r/w018 r/w019
Row 5   r/w020 r/w021 r/w022 r/w023
Row 6   r/w024 r/w025 r/w026 r/w027
Row 7   r/w028 r/w029 r/w030 r/w031
Row 8   r/w032 r/w033 r/w034 r/w035
Row 9   r/w036 r/w037 r/w038 r/w039
Row 10   r/w040 r/w041 r/w042 r/w043
Row 11   r/w044 r/w045 r/w046 r/w047
Row 12   r/w048 r/w049 r/w050 r/w051
Row 13   r/w052 r/w053 r/w054 r/w055
Row 14   r/w056 r/w057 r/w058 r/w059
Row 15   r/w060 r/w061 r/w062 r/w063
Row 16   r/w064 r/w065 r/w066 r/w067
Row 17   r/w068 r/w069 r/w070 r/w071
Row 18   r/w072 r/w073 r/w074 r/w075
Row 19   r/w076 r/w077 r/w078 r/w079
Row 20   r/w080 r/w081 r/w082 r/w083
Row 21   r/w084 r/w085 r/w086 r/w087
Row 22   r/w088 r/w089 r/w090 r/w091
Row 23   r/w092 r/w093 r/w094 r/w095
Row 24   r/w096 r/w097 r/w098 r/w099
Row 25   r/w100 r/w101 r/w102 r/w103
Row 26   r/w104 r/w105 r/w106 r/w107
Row 27   r/w108 r/w109 r/w110 r/w111
Row 28   r/w112 r/w113 r/w114 r/w115
Row 29   r/w116 r/w117 r/w118 r/w119
Row 30   r/w120 r/w121 r/w122 r/w123
Row 31   r/w124 r/w125 r/w126 r/w127
 

Back to Top

 

 

 

 

 

Sound

Sound and Music Links

Tone Toy 2008

A program for the Atari 2600 made with batari Basic that lets you play with sounds and sound effects using loops. It can simply be used as a toy or you can use it to think up possible new sound effects for your games.

 

VbB Music and Sound Editor

Easily create music and sound effects for your games using this built-in VbB editor.

 

The Atari 2600 Music and Sound Page

Expanded information about Atari 2600 sound.

 

do re bB

the BASICs of batari music.

 

Piano Key Frequencies

Interesting information at Wikipedia.

Text by SeaGtGruff (adapted by Random Terrain)

The Atari 2600's sound is generated by the TIA chip, which has two independent audio channels that work identically (channel 0 and channel 1). Each channel has three registers that determine the sound that will be produced (AUDV0, AUDC0, AUDF0, AUDV1, AUDC1, AUDF1).

 

AUDVx stands for AUDio Volume. The volume register determines the volume or amplitude of the sound that will be produced. Valid values are 0 through 15.

 

AUDCx stands for AUDio Control. The control register determines the waveform or tonal quality that will be produced. Valid values are 0 through 15.

 

AUDFx stands for AUDio Frequency. The frequency register determines the frequency or note that will be produced. Valid values are 0 through 31.

 

Set AUDV0 or AUDV1 to pick the volume or amplitude of the sound you want to play0 is "off" or "mute" and 15 is the loudest.

 

Set AUDC0 or AUDC1 to pick the waveform you want to use. With one exception, each waveform is just a stream of 0s and 1s that are repeated endlessly in a specific pattern, causing the speaker to vibrate in that pattern and create a sound. The length of the pattern determines the primary frequency of the sound, and the complexity of the pattern determines how "pure" or "noisy" the sound is. One waveform is just a stream of 1s (or "always on"), so it sounds "silent" (because the speaker doesn't vibrate back and forth the way it does with the other waveforms)-- but you can use the volume register with this "always on" waveform to create your own waveforms.

 

Set AUDF0 or AUDF1 to pick the frequency or note you want to play. The TIA doesn't use the standard set of musical notes (C, D, F#, G, etc.)instead, it uses harmonics (or really "subharmonics") of the primary frequency that's been selected with the AUDC0 or AUDC1 register. To determine what the resulting frequency will be, add 1 to the AUDF0 or AUDF1 setting and divide the primary frequency by that numberfor example, AUDF0 = 3 divides the primary frequency by 4 (3 plus 1), whereas AUDF0 = 7 divides it by 8.

 

Unless you're using the "always on" waveform, making music with the TIA is a "set it and forget it" thing, meaning you can set AUDC0, AUDV0, and AUDF0 (or AUDC1, AUDV1, and AUDF1) and they'll keep their values, playing the same sound continuously until you change their settings to pick a different sound. In practical terms, this means you don't need to keep setting them over and over again within a loop to keep playing the same sound; you just set them once and then you don't have to worry about them again until you're ready to play a different sound.

 

 

Below are two example programs that show how you can make sounds without using data.

 

A simple/plain/lazy sound is made in the example below when the fire button is pressed:

   dim _Sound0 = c
   dim _Chan0_Duration = d
   dim _C0 = e
   dim _V0 = f
   dim _F0 = g



__Main_Loop



   ;***************************************************************
   ;
   ;  Fire button check.
   ;
   ;  Turns on channel 0 sound effect 1 if fire button is pressed.
   ;
   if joy0fire then if !_Sound0 then _Sound0 = 1 : _Chan0_Duration = 15



   ;***************************************************************
   ;
   ;  Channel 0 sound effect check.
   ;
   ;```````````````````````````````````````````````````````````````
   ;  If no channel 0 sound effect is on, skip all channel 0
   ;  sound effect subsections.
   ;
   if !_Sound0 then goto __Skip_Channel_0

   ;```````````````````````````````````````````````````````````````
   ;  Decreases the channel 0 duration counter.
   ;
   _Chan0_Duration = _Chan0_Duration - 1

   ;```````````````````````````````````````````````````````````````
   ;  If channel 0 duration counter is zero, end current sound
   ;  effect.
   ;
   if !_Chan0_Duration then goto __Clear_Channel_0



   ;***************************************************************
   ;
   ;  Channel 0 sound effect 1.
   ;
   ;  A simple/plain/lazy sound.
   ;
   ;```````````````````````````````````````````````````````````````
   ;  If sound 1 isn't on, skip this subsection.
   ;
   if _Sound0 <> 1 then goto __Skip_Chan0_Sound_001

   ;```````````````````````````````````````````````````````````````
   ;  Sets the tone, volume and frequency.
   ;
   AUDC0 = 4 : AUDV0 = 8 : AUDF0 = 19

__Skip_Chan0_Sound_001



   ;***************************************************************
   ;
   ;  Other channel 0 sound effects go here.
   ;
   ;***************************************************************



   ;***************************************************************
   ;
   ;  Jumps to end of channel 0 area.
   ;
   goto __Skip_Channel_0



   ;***************************************************************
   ;
   ;  Clears channel 0.
   ;
__Clear_Channel_0

   ;```````````````````````````````````````````````````````````````
   ;  Turns off channel 0 sound variable and mutes channel.
   ;
   _Sound0 = 0 : AUDV0 = 0



   ;***************************************************************
   ;
   ;  End of channel 0 area.
   ;
__Skip_Channel_0



   ;***************************************************************
   ;
   ;  Displays the screen.
   ;
   drawscreen



   goto __Main_Loop

 

 

 

The example below has five sound effects. A different sound effect is assigned to the each of the four joystick directions and the same simple/plain/lazy sound effect from above is still assigned to the fire button:

 

Once you check out the other four sound effects in the example program above, you can see how easy it is to take a plain old lazy sound effect and make it sound more complex or more pleasing to the ear.

 

 

 

 

Setting the values, for instance, by AUDV0 = 10 : AUDC0 = 12 : AUDF0 = 4 will produce a tone, and it will stay on until you set AUDV0 = 0. Typically, a frame counter is set up that keeps sounds on for a specified number of frames (which occur 60 times a second).

The following chart is adapted from Atari 2600 VCS Precise Sound Values and Distortion Breakdown by Glenn Saunders:

 

Tone

What it Sounds Like

     
     
 0

No sound (silent).

     
     
 1

Buzzy tones.

     
     
 2

Carries distortion 1 downward into a rumble.

     
     
 3

Flangy wavering tones, like a UFO.

     
     
 4

Pure tone.

     
     
 5

Same as 4.

     
     
 6

Between pure tone and buzzy tone (Adventure death uses this).

     
     
 7

Reedy tones, much brighter, down to Enduro car rumble.

     
     
 8

White noise/explosions/lightning, jet/spacecraft engine.

     
     
 9

Same as 7.

     
     
10

Same as 6.

     
     
11

Same as 0.

     
     
12

Pure tone, goes much lower in pitch than 4 & 5.

     
     
13

Same as 12.

     
     
14

Electronic tones, mostly lows, extends to rumble.

     
     
15

Electronic tones, mostly lows, extends to rumble.

     
     

 

 

Summary:

 

Unique

Redundant 

0
11
1 2 3 4
5
6
10
7
9
8 12
13
14 15


Back to Top

 

 

 

 

 

Joysticks

Did You Know?

The joysticks and fire buttons are similar to bit operations in how they are read (an equal sign is not used).

 

So don't do this:

  if joy0fire = 1 then . . .

Do this instead:

  if joy0fire then . . .

And don't do this:

   if joy0fire = 0 then . . .

Do this instead:

  if !joy0fire then . . .

Joysticks are read by using an ifthen statement. There are four directional functions and one fire function for each joystick.

Example:

   if joy0up then y = y - 1
   if joy0down then y = y + 1
   if joy0left then x = x - 1
   if joy0right then x = x + 1
   if joy0fire then goto __Purple_Monkey

These can also be inverted using the NOT ( ! ) token. For example:

   if !joy0up then goto __Tasty_Pilgrim

Below are two example programs that might be useful. The first one disables rapid-fire. The second program uses variable-speed rapid-fire.

 

 

SWCHA

Back to Top

 

 

 

 

 

Console Switches

Reading the console switches is done by using an ifthen statement.

 

For example, these are accessed by:

   if switchreset then 200

These can all be inverted by the NOT (!) token:

   if !switchreset then 200

Back to Top

 

 

 

 

 

Numbers

Did You Know?

The calculator on your computer can convert decimal, hex, and binary numbers, but this online tool seems to be faster, easier to use, and more fun.

Back to Top

 

 

 

 

 

Math

Did You Know?

The calculator on your computer can convert decimal, hex, and binary numbers, but this online tool seems to be faster, easier to use, and more fun.

Full expression evaluation for integerAny number without a decimal (positive, negative or zero). A whole number. math is supported by batari Basic. It evaluates expressions as efficiently as possible by using the stack when needed to perform intermediate calculations, so no additional space is needed in most cases.

You can only use expression evaluation for variable assignments. You can't (yet) use expressions as arguments in functions, bB commands or comparisons, or with fixed point math.

Expressions can contain addition, subtraction, division, multiplication and/or bitwise operators.


The order of operations is:
() Parentheses
*,/ Multiplication and division (see below)
+,- Addition and subtraction (see below)
&,^,| Bitwise operators

Examples of complex expressions:

   a = e-4*2
   a = (e-4)*2
   a = (e-4)*2*(myarray[4]-(4+c[r]))+2|e

Warning: Using complex expressions might result in a localized overflow (that is, an intermediate value that exceeds 255 or is less than zero) if sub-expressions are not well-constructed or variables allowed to get too large (or small, as the case may be.) Also, complex statements, functions, subroutines, and bankswitching all use the stack, so using excessively complex statements in a nested function or subroutine may overflow the stack into the variable space, causing weird bugs. However, stack overflows are still considered to be somewhat unlikely.

 

 

Back to Top

 

 

 

 

 

Assembly Language

Assembly Language Links

Instead of reposting the same links here, check out the useful Assembly Language Links on one of the Andrew Davie tutorial pages.

Did You Know?

It seems incude should come before includesfile in your code or it may not compile.

 

Example:

   include div_mul.asm
   includesfile bankswitch_SC.inc
   set romsize 8kSC

Back to Top

 

 

 

 

 

Atari 7800

The Atari 7800 is reverse-compatible with nearly 100% of Atari 2600 games. All bB games should run on the 7800. However, games that use the COLOR/BW switch may have problems. On the 7800, the switch is meant to be used as a PAUSE switch. On the 2600 this is a toggle or rocker switch, but on the 7800 it is a momentary pushbutton.

Most games will run exactly the same on either console because most do not use the COLOR/BW switch. But if necessary, bB can detect what console it is running on so you can account for this difference. When your game begins, temp1 will contain zero if the console is a 2600, or 255 if it is a 7800.

Note that you must check temp1 at the beginning of your game (it may be overwritten if you don't check it right away) and set a variable depending on temp1's value. A single bit is all you need.

 

Below is an example program by RevEng:

   rem ** 7800 detection won't work with the Harmony cart in menu mode 
   rem ** since the menu program changes these memory locations. 

   dim atari7800 = z

   rem ** This has to happen before a drawscreen or subroutine, or anything
   rem ** else that may obliterate temp1...

   atari7800 = temp1&1

   rem ** Uncomment the line below to test 7800 pausing in stella.
   rem ** Changing from color to BW will pause.
   rem ** Switching back to color will remain paused.
   rem ** Changing from color to BW will unpause.
   rem ** Switching back to color will will remain unpaused.

   rem atari7800 = 1

   rem ** For a 2600, atari7800 is now 0. For a 7800, atari7800 is now 1.

   scorecolor=$0A

   player0:
   %01111110
   %11000011
   %11000011
   %00000000
   %00000000
   %01100110
   %01100110
end

   player0x = 40 : player0y = 40

__Main_Loop

   COLUBK = 0
   COLUP0 = $0A

   player0x = player0x + 1

   drawscreen

   rem ** 2600 pause handling...
   if atari7800 = 0 && switchbw then goto __Pause_Game

   rem ** 7800 pause handling...
   if atari7800 = 1 && switchbw then atari7800 = %00000011 : goto __Pause_Game
   if atari7800 > 1 then if !switchbw then atari7800 = 1

   goto __Main_Loop



__Pause_Game

   COLUBK = $A4
   COLUP0 = $0A

   drawscreen

   rem ** This code should be at the bottom of the pause loop.

   rem ** 2600 pause handling...
   if atari7800 = 0 && !switchbw then goto __Main_Loop
   if atari7800 = 0 then goto __Pause_Game

   rem ** 7800 pause handling...
   if atari7800 = %00000011 && switchbw then goto __Pause_Game

   atari7800 = %00000111

   if switchbw then goto __Main_Loop

   goto __Pause_Game

 

 

Back to Top

 

 

 

 

 

Troubleshooting

Did You Know?

If you get a "complex condition detected" error message, you might have an ifthen that is missing a then. Using things in an ifthen that aren't supposed to be there can also cause this error. Check out the "Did You Know?" box here and here.

This section does not cover all possible problems, but it does explain some common programming errors and their resolutions.

There are two types of programming errors. One type of error is a compilation error, that is, an error is caught by the compilation process and a proper binary is not produced. Another type is when the compilation process is successful but the binary file doesn't work correctly. This section outlines those two types of errors and tries to help resolve them, or at least the most common of them.

 

 

Back to Top

 

 

 

 

 

Memory Maps

Note: playfieldpos is an internal system variable that controls which line to start drawing the top playfield block and when to stop drawing the bottom one. The scrolling routines update it automatically so it's not necessary to use it unless you need to know where the playfield is located.

 

 

 

Standard Kernel Memory Map

$80    player0x
$81    player1x
$82    player0colorstore
       missile0x
$83    missile1x
$84    ballx
$85    player0y
       objecty
$86    player1y
$87    player1color
       missile1height
$88    missile1y
$89    bally
$8a    player0pointer
       player0pointerlo
$8b    player0pointerhi
$8c    player1pointer
       player1pointerlo
$8d    player1pointerhi
$8e    player0height
$8f    player1height
$90    player0color
       currentpaddle
       missile0height
$91    paddle
       missile0y
$92    ballheight
$93    score
$94    
$95    
$96    scorepointers
$97    
$98    
$99    
$9a    
$9b    
$9c    temp1
$9d    temp2
$9e    temp3
$9f    temp4
$a0    temp5
$a1    temp6
$a2    rand
$a3    scorecolor
$a4    var0 
$a5    var1 
$a6    var2 
$a7    var3 
$a8    var4 
$a9    var5 
$aa    var6 
$ab    var7 
$ac    var8 
$ad    var9 
$ae    var10
$af    var11
$b0    var12
$b1    var13
$b2    var14
$b3    var15
$b4    var16
$b5    var17
$b6    var18
$b7    var19
$b8    var20
$b9    var21
$ba    var22
$bb    var23
$bc    var24
$bd    var25
$be    var26
$bf    var27
$c0    var28
$c1    var29
$c2    var30
$c3    var31
$c4    var32
$c5    var33
$c6    var34
$c7    var35
$c8    var36
$c9    var37
$ca    var38
$cb    var39
$cc    var40
$cd    var41
$ce    var42
$cf    var43
$d0    var44
$d1    var45
$d2    var46
$d3    var47
$d4    temp7
$d5    playfieldpos
$d6    A
       a
$d7    B
       b
$d8    C
       c
$d9    d
       D
$da    E
       e
$db    F
       f
$dc    G
       g
$dd    H
       h
$de    I
       i
$df    J
       j
$e0    K
       k
$e1    L
       l
$e2    M
       m
$e3    N
       n
$e4    O
       o
$e5    P
       p
$e6    Q
       q
$e7    R
       r
$e8    S
       s
$e9    T
       t
$ea    U
       u
$eb    V
       v
$ec    W
       w
$ed    X
       x
$ee    Y
       y
$ef    Z
       z
$f0    pfheighttable
       pfcolortable
       aux1
$f1    aux2
$f2    lifepointer
       aux3
       pfscore1
$f3    aux4
       pfscore2
       lives
$f4    aux5
       pfscorecolor
       lifecolor
$f5    statusbarlength
       aux6
$f6    stack1
$f7    stack2
$f8    stack3
$f9    stack4
$fa    [reserved for the stack]
$fb    [reserved for the stack]
$fc    [reserved for the stack]
$fd    [reserved for the stack]
$fe    [reserved for the stack]
$ff    [reserved for the stack]
 

Multisprite Kernel Memory Map

$80    missile0x
$81    missile1x
$82    ballx
$83    objecty
       missile0y
$84    missile1y
$85    bally
$86    SpriteIndex
$87    player0x
$88    NewSpriteX
       player1x
$89    player2x
$8a    player3x
$8b    player4x
$8c    player5x
$8d    player0y
$8e    NewSpriteY
       player1y
$8f    player2y
$90    player3y
$91    player4y
$92    player5y
$93    NewNUSIZ
       _NUSIZ1
$94    NUSIZ2
$95    NUSIZ3
$96    NUSIZ4
$97    NUSIZ5
$98    NewCOLUP1
       _COLUP1
$99    COLUP2
$9a    COLUP3
$9b    COLUP4
$9c    COLUP5
$9d    SpriteGfxIndex
$9e    
$9f    
$a0    
$a1    
$a2    player0pointer
       player0pointerlo
$a3    player0pointerhi
$a4    P0Bottom
$a5    P1Bottom
$a6    player1pointerlo
$a7    player2pointerlo
$a8    player3pointerlo
$a9    player4pointerlo
$aa    player5pointerlo
$ab    player1pointerhi
$ac    player2pointerhi
$ad    player3pointerhi
$ae    player4pointerhi
$af    player5pointerhi
$b0    player0height
$b1    spriteheight
       player1height
$b2    player2height
$b3    player3height
$b4    player4height
$b5    player5height
$b6    PF1temp1
$b7    PF1temp2
$b8    PF2temp1
$b9    PF2temp2
$ba    pfpixelheight
$bb    playfield
       PF1pointer
$bc    
$bd    PF2pointer
$be    
$bf    aux3
       statusbarlength
$c0    pfscorecolor
       lifecolor
       aux4
$c1    aux5
       pfscore1
       lifepointer
$c2    lives
       aux6
       pfscore2
$c3    playfieldpos
$c4    scorepointers
$c5    
$c6    
$c7    
$c8    
$c9    
$ca    temp1
$cb    temp2
       P1Display
$cc    temp3
$cd    temp4
       RepoLine
$ce    temp5
       P0Top
$cf    temp6
$d0    temp7
$d1    score
$d2    

$d3    
$d4    pfheight
$d5    scorecolor
$d6    rand
$d7    A
       a
$d8    B
       b
$d9    C
       c
$da    D
       d
$db    E
       e
$dc    F
       f
$dd    G
       g
$de    H
       h
$df    I
       i
$e0    J
       j
$e1    K
       k
$e2    L
       l
$e3    M
       m
$e4    N
       n
$e5    O
       o
$e6    P
       p
$e7    Q
       q
$e8    R
       r
$e9    S
       s
$ea    T
       t
$eb    U
       u
$ec    V
       v
$ed    W
       w
$ee    X
       x
$ef    Y
       y
$f0    Z
       z
$f1    spritesort
$f2    spritesort2
$f3    spritesort3
$f4    spritesort4
$f5    spritesort5
$f6    stack1
$f7    stack2
$f8    stack3
$f9    stack4
$fa    [reserved for the stack]
$fb    [reserved for the stack]
$fc    [reserved for the stack]
$fd    [reserved for the stack]
$fe    [reserved for the stack]
$ff    [reserved for the stack]
 

 

 

 

 

Glossary of Terms

This non-alphabetical glossary is a work in progress. More will be added to it over time.

 

 

     

    Constants, Variables, and Values

    Text by SeaGtGruff (adapted by Random Terrain)

    Constants and variables are like boxes that can hold things, and those things that are stored in the boxes are called values. In the Atari 2600, each box is normally the size of one byte, but you can also divide a box into smaller sections (bits or groups of bits), and you can combine two or more boxes to create a larger box.

     

    These boxes have addresses within the Atari's memory, but we give them names so they're easier for us to use. For example, "address $83" tells us the address of that particular box, but doesn't tell us what "lives" at that address. If we're going to be using that box to store the number of lives a player has remaining, then it's easier to write our program (and to read and understand it later on) if we call it something like "_Lives_Remaining" rather than "$83."

     

     

     

       

      Constants

      Text by SeaGtGruff (adapted by Random Terrain)

      A constant is a box that contains a value which will never change and that can't be changed once the box has been filled. For example, if we've taken a box, named it "_Three," and then put the number 3 in it, we can use the constant "_Three" in places where we want to use the number 3. That may sound silly, and that particular example iswhy not just use 3?but constants can be very useful in programming.

       

      Suppose you want the spaceship in your game to be yellow. You can define a constant named "_Ship_Color" and put the value for the color yellow in it. Then anywhere you want to refer to the ship's color you say "_Ship_Color." Later on you may decide you want the ship to be light blue instead of yellow. All you have to do is change the definition of "_Ship_Color" to be the value for light blue and it will change everywhere "_Ship_Color" was used in your programyou don't need to go searching for all the places it's used and change them individually (potentially missing some places).

       

       

       

       

      Variables

      Text by SeaGtGruff (adapted by Random Terrain)

      A variable is a box that contains a value which needs to be able to change while the program is running. For example, if we've named a box "_Lives_Remaining," then we can store the number of spare lives the player starts with in that variable. As the game is being played, we can reduce the value of "_Lives_Remaining" by 1 whenever the player loses a life, or increase it by 1 whenever the player earns an additional spare life.

       

       

       

       

      Values

      Text by SeaGtGruff

      Values come in two basic flavorsnumbers (numeric values) and characters (alphanumeric values, meaning letters, numbers, or other symbols). However, batari Basic doesn't have alphanumeric values, so all we need to understand in batari Basic are numeric values. A constant or variable is limited in the values it can contain. A single byte can hold any whole number from 0 to 255. A single bit can hold a 0 or a 1. So depending on the size of the box (how many bits wide it is), it can hold a value ranging from 0 to 1 (1 bit wide), or from 0 to 7 (3 bits wide), or from 0 to 255 (8 bits or 1 byte wide), or from 0 to 65535 (2 bytes wide), and so forth.

     

     

     

     

     

    Memory

    Text by SeaGtGruff

    A memory location is like a box with an address. Memory is used to store constants, variables, and the programming instructions that tell the Atari how the game works. Memory comes in two basic flavorsROM and RAM.

     

     

     

       

      ROM

      Text by SeaGtGruff (adapted by Random Terrain)

      ROM stands for "Read Only Memory." It is memory that can't be changed once it's been written to.

       

       

       

       

      RAM

      Text by SeaGtGruff (adapted by Random Terrain)

      RAM stands for "Random Access Memory" It is memory that can be changed. RAM is used to store variables and other information that needs to be able to change, such as a screen display. The Atari 2600 doesn't actually have "screen memory" and screen displays are often defined in ROM, but in its standard kernel, batari Basic sets aside some RAM to use as "screen memory" for the playfield.

       

      The Atari 2600 only has 128 bytes of RAM, but some game cartridges have extra (or expansion) RAM on them so more variables or more detailed screen displays can be used.

     

     

     

     

     

    Registers

    Text by SeaGtGruff

    Registers are special memory locations that are used for specific purposes by the Atari 2600. They are found on the three chips that make up the "brain" of the Atari:

    1. 6507 or CPU (which performs the game instructions).
    2. 6532 or RIOT chip (which supplies the RAM as well as the timer and interfaces with the input/output devices like the console switches and game controllers).
    3. TIA or "Television Interface Adapter" chip (which handles the video and audio).

     

    A few of these registerssuch as the accumulator and the X and Y registers inside the 6507 chipdon't have memory addresses, but we can store information in them by using specific instructions. But most of the other registersthose found inside the RIOT and the TIAare mapped to memory addresses so we can read from them or write to them. Most registers are like RAM addresses because their contents can change, but some registersparticularly many of the ones in the TIAare less than 8 bits, so they can hold only specific ranges of values. And a few of the TIA's registers don't even have any bits at allthey're called "strobe" registers that make something happen whenever we write to them. The TIA's registers come in two different flavorsread-only and write-only.

     

     

     

       

      Read-Only Registers

      Text by SeaGtGruff (adapted by Random Terrain)

      A read-only register can be read, but you can't write to it. The TIA's read-only registers are used to read collisions between the graphical objectsfor example, reading the CXM0P register lets you see if missile0 has overlapped (collided) with the player 0 sprite or the player 1 sprite. There are also read-only registers for reading the paddles or the joystick buttons.

       

       

       

       

      Write-Only Registers

      Text by SeaGtGruff (adapted by Random Terrain)

      A write-only register can be written to, but you can't read it. The TIA's write-only registers are used to draw the game on the screen, play sounds, or perform some specific action like clearing the collision registers or moving the sprites to the left or right. You can write a new value to a write-only registerfor example, writing a color value to the COLUPF register will tell the Atari what color to draw the playfield withbut you can't read a write-only register to see what value it's currently set to.

       

 

 

 

 

 

Subroutines

Text by SeaGtGruff (adapted by Random Terrain)

When you perform a gosub, the return address must be pushed onto the stack so the program can eventually return to where you called the subroutine from. The 2600 has a small stack to begin withonly 128 bytesand it coincides with the zero-page RAM that's used for variables, so you need to be careful about how much you use gosub (or JSR if you're using assembly). And batari Basic has even less usable stack space because it uses most of the zero-page RAM for what I call batari Basic's "system variables" (things like the player pointers, sprite x and y coordinates, etc.), the playfield RAM (if you aren't using the Superchip option in a bank-switching game), and the user variables (a through z). So that means you have to be extra careful about how much you use gosub in batari Basic. Note that it isn't the number of subroutines that's the issue, but rather the number of nested subroutines. So it's perfectly safe to call a subroutine, but you want to try to avoid calling a subroutine that calls another subroutine that calls another subroutine that calls another subroutine, etc.

 

If you're used to programming in a high-level language on a computer, you might not think twice about using a bunch of nested subroutines, but when programming for the Atari 2600and particularly when using batari Basicyou need to be mindful of how many levels of nested subroutines your code contains, otherwise the stack could end up overwriting some of your variables and causing program glitches. I think a batari Basic program can have up to 5 levels of nested subroutines before the stack begins to overwrite some of the variables, and you can nest more than 5 levels of subroutines if you aren't using any of the variables that would be overwritten-- but keep in mind that batari Basic also uses subroutines (for example, drawscreen is a subroutine). So it's probably best not to go beyond 3 levels of nested subroutines. And make sure that whenever you call a subroutine it will eventually do a return, otherwise the return address will get left on the stack. You can use pop to remove a return address from the stack, but that should only be done if you're sure you know what you're doing.

 

Calling a subroutine and then doing a return takes up more machine cycles than doing a straight goto. That generally isn't a problem unless you're working on a section of code that has really tight timing constraintsfor example, if you're writing your own display kernel in assembly then you might not want to do a JSR in the loop that draws the active lines (unless you've allowed for the extra time needed for the JSR and RTS). On the other hand, if your batari Basic program contains a large number of gosubs and returns, it might start to eat into your free cycles. And this is even more the case if you're using bankswitching and are doing gosubs and returns between different banks, because gosubs and returns between banks take up even more cycles than regular gosubs and returns. So it's a good idea to design your batari Basic programs to use goto instead of gosub wherever possible.

 

Of course, sometimes you do need to use gosub instead of gotoafter all, subroutines are an essential part of efficient programming. You don't want to repeat the same code in multiple places in your program if it would be more ROM-efficient to put that section of code in a subroutine and then gosub to it from different places in your program. But you should avoid using gosub in cases where it really isn't necessary, such as if the code in the subroutine is only called from one spot, or if the subroutine is so short that it would actually be more efficient to just duplicate that code wherever it's needed.

Back to Top

 

 

 

 

 

Useful Code and Tips

 

Useful Tools

bB Tools and Toys

Quickly convert hex, decimal, binary and more with the programming equivalents tool. There's also a playfield toy and a magic Firefox spell check box for REM statements.

 

Interactive TIA Color Charts and Tools

Includes an NTSC/PAL color conversion tool and Atari 2600 color compatibility tools that can help you quickly find colors that go great together (possibly saving you a lot of time and energy).

 

batari Basic Code Cleaner

Paste your bB program into the text box, generate the indented code, copy and paste the result in a post at AtariAge and the crucial indentation will be preserved.

 

PlayerPal

If you can't use Visual batari Basic to make sprites, try this online sprite editor.

 

Atari 2600 Label Maker

Produces authentic looking Atari 2600 Labels including the famous "Picture Label" using your own image and title. Related link: Atari Cart & Box Fonts

 

WinMerge

If you use Save As every time you make a major change to your program and your latest version won't compile, but you made enough changes that you don't want to start over from the last save, don't worry. You can use WinMerge to compare the two files. You can see the differences and quickly track down the problem.

 

PhotoFiltre

An image retouching program that makes the kind of arrows you might see in an Atari 2600 game manual. Select the Line Tool and click on the arrow checkbox.

Related Links

 

 

 

 

 

Table of Contents

Getting Started

IDE for batari Basic (VbB)

Useful AtariAge Links

Download the Manual

Test Your Games on a Real Atari

Sell Your Games

New to BASIC & Game Making?

Parts of a Program

Basic Questions

How does an Atari 2600 work?

What is a programming language?

What is BASIC?

What is a program?

What is a CPU?

What is a value?

What is binary?

What is a bit?

What is a byte?

What is a variable?

What is an alias?

What is ROM?

What is RAM?

Keywords, Constants, and Registers

Quick Reference

Things You Should Know

Indent!

Don't Use Line Numbers

Memory

Timing

White Space

Line Length and Other Limitations

DOS Compatibility

Miscellaneous

Comments (rem, semicolons...)

reboot

end

Variables

Variable Testing

let (optional)

const

dim

def

Bit Operations

Nybble Variables

Improved Nybble Variables

Bitwise (Logical) Operators

Fixed Point Variables

Ephemeral Variables/Registers

Temporary Variables

Labels and Line Numbers

Jumping Around

goto

ongoto

gosub

ongosub

return

pop

Decision Making (Brains of Game)

ifthen

Boolean Operators (&&, ||, !)

else

Loops

for-next

next

Random Numbers

rand

Data Statements and Arrays

Sequential Data [sdata, sread]

Colors

COLUBK

COLUPF

COLUP0

COLUP1

scorecolor

Atari 2600 TIA Color Charts

Objects

Player Graphics (Sprites)

player#height

Missiles

Ball

The Playfield

Playfield Variable Chart

pfres

pfrowheight

drawscreen

vblank

pfclear

pfpixel

pfhline

pfvline

pfscroll

playfieldpos

pfread function

score

scorecolor

scorefade

noscore

pfscore bars

BCD Compliant Number

dec

TIA Registers

NUSIZ0, NUSIZ1

CTRLPF

REFP0, REFP1

PF0

AUDVx, AUDCx, AUDFx

Collision Detection

Display kernel

 

DPC+ Kernel

Good News / Bad News

Harmony Cart Fix

Variables (DPC+)

The Stack (DPC+)

Score Colors (DPC+)

Player Graphics (DPC+)

dpcspritemax (DPC+)

playerxcolor (DPC+)

NUSIZx and REFPx (DPC+)

REFPx for Virtual Sprites

Virtual Sprite Masking

Missiles (DPC+)

Collision Detection (DPC+)

The Playfield (DPC+)

pfclear (DPC+)

DFxFRACINC (DPC+)

Playfield Resolution (DPC+)

pfscroll (DPC+)

Playfield Colors (DPC+)

Background Colors (DPC+)

vblank (DPC+)

Multisprite Kernel

Minikernels/HUDs

life counter/status bar

lives

lifecolor

statusbarlength

statusbarcolor

Writing Your Own Minikernel

Additional Kernels, Minikernels

Compiler Directives (set)

smartbranching

tv

romsize

optimization

kernel

kernel_options

readpaddle

player1colors & playercolors

no_blank_lines

pfcolors

pfheights

background

debug

legacy

Bankswitching

Superchip RAM

Sound

AUDVx, AUDCx, AUDFx

Tone Chart

Joysticks

Left Joystick Functions

Right Joystick Functions

Advanced Joystick Reading

2-Button Games

Console Switches

Numbers

Decimal Numbers

Hexadecimal Numbers

Binary Numbers

Negative Numbers

Math

Addition

Subtraction

Multiplication

Division

Modulus Operation

Functions

macro

Assembly Language (asm)

include

includes file

inline

Hacking bB .asm Files

Atari 7800

Troubleshooting

Compilation Errors

Preprocessor Errors

Compiler Errors

Assembler Errors

Branches out of Range

Syntax Errors

Duplicate Labels

Unresolved Symbols

2600 Basic Compilation Failed!

Error: invalid operator: goto

VERBOSE ERROR MESSAGE

Searching the Assembly File

Other Errors

Blank Screen

Players Use Score Color

Timing Problems

Earlier Games Don't Work Correctly

Upgrading bB Doesn't Fix Anything

Memory Maps

Standard Kernel Memory Map

Multisprite Kernel Memory Map

Glossary of Terms

Constants, Variables, and Values

Constants

Variables

Values

Memory

ROM

RAM

Registers

Read-Only Registers

Write-Only Registers

 

Expanded Index

Back to Top

 

Disclaimer

View this page and any external web sites at your own risk. I am not responsible for any possible spiritual, emotional, physical, financial or any other damage to you, your friends, family, ancestors, or descendants in the past, present, or future, living or dead, in this dimension or any other.

 

Home Useful Inventions Favorite Quotes Game Design Atari Memories Personal Pages About Site Map Contact Privacy Policy