I installed Stella (an Atari 2600 VCS emulator), downloaded the Atari 2600 BASIC cartridge and have been playing around with it for the past few days. If I'm going to do some Stupid Twitter Trick™ with it, I might as well know how it works, right?
And thus, this review.
Honestly, I don't think the Atari 2600 BASIC has ever had a fair review. It's pretty much reviled as a horrible program, a horrible programming environment and practically useless. But I think that's selling it short. Yes, it's bad (and I'll get to that in a bit), but in using it for the past few days, there are some impressive features on a system where the RAM can't hold a full Tweet and half the CPU time is spent Racing The Beam. I'll get the bad out of the way first.
Okay, here's how this works. I want to enter this line:
(Ah yes! The “left arrow” for assignment. Mathematicians rejoice!) Upon startup, the Atari 2600 BASIC cursor is white. This is important, because this tells you what mode you are in. Hit a key when the cursor is white, and you do the functions labeled in white above each key. To get an “A,” you hit the bottom center button on the left controller (the one with the arrow circling around it) until the cursor turns blue, then you can hit the upper left key on the left controller (labeled “STATUS + A IF”). It's a bit hard to see, but yes, that “A” is indeed blue.
To get the “←” symbol (it's the top right button on the left controller) you hit the bottom middle button the the left controller until the cursor cycles back to red, then hit the upper right button on the left controller. Then cycle the cursor back to blue to get the “A,” then cycle to red to get the “plus” and the “1” (top left button on the right controller).
That's probably bad enough on the real thing. On the simulated Atarti 2600? Okay, what key on my keyboard is the “cycle” key? Then what key is the “A” key? Here's what I have to type to get that line of code:
But to be honest, it's on par with other keyboards of the time and may be a bit better, having actual tactile feedback instead of a simple membrane. I'm also picky about keyboards so I'm always going to bitch about the keyboard unless it's an IBM model M.
And given that the Atari 2600 only has 128 bytes of memory, it's expected that the programs are going to be rather short. I at first thought that you had 64 bytes for the program, but no—it's 64 bytes for the program, variables and runtime expression evaluation! That actually surprised me. Even worse, running this program over and over again (spaces added for clarity):
1 A ← 1 2 B ← 2 3 PRINT A,B
No, really, that program, if run multiple times, will eventually exhaust all of memory. But not all programs leak memory. This program, if run over and over again (more on this little program in a bit):
1 D ← 1 2 HOR1 ← HOR1 + D 3 IF HOR1 = 0 THEN GOTO 5 4 IF HOR1 ← 99 THEN GOTO 2 5 D ← 99 - D + 1 6 GOTO 2
won't leak so much as a byte. Go figure.
is that each variabled used in the program
(and it doesn't matter if it's a predefined variable like
HOR1 or a user defined variable like
consumes three bytes out of the precious 64 bytes you get for your program!
On the plus side though,
unused variables (event the builtin ones) don't use space at all
(I figured this out by watching the RAM use in Stella).
The grahics are pretty pathetic as well.
There are two dots that can be manipulated.
The builtin variables
VER1 control the horizontal and vertical position for one dot;
VER2 are used for the other dot.
The colors are fixed.
and if the builtin variable
HIT is 1,
the two dots are in the same position.
The positions are themselves limited to 0 to 99, but that's because all variables are limited to the range 0 to 99. The values wrap though—add 1 to 99 and you get 0. Subtract 1 from 0 and you get 99.
Which leads us into the ugly.
there are no negative values—everything is unsigned.
And the values are all limited from 0 to 99.
This stems from a unique feature of the Atari 2600 CPU,
(a cheaper variation on the 6502).
That CPU can do math in either binary or binary-coded decimal
and the Atari 2600 BASIC uses the binary-coded decimal mode, which restricts the values from 0 to 99.
So while you don't have negative numbers,
you do in a way because of the way the math works.
99 plus 99 is 198,
but because the range is modulus 100,
the result is 98.
Add 99 again,
and you end up with 97.
I use this fact in the above program.
Line 5 negates
D—it converts 99 to 1,
or 1 back to 99.
1 to -1 and back again,
causing the dot to slowly crawl back and forth across the screen.
But now we finally arrive at what's good, or rather, what's amazing about this program.
First and foremost, it's an IDE.
Dispite it being only 4,096 bytes, there's a pretty credible, windowed(!) integrated development environment in there. If you look back at the keypad, you'll notice the first six buttons on the left controller are labeled:
Those are the various “windows” (and technically, they are windows, even if they don't overlap but are instead, stacked vertically on the screen) and the buttons there toggle the “windows” on and off.
The “STATUS” window (you can see it in the screen shot from the other day) shows memory usage (how many bytes, called “symbols”) and how fast the program will run (1, 2, 4, 8, 15, 30 and 60 are the speed values and they reflect how often the interpreter is run—once a second, twice a second, on up to 60 times a second). The “PROGRAM” window obviously contains the program (all nine lines if you have that many—and the IDE automatically numbers the lines for you even though it doesn't use them or store them—more on that below).
The “VARIABLES” window contains a list of the variables used in the program, listed as:
A is 1 HOR1 is 40 B is 2
“OUTPUT” is the text output window;
Leaving the “STACK” window, which is a misnomer actually. It's not a true stack, since there is no concept of “subroutine” in the Atari 2600 BASIC. You could think of it as “TRON” as it actually shows you the execution of each statment that is abolutely amazing! Imagine each line below being shown one at a time and you'll get a feeling for how this works. We'll be following line 5 from the above program (assuming D is 1):
D D← D←99 D←99-D D←99-1 D←98 D←98+1 D←99
One more example, to show that the Atari 2600 BASIC also follows mathematical precedence. Here, A is 1, B is 2 and C is 3. The line of code we're following is:
and during execution:
D D← D←A D←1 D←1+B D←1+2 D←1+2*C D←1+2*3 D←1+6 D←7
Strange as it sounds, this blew me away. I don't think I've ever seen anything like this. Sure, in debuggers where you execute a line at a time. Or in assembly language, instruction by instruction. But never substeps in expression evaluation. And of course, you can always step through the code with the “STEP” button. I just find it amazing that all of this, as simple as it is, can fit in 4,096 bytes of code.
How it stores the code internally is interesting. Most BASICs I'm aware of store the line number as part of the program, but here, that's not done. Take this program for example:
1 A ← 1 2 HOR1 ← HOR1 + 1 3 A ← A + 5 4 GOTO 2
Internally in memory, it's stored:
|F1||<end of line>|
|F1||<end of line>|
|F1||<end of line>|
|FF||<end of program>|
Not a line number in sight,
GOTO statements do a linear scan of the program
(a typical design choice of BASIC systems on 8-bit computers at the time)
but the end of each line is marked.
but whatever works I guess.
Variables are stored after the program, sequentially:
|EE||is (see below)|
As best as I can tell,
EE is used when displaying the variables on the “VARIABLES” window,
and probably means “is.” It's probably done that way to avoid a special case when displaying data—it can be treated the same when displaying the program.
I'm guessing there's not much space left what with the font data and code to support the IDE in addition to running a
(admittedly very simple) BASIC interpreter for special casing the variables.
As a “proof-of-concept” it's an amzing piece of work. As an actual product, yes, it sucks, mostly because of the limitations of the hardware. The ideas behind it are incredible though, and I think it's gotten short shrifted because of the limitations, which is sad. There is something to learn from here.
Update Wednesday, June 17th, 2015 at 1:56 AM
I almost forgot—the
IF statement is an expression!
You can do the following:
A ← IF B = 15 THEN 40 ELSE 99
A will be 40 if
B is 15,
A will be 99.
There aren't many languages I've used that have allowed this.