Graphics: From BASIC To ML
As promised, this month I will introduce you to how Atari BASIC (and, indeed, virtually every other language available for the 8-bit Atari machines) "talks" to the Atari Operating System (OS). It is important first to note that Atari BASIC has no built-in graphics subroutines. All graphics support in these machines comes directly from the OS. Today, this is not much of a revelation: The Atari ST, Apple Macintosh, and Commodore Amiga machines all come complete with an OS that supports numerous sophisticated text and graphics functions. To use these features with any given language (BASIC, C, Pascal, or whatever), the language designer only needs to provide the user with a simple interface and then to let the OS do the real work.
When the Atari 8-bit machines first appeared, though, they were unique in providing this kind of interface in a family of low-priced machines. For example, the Commodore 64 has no graphics whatsoever built into its OS, and the Apple II (up until the IIGS) had only limited low-resolution capabilities. Generally, such machines are not very friendly things to write assembly language for, in marked contrast to the Atari 8-bit models. (Looking back, if we Atari loyalists have any regrets or complaints, they might be only that Atari never produced the software tools—for example, computer languages—to fully exploit the capabilities of the OS. Other companies produced those languages—such as the Pascal from Kyan Software and BASIC XL/XE from my employer, OSS—but they never achieved the success that a language from Atari could have.)
The above history lesson was not entirely an exercise in nostalgia. It leads us to a very important point: If Atari BASIC didn't have any graphics-oriented statements built in, you could still perform graphics fairly easily. Let's take a look at some Atari BASIC equivalents:
10 GRAPHICS mode
is actually the same as
10 TEMP = 12 : IF mode < 16 THEN TEMP = TEMP + 16 11 CLOSE #6 : OPEN #6, TEMP, mode, "S : "
Do you see what we did? The GRAPHICS statement is really just a special kind of OPEN. (Actually, I have left out consideration of the "+32" modes and have simplified things a bit, but for 99 percent of all programs the above will work fine.) In other words, all of the graphics modes of the Atari 8-bit computers are built into the OS ROMs (Read Only Memory chips).
The simplest BASIC statement to emulate is COLOR—you can leave it out altogether. We'll take a look at why when we get to PLOT in a moment. But POSITION isn't much harder (if we ignore GRAPHICS modes 8 and 24—see below).
330 POSITION xpos, ypos
can be emulated via
330 POKE 85, xpos : POKE 84, ypos
And, once POSITION has been dispensed with, PLOT becomes easy, also. (As you study these conversions, see if you can figure out why and how they need changing for GRAPHICS modes 8 and 24.)
281 PLOT xpos, ypos
281 POSITION xpos, ypos : PUT #6, mycolor
which, in turn, can be changed to
281 POKE 85, xpos : POKE 84, ypos : PUT #6, mycolor
Incidentally, mycolor is the color value you would otherwise have specified in the COLOR statement. And I am purposely using lowercase names for my variables to show that the names don't matter. Choose your own as you like. Similarly, then, you can make the following substitutions.
978 LOCATE xpos, ypos, what
can be written as
978 POSITION xpos, ypos : GET #6, what
or, by extension,
978 POKE 85, xpos : POKE 84, ypos : GET #6, what
The last one, for now, is just a bit more exotic:
330 DRAWTO xpos, ypos
is actually performed as if you had used
330 POSITION xpos, ypos 331 POKE 763, mycolor : XIO 17, #6, 12, 0, "S : "
or, in more detail,
330 POKE 85, xpos : POKE 84, ypos 331 POKE 763, mycolor : XIO 17, #6, 12, 0, "S : "
Why did I go to the trouble of breaking the BASIC statements above down into equivalent forms? Because these equivalent forms are much easier to translate into assembly language, and such translation is the main point of this article. For example, POKE and PEEK are the easiest BASIC statements to translate to assembly language. The reason? Much of assembly language consists of nothing more than fancy ways to do PEEKs and POKEs. In this short set of articles, I can't hope to teach you all the addressing modes of the 6502, so let me restrict myself to the simplest form.
For a first example, to emulate the BASIC statement
POKE 85, xpos
in 6502 assembly language, we need only code
LDA xpos STA 85
which can be read as "LoaD the A register with the contents of xpos and then STore the contents of the A register into location 85." That sounds simple enough, but the thing that makes the 6502 one of the more difficult CPU's to program for is the fact that the A register can hold, at most, one byte of information.
You don't see why that is a problem? Well, suppose we are doing work with GRAPHICS 8 or 24, where the horizontal (x) position can range from 0 to 319. A single byte can hold only values in the range 0-255. Oops. Ah, well, the analogy with Atari BASIC isn't so bad here, because the POKE command has the same restriction. It, too, can only affect a single byte. By extension, then: How do you change more than byte when using POKEs in BASIC? By using more than one POKE, right? So, in assembly language, you must use more than one STA instruction.
But if I even hope to be able to finish this set of articles, I will have to cut off this introduction to 6502 assembly language at this point. If you did not understand any of this article, I would suggest you learn more about BASIC before trying assembly language. If you are a good BASIC programmer and this left you looking for more, then I suggest that you look into some of the books I recommended in my July column.