Share on Facebook Share on Twitter Email
Answers.com

Atari BASIC

 
Wikipedia: Atari BASIC
Atari BASIC
A rudimentary Atari BASIC program ready to run

A rudimentary Atari BASIC program ready to run
Developer(s) Shepardson Microsystems
Stable release Revision C / 1983
Operating system Atari 400/800/XL/XE
Type BASIC
License Copyright © 1979 Atari Inc. Proprietary

ATARI BASIC is a ROM resident BASIC interpreter for the Atari 8-bit family of 6502-based home computers. The interpreter originally shipped on an 8 KB cartridge; on later XL/XE model computers it was built in, and loads by default when the machines are booted without other cartridges in place. The complete commented source code and design specifications of ATARI BASIC were published as a book in 1983.[1] This marked the first time source code was made available for a commercial language.[citation needed]

A small program (in Spanish) using GRAPHICS 2 mode

Contents

Background

The machines that would become the Atari 8-bit family had originally been developed as a second-generation games console intended to replace the Atari 2600. Ray Kassar, the then-new president of Atari, decided to challenge Apple Computer by building a home computer instead. This meant Atari needed the BASIC programming language, then the standard language for most home computers.

Atari did what many of the other home computer companies did: they purchased the source code to the MOS 6502 version of Microsoft 8K BASIC intending to port it to run on their new machines. But the name was something of a misnomer, as the 8K referred to its original size on the Intel 8080's instruction set. On the 6502's inherently less dense instruction set the language is somewhat larger, around 9K. Additionally, Atari felt that they needed to expand the language somewhat to add better support for the specific hardware features of their computers, similar to what Apple had done with their Applesoft BASIC. This increased the size again, to around 11K. Atari had designed their ROM layout in 8 kB blocks, and paring down the code from 11 to 8 kB turned out to be a significant problem. Adding to the problem was the fact that the 6502 code supplied by Microsoft was undocumented.

Six months later, they were almost ready. But Atari had a deadline with the Consumer Electronics Show (CES) approaching and decided to ask for help.

Shepardson Microsystems

The 8kB ROM Atari BASIC cartridge for Atari 8-bit computers.

In September 1978 Atari asked Shepardson Microsystems (SMI) to bid on completing BASIC. Shepardson had written a number of programs for the 6502-based Apple II, and were in the midst of finishing a new advanced BASIC for the Cromemco S-100 bus machines (Cromemco 32K Structured BASIC). SMI examined the existing work and decided it was too difficult to continue paring it down; instead they recommended developing a completely new version that would be easier to fit into 8 kB. Atari accepted the proposal, and when the specifications were finalized in October 1978, Paul Laughton and Kathleen O'Brien began work on the new language.

The result was a rather different version of BASIC, known as ATARI BASIC. In particular, the new BASIC featured string handling very different than Microsoft's version, patterned like Data General's BASIC rather than Microsoft's version which used strings similar to those from DEC BASIC.

The contract specified a delivery date by April 6, 1979 and this also included a File Manager System (later known as DOS 1.0). Atari's plans were to take an early 8K version of Microsoft BASIC to the 1979 CES and then switch to the new Atari BASIC for production. Thanks to a bonus clause in the contract, development proceeded quickly and an 8K cartridge was available just before the release of the machines. Because of the speed in getting Atari BASIC, Atari ended up taking it to CES instead of the pre-production Microsoft BASIC.

Shepardson's programmers found bugs in the first-pass review and managed to fix some of them, but Atari had already committed BASIC to manufacturing. This initial buggy version became known as Revision A.

  • Revision A - First Atari BASIC cartridge. 8kB ROM.
  • Revision B - Fixed all of the major bugs in Revision A, but introduced a leaking memory bug. Found built-in on the 600XL and early 800XLs. No cartridges.
  • Revision C - Eliminated memory leak in Revision B. Found on later 800XLs, the 800XLF, XEGS and all XE computers. Limited cartridge production run.

The version can be tested by entering the command PRINT PEEK(43234) at the READY prompt. A result of 162 signifies Revision A, 96 means Revision B, and 234 means Revision C.

Description

Program editing

What happens when a line containing a syntax error is entered

Atari BASIC uses a line-oriented editor, in common with most BASICs of the era. Unlike many BASICs, however, Atari BASIC immediately checks the line for syntax errors. If a problem is found it re-prints the line, highlighting the text near the error. This makes catching errors on the Atari much easier than on other editors, as most BASICs would not display most errors until the program was later RUN, when the new line would no longer be fresh in the author's mind.

When not running a program, Atari BASIC is in immediate mode, where lines can be entered (with a line number) to add a line in the program or modify an existing one, or commands can be entered (without a line number) that are executed immediately. Unlike most other BASICs, however, Atari BASIC allows all commands to be executed in both modes. For instance most BASICs only allow LIST to be used in immediate mode, while Atari BASIC also allows it to be used inside a program. This was sometimes used as part of a way to produce self modifying code.

Program lines can be up to three screen lines of 40 characters, so 120 characters total. The cursor can be moved freely in these lines, unlike in other BASICs where to get "up" a line one has to continuously scroll leftwards until the cursor is wrapped at the left margin (and similarly to go down when wrapping at the right margin) – though that worked too. The OS handles tracking whether a physical line flowed to the next on the same logical line; the three-line limit is fairly arbitrary but keeps lines below 128 characters and so probably reduces the chances of buffer overflow.

It is actually possible to move the cursor anywhere on the screen, and it will wrap on all sides. Hitting "enter" will submit that (logical) line to the tokenizer. So, in the example pictured above (with "PRUNT", all that will be required for the fix is to move the cursor over the U, type I (the editor only has an overwrite mode) and then hit Enter. This was quite a frequent editing technique for, say, renumbering lines, since there is no built-in renumbering facility but quickly one could learn to, say, overwrite the numbers on a set of lines then just hit return repeatedly to enter them back into the program. Indeed, a slightly cryptic but essentially simple idiom allows this to be done by the program itself as it is running, producing self-modifying code. This is not an artifact or cheat around the system but inherent in the combined behavior of the editor and tokenizer.

Character set

The Atari variation on ASCII, called ATASCII, has 128 (8016) characters mostly corresponding to ASCII but with a few exceptions. All characters have printable forms unlike ASCII where codes 0-31 (0-1F16) were "control codes" that performed special functions such as requesting a paper feed or ringing an attention bell. Characters 128-255 (8016-FF16) were displayed as the inverse video of characters 0-127 (0016-7F16). Variable names had to be composed of upper-case alphabetic (65-90, 4116-5A16) and numeric (48-57, 3016-3916) characters, starting with an alphabetical character, and for strings terminating with a dollar sign (36, 2416).

The character set has a full ensemble of lower case characters and some graphics characters, but it is frequent to see programs mostly in upper case. This may be simply because of the conventions of the time, previous machines not having lower case; or that some devices such as daisy wheel printers may not have lower case, or that the lower-case font was not very attractive, in particular struggling to squeeze ascenders and descenders into the 8×8 fixed grid used to define each glyph. On Revision C ROMs there is an alternative font including characters with diacritics, intended for European users, but this is rarely used. Adding user-defined fonts is relatively easy and each took 1 kilobyte; a one-byte is used to indicate the start page of a font (though only one could be used at a time without machine code display list interrupts to change the font midway down the screen). Similarly on later GTIA graphics processors, a little-known 8×10 font mode exists, where two lines top or bottom of a character are assumed blank, thus keeping the actual glyphs to 8×8 but allowing ascenders or descenders without these characters touching those above or below; this is very rarely used, partly because dot matrix printers can not easily support it. The ease of implementing other fonts means many were freely available, with font editors and so forth too.

The tokenizer

Like most BASIC interpreters, Atari BASIC uses a token structure to handle lexical processing for better performance and reduced memory size. The tokenizer converts lines using a small buffer in memory. The token output buffer (addressed by a pointer at LOMEM – 80, 8116) was 1 page (256 bytes) long, and any tokenized statement that is larger than the buffer would generate an BASIC error (14 – line too long). Indeed, the syntax checking described in the "Program editing" section is a side-effect of converting each line into a tokenized form before it was stored. Sinclair BASIC uses a similar approach, though it varies between models.

The output from the tokenizer is then moved into more permanent storage in various locations in memory. A set of pointers (addresses) indicates these locations: variables are stored in the variable name table (pointed to at VNTP – 82, 8316) and the values are stored in the variable value table (pointed to at VVTP – 86, 8716). Strings have their own area (pointed to at STARP – 8C, 8D16) as do the runtime stack (pointed to at RUNSTK – 8E, 8F16) used to store the line numbers of looping statements (FOR...NEXT) and subroutines (GOSUB...RETURN). Finally, the end of BASIC memory usage is indicated by an address stored at MEMTOP – 90, 9116) pointer.

By indirecting the variable names in this way, a reference to a variable needs only two bytes to index its entry into the appropriate table; the whole name does not need to be stored each time. This also made variable renaming trivial if the program is in storage, as it is simply a case of changing the single instance of its name in the table: indeed, obfuscated code can be produced for a finished program by renaming variables in the name tables – possibly all to the same name. This doesn't confuse the interpreter since internally it is using the index values not the names. Of course, new code will be difficult to add because the tokenizer has to translate names to indices, and can get confused if names were not unique (though it was OK to have names in both the string and 'variable' namespaces, e.g. HELLO = 10 and HELLO$ = "WORLD".)

Atari BASIC uses a unique system for abbreviating reserved words. Unlike Microsoft BASIC where there were a few "pre-rolled" short forms, (like ? for PRINT and ' for REM) Atari BASIC allows any keyword to be abbreviated using a period. So L. will be expanded to LIST. To expand an abbreviation the tokenizer will search through its list of keywords (see below) and find the first that matched. To improve the probability of the programmer correctly guessing an abbreviation, and to save typing, the list of reserved words is sorted to place the more commonly used commands nearer the top. REM is at the very top, and can be typed in just as .. This also sped lexical analysis generally. In comparison, Microsoft BASIC uses separate tokens for their few short forms, whereas Atari BASIC has only one token for each keyword – when the program is later LISTed it will always write out the full words (since only one token represents all possible forms).

There were two exceptions to this: PRINT had a synonym, ?, and LET had a synonym which was the empty string (so LET A = 10 and A = 10 meant the same thing, assuming that "=" at this point of the tokenization meant assignment not equality). These were separate tokens, and so would remain as such in the program listing.

Some other contemporary BASICs had variants of keywords that included spaces (for example GO TO). Atari BASIC did not. The main exceptions here were keywords for input/output (see section below) such as OPEN # and PRINT #; it rarely occurred to many programmers that the # was actually part of the tokenized keyword and not a separate symbol; it may be that the BASIC programmers kept the form # to conform with other BASICs (The syntax derives from Fortran), though it is entirely unnecessary, and probably a hindrance, for tokenizing.

Expanding tokens in the listing could cause problems when editing. The Atari line input buffer was three lines (120 characters); after that a new "logical line" was automatically created. This didn't matter much for output but it did for input, as the operating system would stop returning characters to the tokenizer after the end of the third line. But using abbreviations when typing in a line could result in an expanded line that was significantly longer than three lines (and, a more minor concern, some white space could be omitted e.g. PRINT"HELLO" would be detokenized as PRINT "HELLO". If one then wanted to edit the line, one would need to replace the expanded commands with their abbreviations to be able to submit them back to the tokenizer.

Also, literal line numbers in statements were calculated at runtime using the same math routines as other BASIC functions. This calculation allowed routines to be referred to by variables, for instance GOTO EXITOUT, as long as one remembered to initialize EXITOUT. This was much more useful than it might sound; tokenized variables were stored in a six-byte format only once in memory (in the VVTP), and the GOTO target was to by just the two-bytes index into VVTP, whereas explicit line numbers took up the six bytes needed for a floating-point (FP) number every time they appeared in the program. (The design choice to store them as FP is discussed later.) If many parts of a program jumped to a single line number, which is fairly common in BASIC, replacing the explicit line numbers with variables could save considerable amounts of memory. Because the line numbers were stored as FP, hackers could change line numbers to be non-integer values, as part of deliberate obfuscation.

String handling

Atari BASIC differed dramatically from Microsoft-style BASICs in the way it handled strings. In BASICs following the Microsoft BASIC model, strings are special types that allow for variable length and various operations. Atari BASIC has no strings of this sort, instead using arrays of characters, rather like Fortran. This allowed the BASIC language programmers to remove all the special-purpose code needed for handling dynamic resizing of strings, reusing instead the code already being used to handle arrays of numbers.

Of course, strings are not used by end programmers in the same way as arrays of numbers – at least not normally – so Atari BASIC also included a selection of commands for "slicing" up arrays. A$ referred to the entire string, whereas A$(4,6) "sliced" out the three characters 4, 5 and 6. In theory, this was a more elegant solution than Microsoft BASIC's LEFT$, MID$, and RIGHT$ solution, as this syntax replaces three separate commands with a single one.

Although this simplification reduced the size of Atari BASIC and offered some theoretical performance benefits, it also made it much more difficult to port BASIC programs onto the Atari, arguably more so than any other difference. Users would have to scan programs for instances of LEFT$, et al., and replace them with slicing commands. Also, strings were allocated a fixed size using the DIM command and the size could not be changed after. This generally meant the string sizes were over-allocated by the programmer to a guesstimate of their likely maximum size.

A common trick was to assign MYSTRING$(1) to MYSTRING$(2), this would copy the same character from the first in the string into every position in the string, relying on the order of copying used in the Atari BASIC array copy routine – it was essentially undefined behavior.

Strings in Atari BASIC were limited to one-dimensional arrays, so arrays of strings had to be implemented by the programmer. For short strings of approximately the same length, this was generally done by padding the strings so they are all the same length. According to Bill Wilkinson, a programmer at SMI, the decision to go with strings larger than 255 characters in size made string arrays unfeasible.

Input/Output

CIO overview

The Atari OS included a subsystem for device input/output (I/O) known as CIO (Central Input/Output). All I/O went through a central point of entry (E45C16) passing the address of an I/O Control Block (IOCB), a 16-byte structure that defined which device was meant, and what kind of operation (read, write, seek etc). There were 8 such IOCBs, allocated at fixed locations in page 3 of memory. Most progams therefore could be written independently of what device they were using, as they all conformed to a common interface – this was very rare on home computers at this time. Devices such as S: (the screen) and E: (the editor) did have special operations, for example to draw graphics or to ask for line input (in fact E: was pretty much a combination of S: and K:, the keyboard input device), but these were done in a uniform way and new device drivers could be written fairly easily that would automatically be available to BASIC and indeed any other program using the Atari OS, for example to provide support for new hardware devices such as mouse pointers, or software devices such as an 80-column display (using typically a 4×8 pixel font). Existing drivers could be supplanted or augmented by new ones since the driver table was searched newest-to-oldest, so a replacement E:, for example could displace the one in ROM to provide an 80-column display for example, or to generate a checksum whenever a line was returned – this technique was used for some of the program listing checkers that provided a checksum for each line.

CIO access in BASIC

Atari BASIC supported CIO access with reserved words OPEN #, CLOSE #, PRINT #, INPUT #, GET #, PUT #, NOTE #, POINT # and XIO. There were routines in the OS, for example for graphics fill and draw, that were not available as specific BASIC keywords, but could be obtained through XIO. Since they were already provided in the OS, one can only assume the BASIC programmers ran out of time or space to add them to the BASIC tokenizer: they are available in variants such as Turbo-BASIC XL, and in other languages.

Up to eight IOCBs could be in use at a time, numbered 0 through 7 (0 was, by default, the editor E:). The BASIC statement OPEN # was used to prepare a device for I/O access:

REM Opens the cassette device on channel 1 for reading in BASIC
OPEN #1,4,0,"C:MYPROG.DAT"

Here, OPEN # means "ensure channel 1 is free" (an error otherwise results), call the C: driver to prepare the device (this will set the cassette tape spools onto tension and advance the heads keeping the cassette tape player "paused"; the 4 means "for read" (other codes were 8 for write, 12 = 8 + 4 for "read-and-write", and so forth), and the zero provides extra information, here not used. The string gives the device name and optionally a filename. Devices could have numbers (mainly disks, printers and serial devices, so "P1:" might be a plotter and "P2:" might be a daisy-wheel printer); "R1:" may be a modem and "R2:" an oscilloscope (R for RS-232, provided by an add-on interface and not built into the OS).

Reserved IOCBs in BASIC

BASIC disallowed access to IOCB 0 (the editor, E:) and reserved IOCB 7 for printing and cassette operations using the built-in commands LPRINT, SAVE, LOAD, CSAVE, CLOAD, though there was nothing to stop printers or the cassette being used on other channels too. IOCB 6 was used for accessing the Screen device (S:) in graphics modes for drawing lines, filling shapes and so on. Common devices were C: for the cassette, D: for disks, P: for printers and so on. SAVE and LOAD output the tokenized form of the BASIC program, LIST and ENTER the text source.

For the other CIO functions, BASIC used the XIO statement for access. This essentially just primed an IOCB and called the CIO entry point; any of the other commands could be achieved with XIO, but its form was not very friendly for BASIC users. included screen functions and serial (RS-232) functions (on R:) as well as disk operations like format or deleting a file.

It could be argued that some statements such as LPRINT, CLOAD and CSAVE were redundant; the ROM space used by these routines could perhaps have been better used to implement other things, and it put IOCB 7 out of bounds (that being said, very few programs needed to use more than a few IOCBs).

Error Handling

I/O routines returned error codes of 128-255 (8016-FF16) via the processor's Y register and setting the carry flag of the processor. Setting the carry flag is a neat trick since the caller can immediately branch-on-carry (BRC) to an error routine, a brief, quick and relocatable 6502 instruction (2 bytes, 2 cycles), without having to test Y for the (we hope) normal case where there is no error.

As with other aspects of the CIO, error codes were common across devices but could be extended for particular devices. Error handlers could thus be written quite generically, to fail gracefully, maybe put out a message, ask the user whether to retry, propagate the error, and so on.

There were no user-friendly messages for standard error codes in the OS itself. They would be interpreted by the application.

Atari BASIC (and other languages) thus had the freedom to return error codes less than 128, and these meant different things in different languages. There was nothing to stop a perverse implementer using error codes of 128 or above, but no incentive to do so.

Graphics

Hardware support

The Atari hardware had (for its time) quite a sophisticated graphics system, stemming from its basis in video games consoles. Unlike many other home computers of the time, the graphics "mode" – the size of pixels and the number of colors that could be displayed – was not fixed but was described on a line-by-line basis in a small microcontrol language to create a display list. Each entry in this list described one or more lines on the TV display, top-to-bottom. A dedicated graphics microprocessor, "ANTIC", read these out during the horizontal blanking interval to determine how to display the next TV line. Lines could be narrow (256 pixels wide at highest resolution), normal (320 pixels) or wide (384 pixels). Characters were 8×8 and one display list entry would thus describe 8 TV lines, the ANTIC would keeping a counter (shift register) of which line in the font to read the pixel data from for each of those lines, thus only requiring one entry for the whole 8 lines in the display. Similarly for larger, coarser graphics modes, the ANTIC chip kept track of the information so that it would display the data on more than one TV line.

Later (XL and XE) machines had an additional graphics processor called CTIA (later GTIA) offering additional modes, providing additional graphics modes, but for the purposes of discussing Atari BASIC these do not affect the basic description as they were programmed much the same way.

Sprites (Player/Missile Graphics)

A hardware sprite (computer graphics) system was also handled by ANTIC. A sprite was essentially a character 8 pixels wide and 256 TV lines long (note this did not vary with the graphics mode), in one color. (The sprite actually extended the whole height of the display including the screen border but the top and bottom were just a solid color.) It could be considered an extremely tallcharacter in a font. ANTIC would automatically overlay the sprite "stripe" at a horizontal position, so that where there was a 0 bit in the sprite definition the normal graphics pixel color would be displayed, but where there was a 1 bit the sprite color would be displayed. Moving the sprite vertically was achieved by block moving (or rotating) its definition in memory, which was reasonably easy in machine language although the 6502 processor has no built-in block memory move instruction.

Although these sprites had quite severe limitions because of their width and color restrictions, careful use of them could make graphics programming, particularly games, significantly simpler since it reduced the need to manipulate display memory for fast-moving objects (such as the "player" and his weapons in a shoot 'em up fame (in fact the official name of the sprite system was "Player/Missile Graphics"). In fact There were four sprites, but they could be overlapped making multi-colored sprites, at the expense of reducing the number of sprites available for other uses.

The ANTIC microprocessor had many "registers" by which colors could be set, and the horizontal position (and enabling) of the sprites, and so forth. For example, for a four-colour graphics mode, only four colours could be displayed, but these could be chosen from any of the 256 in the physical color palette. For 2-color modes there was actually only one color, which could be displayed at two levels of luminance. Data in memory described the pixel colors as "logical colors", for example for a 4-color mode two bits of a byte (with values 00, 01, 10 or 11) would describe the color for a pixel, so one byte stored four pixels and ANTIC rendered them from a shift register. For character modes, the data in memory simply described the index into the character set, and ANTIC stored the individual pixel data for the character in a shift register.

The display list could specify for each line the address in memory from which to fetch the data (with some trivial memory alignment restrictions), but if this was not specified then ANTIC would fetch the data from the next address in memory from where it finished reading the previous line.

Interrupts

Short sections of machine language code could be executed during the horizontal blanking interval, and this was typically done to change the values in the color registers, horizontal sprite positions and so forth thus giving the appearance of more colors or more flexible sprites than the hardware provided ab initio. This machine code had to be very short as there were not many clock cyles available during each horizontal blank. These routines were known as DLIs (display list interrupts) but were simply off limits to Atari BASIC as it would have been far too slow to perform even the simplest tasks. Strictly these should be called "DLI routines" but were usually just called "DLIs".

During the vertical blanking interval, a much longer interval, another interrupt was generated and the Operating System hooked into this to perform some housekeeping tasks. Again, this was not available to Atari BASIC directly, although with some manipulation and severe restrictions (because BASIC was not designed to be re-entrant) it was possible for a VBI (vertical blank interrupt) routine to call a BASIC routine.

Operating system support

The operating System provided several standard "Graphics modes" by which it set up a display list automatically, and allocated memory, at the top end of free memory. These provided a range of graphics modes including text modes, graphics modes and mixed text-and-graphics modes. It was only these predefined modes that were available to Atari BASIC.

The lack of an OS routine for a general-purpose memory move routine perhaps exhibited in artifacts of the graphcs design. For example, once a graphics channel had been opened, it was not possible (or at least easy) to move it down in memory so that other memory could be reserved above it, which meant that generally a program would allocate "more than enough" memory above the high memory pointer (HIMEM) then set the graphcis mode (with the GRAPHICS statement) to have the operating system allocate memory for the display below the new high water mark.

Most of ANTIC's registers were write-only, their values could not be read (or rather they could be, but were meaningless or returned different values from those written as they were multiplexed). The Operating System kept copies of the values written in "shadow registers" in pages 0 and 2 of memory (page 1 was the hardware stack on 6502 processors), thus allowing programs to read the values. The values written here were rewritten to the ANTIC registers during the vertical blank interrupt.

The operating system provided access to the graphics in two ways: by allowing direct reads and writes (in Atari BASIC, through the PEEK and POKE commands to the memory being used to hold the graphics (by making available the address of the start of that memory in a well-known location), and to the shadow registers, and also by providing a CIO device, "S:", through which CIO commands could be issued. The S: device supported the general-purpose XIO command used to implement PLOT, DRAWTO and FILL (unfortunately the last was not exposed to Atari BASIC, and was also rather tricky to get right at the best of times, as it used a rather primitive scanline fill that filled lines left-to-right, bottom-to-top but stopped as soon as a boundary was met, rather than providing a full flood fill).

In a way there was some confusion and overlap here in the design. For example, the CIO NOTE and POINT commands could be considered analagous to reading and writing the position of the cursor, but instead they had a separate interface through well-defined memory locations. Thus the exposure of the graphics API to BASIC and other languages was perhaps not as orthogonal and device-independent as it could have been.

Atari BASIC support

Atari BASIC supported graphics using the statements COLOR, SETCOLOR, CLEAR, PLOT, DRAWTO, LOCATE and GRAPHICS.

Because of the support provided by the operating system, Atari BASIC implemented most of its graphics statements as simple calls to those routines or just set the memory registers for the cursor position and so on. In many cases it simply left programmers to use PEEK and POKE statements. It could be argued that some statements such as SETCOLOR were not only redundant but confusing, since they simply set one color value in a shadow register and could be as easily, and more quickly, done with a POKE command; the ROM space used by these routines could perhaps have been better used to implement other things.

The lack of a FILL command is a notable omission considering that the routine, however primitive, was available in the operating system. It could be achieved with the general-purpose XIO command, but was rather fiddly:

REM The co-ordinates of the corners of the fill quadrilateral have to be set up
REM before calling XIO, using POKE into the IOCB. This is quite a trick because
REM it's not easy to find out where the IOCB is. Anyway, then we do:
XIO 18,#6,12,0,"S:"
REM XIO # = Extended IO.
REM 18    = Fill (17=Drawto).
REM #6    = On Channel 6, mapped to the graphics screen device.
REM 12    = Read/write.
REM 0     = Redundant (unused).
REM "S:"  = Logical device, used only for OPEN and some disk
REM         commands with a target such as for a RENAME
REM         Redundant here but used by convention

There was no BASIC support for sprites, although they were not particularly difficult to program in BASIC using PEEK and POKE, but this could not be done particularly fast in, say, games. Similarly, setting up a custom display list could be done, but was rather difficult, and was far more easily and effectively done in machine language. Sprite data could be defined using a DATA statement, and then POKEd into memory. However, scrolling a sprite vertically, for example, was not quick in BASIC as there was no "block memory move" statement and required a slow FOR loop of PEEKs and POKEs.

Hardware support

In comparison to the BASICs of some competing machines at the time, Atari BASIC had good built-in support of sound, (SOUND statement), graphics (GRAPHICS, SETCOLOR, COLOR, PLOT and DRAWTO) and peripheral units like joysticks (STICK, STRIG) and paddles (PADDLE, PTRIG). Other home computer users were often left with cryptic POKEs for such programming.

That being said, the parameters for many of these commands were cryptic, and essentially little better than machine code. SOUND took four numeric parameters for pitch, tone, volume and channel (the Atari 8-bits had 4-channel sound); the GRAPHICS statement took three to handle the numerous graphics modes, SETCOLOR and COLOR each took a number of parameters with different meanings depending on the graphics mode and often which did not match between the two, and so forth. It may be an example of Conway's law: clever designers made excellent hardware, by and large following a common model (memory-mapped register addressing for ANTIC, GTIA and Pokey, for example), but the lack of the teams' interaction made them work in curiously different ways. One may wonder why it would be thought so important to include two key words for examining the state of paddles – something that could be done easily with a single PEEK and indeed in every respect more efficiently than a PADDLE statement – yet not have a FILL command that was already coded in the OS and would have been uniquely advanced for the BASICs of the time.

Similarly, advanced aspects of the hardware such as sprites were completely out of bounds for BASIC programmers, and the lack of access to timers made sound programming difficult, particularly because North American machines ran on different clock speeds from the rest of the world (basically because they were tied to the speed of the television system).

Performance

Atari BASIC was slower than other BASICs, sometimes by a surprising amount given the higher speeds of the underlying hardware. Most of these problems stemmed from two particularly poorly implemented bits of code.

One was a side-effect of the way that Atari BASIC recalculated line numbers as the program was being run. This meant that a GOTO had to run a small amount of additional code in order to find the line to jump to. This would normally be a minor issue, but the same code was also used to implement the "reverse jump" at the end of FOR...NEXT loops, dramatically lowering overall performance of these very common structures. It is fairly obvious that a line number can be stored in a 16-bit integer, but presumably the designers chose to store it that way for other design reasons.

Atari BASIC didn't support integer variables, so all numeric operations were in floating point. Atari BASIC relied on the Atari OS's built-in floating point routines (BCD notation), which were slow. Most of this was due to a particularly poor implementation of the multiply code that was used throughout the math libraries. This was arguably not a problem of the language itself but the underlying OS, but it added to the general poor performance.

The MOS 6502 processor had a special mode for dealing with BCD (the SED and CLD instructions to treat each 4 bits of a byte as a BCD digit), and perhaps that was particularly attractive to the designers for implementing floating point as BCD. The now almost universal IEEE 754 standard of representation of floating point numbers was still at the design stage when the Atari 8 bit family and its contemporaries first came to market, so the design of an FP implementation was very much up to the OS or BASIC designer.

Several commercial and shareware BASICs were available on the platform that addressed some or all of these issues, resulting in performance that was 3 to 5 times faster than the Atari version. Using these BASICs, the Atari was one of the fastest home computers of its era.

Atari later sold a diskette-based version of Microsoft BASIC, Atari Microsoft BASIC, and later managed to fit it onto a cartridge as well, but no compiler or runtime was available for redistribution.

Advanced techniques

Despite its small footprint (8 kilobytes), Atari BASIC had some features that gave it some powers of more-advanced versions of BASIC.

Functions

Atari BASIC had no implementation of user functions. However, programmers could simulate user functions because of the way the GOSUB command could reference a variable. For example, a programmer could start a subroutine at line 10000 and have the program initialize a variable with that number, e.g. LET TEST = 10000. The calling code could then initialize some mutually understood variables and use the statement GOSUB TEST to invoke the subroutine. The subroutine starting at line TEST would then do its operation on the predetermined variables and put return results into variables available after RETURN.

Includes

Atari BASIC could import lines of code and merge them into a single program as long as the line numbers didn't conflict. The code to be merged was written to a medium in textual form using the LIST command, and could be put back into the program with the ENTER command. So the stream of text on the medium was, from the BASIC interpreter's point of view, no different from had it been typed at the keyboard or any other input device.

By carefully using blocks of line numbers that did not overlap, programmers could build libraries of subroutines (simulating functions as above) and merge them into new programs as needed.

Embedded machine language

Unlike, for example, the BBC Microcomputer, Atari BASIC did not have a built-in assembly language. Machine code was generally stored as bytes in strings. Machine code functions were invoked via the USR statement, which worked in much the same way as GOSUB, but with fewer guarantees. (Cross your fingers.)

String variables could hold any of the 256 characters available in the ATASCII character set and thus each byte of memory reserved for a string variable could hold any number from 0 to 255. Short relocatable 6502 machine language routines could be converted to ATASCII characters and stored as a string variable. The machine language routine could be called as a function with the USR command specifying the address of the string variable as the location in memory to execute. For example, if the machine language code was stored in a string named ROUTINE$ it could be called and parameters passed to it with ANSWER=USR(ADR(ROUTINE$),VAR1,VAR2). Parameters were pushed onto the hardware stack as 16-bit integers. Similarly, the return value was expected to be a 16-bit integer returned in the machine registers X and A (since, obviously, the return address of the routine must needs be at the top of the stack).

These routines had to be relocatable (no absolute references such as JMP, only branch-type jumps) because the strings could be moved around in memory. For this reason Page 6 (060016–06FF16), a page of memory not used by ATARI BASIC or ATARI OS, was very popular for storing small routines.

On the 6502, relocation is not trivial. These days we expect programs to sit pretty much anywhere in memory; the loader and processor collaborate to make that happen. But microprocessors of that era did not do that. The 6502 was especially hindered by having very few indirection instructions, and those it had were asymmetric: the X and Y registers indirect in different directions. This leads either to rather clumsy code that is forever moving stuff between registers, or clever but obtuse code that keeps them where they need to be even if it would seem more obvious to stick something else there. The 6502 instruction set is small enough that, over a short time, programmers can model the entire processor in their heads, even down to knowing how many cycles each instruction takes, and then start making clever tricks.

As well as using machine code for advanced functions, fairly trivial USR routines were sometimes used simply to get access to OS functions that had not been provided through Atari BASIC: for example block serialization to and from devices (BASIC only let it be done byte by byte, with GET and PUT, which had enormous unnecessary overhead for streaming a block of I/O), or for reading and writing memory (the PEEK and POKE commands were also unnecessarily slow because of the numeric problems described above.

Reserved words

ABS
Returns the distance of a number from zero
ADR
Returns the address of a variable
AND
Boolean operator
ASC
Returns the ATASCII value of a character
ATN
Returns the arctangent of a number in radians
BYE
Clears the program from memory and transfers control to Operating System
CLOAD
Loads a binary program from cassette tape
CHR$
Returns a character given an ATASCII value
CLOG
Returns the common logarithm (i.e. log10) of a number
CLOSE
Closes an I/O channel
CLR
Clears the screen
COLOR
Chooses which logical color to draw in
COM
CONT
Resumes execution of a program after a STOP
COS
Returns the cosine of a number in radians
CSAVE
Saves a binary program to cassette tape
DATA
Defines lists of numeric or string values
DEG
Converts radians to degrees
DIM
Defines the size of a string or array
DOS
Transfers control to the Disk Operating System, allowing return of control
DRAWTO
Draws a line to a given position
END
Finishes execution of the program
ENTER
Loads a text program from an I/O channel
EXP
Returns one number raised to the power of another
FOR
Starts a control loop
FRE
Returns the amount of free memory in bytes
GET
Reads one byte from an I/O channel
GOSUB
Jumps to a subroutine at a given line in the program, placing the return address on the stack
GOTO
Jumps to a given line in the program
GRAPHICS
Sets the graphics mode
IF
Branches depending on whether a condition is true
INPUT
Retrieves a stream of text from an I/O channel
INT
Returns the integral part of a number
LEN
Returns the length of a string
LET
Assigns a value to a variable
LIST
Lists (part of) the program to an I/O channel
LOAD
Loads a binary program from an I/O channel
LOCATE
Returns the logical color or ATASCII character at the cursor
LOG
Returns the natural logarithm (i.e. loge) of a number
LPRINT
Prints text to a printer device
NEW
Erases the program from memory
NEXT
Continues the next iteration of a control loop
NOT
Boolean operator
NOTE
Returns the current position on an I/O channel
ON
Selects and jumps to a line based on the value of a variable
OPEN
Initialises an I/O channel
OR
Boolean operator
PADDLE
Returns the position of a paddle device
PEEK
Returns the value at an address in memory
PLOT
Draws a point at a given location
POINT
Sets the current position on an I/O channel
POKE
Sets a value at an address in memory
POP
Removes a subroutine return address from the stack
POSITION
Sets the position of the graphics cursor
PRINT
Writes text to an I/O channel
PTRIG
Returns whether a paddle trigger is pressed
PUT
Writes one byte to an I/O channel
RAD
Converts degrees to radians
READ
Reads data from a DATA statement
REM
Marks a comment in a program
RESTORE
Sets the position of where to read data from a DATA statement
RETURN
Pops a subroutine return address from the stack and jumps to it
RND
Returns a random number[2]
RUN
Starts execution of a program, optionally from a given line number
SAVE
Writes a binary program to an I/O channel
SETCOLOR
Maps a logical color to a physical color
SGN
Returns the signum of a number
SIN
Returns the sine of a number in radians
SOUND
Starts or stops playing a tone on a sound channel
SQR
Returns the square root of a number
STATUS
Returns the status of an I/O channel
STEP
Indicates the increment used in a FOR loop
STICK
Returns a joystick position
STOP
Stops the program, allowing later resumption
STRIG
Returns whether a joystick trigger is pressed
STR$
Converts a number to string form
THEN
Indicates the statemements to execute in an IF statement
TO
Indicates the limiting condition in a FOR statement
TRAP
Sets to jump to a given line if an error occurs
USR
Calls a machine code routine
VAL
Returns the numeric value of a string
XIO
General-purpose I/O routine

Running without Atari BASIC

On the XL/XE models, Atari BASIC could be disabled by holding down the OPTION key while booting the computer. The XEGS would disable BASIC if powered without the keyboard attached.

If another cartridge were inserted it may also disable Atari BASIC, if they used the same address space.

See also

References

Notes

  1. ^ Wilkinson, Bill (1983). The Atari BASIC Source Book. Compute! Books. ISBN 0-942386-15-9.
  2. ^ The number is derived from signal noise on a hardware chip, POKEY, and so is not a pseudorandom number.[citation needed]

External links


Search unanswered questions...
Enter a question here...
Search: All sources Community Q&A Reference topics
 
 
Learn More
Atari Microsoft BASIC
BASIC A+
Carol Shaw (video game designer)

When was Atari invented? Read answer...
What is an a atari worth? Read answer...
When was atari found? Read answer...

Help us answer these
Who is atari pong?
How was the atari invented?
Who was the atari developed for?

Post a question - any question - to the WikiAnswers community:

 

Copyrights:

Wikipedia. This article is licensed under the Creative Commons Attribution/Share-Alike License. It uses material from the Wikipedia article "Atari BASIC" Read more