Atari BASIC

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by Maury Markowitz (talk | contribs) at 12:32, 22 November 2019 (→‎Performance). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Atari BASIC
Original author(s)Paul Laughton
Kathleen O'Brien
Developer(s)Shepardson Microsystems
Initial release1979; 45 years ago (1979)
Stable release
Revision C / 1983; 41 years ago (1983)
PlatformAtari 8-bit family
TypeBASIC
LicenseCommercial proprietary software

Atari BASIC is an interpreter for the BASIC programming language that shipped with the Atari 8-bit family of 6502-based home computers. Unlike most BASICs of the home computer era, Atari BASIC is not a derivative of Microsoft BASIC, and differs in significant ways. It includes keywords for Atari-specific features and lacks support for string arrays, for example.

The language was originally an 8 KB ROM cartridge for the first machines in the 8-bit series, the 400, 800 and 1200XL. Starting with the 600XL and 800XL, BASIC was built-in to the machines, but can be disabled by holding down the OPTION key while booting. The XEGS disables BASIC if powered without the keyboard attached.

Atari BASIC was generally near the bottom in performance benchmarks of the era. The reasons for this poor showing was the topic of considerable press coverage in Atari-related magazines and columns in general magazines like Creative Computing. The original authors addressed most of these issues in BASIC XL, although a host of 3rd party solutions like Turbo-Basic XL also appeared.

The complete annotated source code and design specifications of Atari BASIC were published as The Atari BASIC Source Book in 1983.[1]

History

The machines that would become the Atari 8-bit family had originally been developed as second-generation video game consoles intended to replace the Atari 2600. Ray Kassar, the new president of Atari, decided to challenge Apple Computer by building a home computer instead.[2] This meant the designs, among other changes, needed to support the BASIC programming language, then the standard language for home computers.

In early 1978, Atari licensed the source code to the MOS 6502 version of Microsoft BASIC.[3] The original Altair BASIC on the Intel 8080 came in three versions for different memory sizes, 4, 8 and 12 kB. Porting this to the less-dense 6502 instruction set caused it to grow in size. At the same time, the price of memory was falling and machines were shipping with more room. When porting to the 6502, instead of three versions with major differences there were two versions that were largely identical; one was about 7800 bytes and used the 8080-format 32-bit floating point numbers, the second was a slightly larger 9 kB version with an expanded 40-bit number format.[4]

Even the smaller 32-bit version barely fit into the 8 kB size Atari had selected for the machine's ROM cartridge format. Atari felt that they also needed to expand the language to add better support for the specific hardware features of their computers, similar to what Apple had done with Applesoft BASIC. This increased the size to around 11 kB, which was typical for other 6502-based machines; AppleSoft BASIC on the Apple II+ was 10240 bytes long, for instance.[a]

Paring down the code from 11 to 8 kB to fit in a ROM turned out to be a significant problem.[3] Six months later they were almost ready with a shippable version of the interpreter. However, Atari was facing a January 1979 deadline with the Consumer Electronics Show (CES) where the machines would be demonstrated. They decided to ask for help to get a version of BASIC ready in time for the show.[3]

Shepardson Microsystems

The 8K Atari BASIC cartridge

In September 1978, Shepardson Microsystems won the bid on completing BASIC.[3] Shepardson had written a number of programs for the Apple II family, which used the same 6502 processor, and were in the middle of finishing a new BASIC for the Cromemco S-100 bus machines (Cromemco 32K Structured BASIC).[5]

Shepardson examined the existing work and decided it was too difficult to continue cutting it down to size; instead, they recommended developing a completely new version, originally 10k in size.[6] To make it fit on an 8k ROM, some of the common routines would be moved to the operating system ROMs. 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.[3]

The contract specified a delivery date on or before 6 April 1979 and this also included a File Manager System (later known as DOS 1.0).[6] 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. Development proceeded quickly, helped by a bonus clause in the contract, and an 8K cartridge was available just before the release of the machines. Atari took that version to CES instead of the MS version.[7] Atari Microsoft BASIC later became available as a separate product.[8]

Releases

The version Shepardson gave to Atari for the CES demo was not supposed to be the final version. Between the time they delivered the demo and the final delivery a few weeks later, Shepardson found several bugs in the code and had developed fixes for them.[7] However, unknown to Shepardson, Atari had already sent the CES version to manufacturing.[9]

This version was later known as Revision A. Among several problems, this version contains a major bug in a subroutine that copies memory; deleting lines of code that were exactly 256 bytes long causes a lockup. This was sometimes known as the "two-line lockup" because it did not trigger until the next line of code or command was entered. It was notorious as it was one of a very few problems that could not be fixed by pressing the Reset key.[10]

Revision B attempted to fix all of the major bugs in Revision A, and was released in 1983 as a built-in ROM in the 600XL and 800XL models. While fixing the memory copying bug, the programmer noticed the same pattern of code in the section for inserting lines, and applied the same fix. This "fix" instead introduced the original bug into this code. Inserting new lines is much more common than deleting old ones, so the change dramatically increased the number of crashes.[10] Another major problem in Revision B was a bug that added 16 bytes to the memory of the program every time it was SAVEd and LOADed, eventually causing the machine to run out of memory even on the smallest programs.[11][12] Mapping the Atari described them as "awesome bugs", and advised Revision B owners "Don't fool around; get the new ROM, which is available on cartridge" from Atari.[12] The book provided a type-in program to patch Revision B to Revision C for those without the cartridge.[13]

Revision C finally eliminated the memory leaks in Revision B.[12] This version was built-in on later versions of the 800XLs,[11] all XE computers, and the XEGS. Revision C was also available in a cartridge production run.[12]

The version can be determined by typing PRINT PEEK(43234) at the READY prompt. The result is 162 for Revision A, 96 for Revision B, and 234 for Revision C.[14]

Description

Program editing

What happens when a line containing a syntax error is entered

Atari BASIC uses a line editor, like most home computer BASICs. Unlike most BASICs, Atari BASIC scans the just-entered program line and reports errors immediately. If an error is found, the editor re-displays the line, highlighting the text near the error in inverse video. Errors are displayed as numeric codes, with the descriptions printed in the manual.

Program lines can be entered by starting with a line number, from 0 to 32767, which will insert a new line or amend an existing one. Lines without a line number are executed immediately. When the programmer types RUN the program executes from the lowest line number. Atari BASIC allows all commands to be executed in both modes. For instance, the LIST command can be used inside a program.

The LIST statement can display either the entire BASIC program or a range of lines by specifying the starting and ending line separated with a comma. LIST "P:" sends a program listing to the printer instead of the screen.

Program lines ("logical lines") can be up to three screen lines ("physical lines") of 40 characters, so 120 characters total. The cursor can be moved freely in these lines, unlike in other BASICs where the cursor can only be moved left or right in the editor. The OS handles tracking whether a physical line flowed to the next on the same logical line, so moving the cursor up and down could move within logical lines or between them, automatically.

Atari BASIC allows keywords to be typed in an abbreviated form using the pattern set by Palo Alto Tiny BASIC, by typing a period at any point in the word. So L. is expanded to LIST, as is LI.. Only enough letters have to be typed to make the abbreviation unique, so PLOT requires PL. because the single letter P is not unique.

Pressing ↵ Enter sends the tokenizer the (logical) line on which the cursor sits. So, in the example pictured above (with PRUNT), all the author needs to do to fix the error is move the cursor over the U, type I (the editor only has an overwrite mode) and hit ↵ Enter. This is a common editing technique for, say, renumbering lines. Atari BASIC has no built-in renumbering command, but one can quickly learn to overwrite the numbers on a set of lines then just hit ↵ Enter repeatedly to put them back into the program.

The tokenizer

Atari BASIC uses a token structure to handle lexical processing for better performance and reduced memory size.[15] In contrast to MS-derived BASICs, Atari BASIC tokenizes the entire line. MS tokenizes only keywords like FOR and PRINT, and leaves everything else - variables, mathematical expressions, numbers and strings - in their original ASCII format. Atari BASIC converted all of these to tokens, replacing variables with a token pointing to their value in memory, and pre-parsing numbers into the 40-bit format they would ultimately be used in. Shepardson referred to this early-tokenizing concept as a "pre-compiling interpreter".[16]

The tokenizer converts lines using a small buffer in memory, and the program is stored as a parse tree.[b] The token output buffer (addressed by a pointer at LOMEM – 80, 8116) is 256 bytes, and any tokenized statement larger than the buffer generates an error (14 – line too long). 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). By indirecting the variable names in this way, a reference to a variable needs only two bytes to address its entry into the appropriate table. Strings have their own area (pointed to at STARP – 8C, 8D16) as does 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.

To expand an abbreviation, the tokenizer searches through its list of reserved words to find the first that matches the portion supplied. More commonly used commands occur first in the list of reserved words, with REM at the beginning (it can be typed as .). When the program is later LISTed it will always write out the full words with three exceptions: PRINT has a synonym, ?; GOTO has a synonym, GO TO; and LET has a synonym which is the empty string (so 10 LET A = 10 and 10 A = 10 mean the same thing). These are separate tokens, and so will remain as such in the program listing.

In the keywords for communicating with peripherals (see the Input/Output section, below) such as OPEN # and PRINT #, the " #" is actually part of the tokenized keyword and not a separate symbol. For example, "PRINT" and "PRINT #0" are the same thing,[c] just presented differently.

Mathematical functions

Atari BASIC includes 12 functions for mathematical and trigonometric calculations. The TAN function is not included, but may be derived via the EXP function. DEG and RAD are used to set whether trigonometric functions use radians or degrees (radians being the default). The RND function generates a number between 0 and 1, with the parameter to the function not being used. The number is derived via the POKEY random number register at address $D20A.

String handling

Atari BASIC differs considerably from Microsoft-style BASICs in the way it handles strings. Microsoft BASIC mostly copied the string-handling system of DEC's BASIC-PLUS, in which strings are first-class types with variable bounds. This allows both string variables as well as arrays of strings, as both are represented internally by a computer word pointing to storage on a heap. In contrast, Atari BASIC copied the string-handling system of Hewlett-Packard BASIC, where the basic data type is a single character and strings are arrays of characters.

The side-effect of this design is that there are no true string arrays and each string variable must be DIMensioned before it can be used. For example:

10 DIM A$(20)
20 PRINT "ENTER MESSAGE: ";
30 INPUT A$
40 PRINT A$

In this program, a 20 character string is reserved, and any characters in excess of the string length will be truncated. The maximum possible length of a string in Atari BASIC is 32,768 characters.

MS BASIC included functions for accessing bits of strings, for instance, LEFT$(A$,10) would return the leftmost 10 characters of A$. In Atari BASIC the string is represented by an array, and was access using array indexing functions. The equivalent statement in Atari BASIC would be A$(1,11); note that the arrays are 1-indexed, not 0-indexed as in most modern variations. Because this "slicing" syntax was the same as two-dimensional arrays in other BASICs, there was no way to define or work with arrays of strings.

Atari BASIC does not initialize array variables and a string or array may contain whatever random data was present in memory when it was allocated. The following trick allows fast string initialization, and it is also useful for clearing large areas of memory of unwanted garbage (numeric arrays can only be cleared with a very slow FOR...NEXT loop)

10 REM Initialize A$ with 1000 characters of X
20 DIM A$(1000)
30 A$="X":A$(1000)=A$:A$(2)=A$

String concatenation in Atari BASIC works as in the following example. The target string must be large enough to hold the combined string or an error will result:

10 DIM A$(12),B$(6)
20 A$="Hello ":B$="there!"
30 A$(LEN(A$)+1)=B$
40 PRINT A$

The INPUT statement cannot be used with a prompt nor with array variables. The latter must be filled indirectly via a statement like 20 INPUT A:B(1)=A. Array variables in Atari BASIC also may contain two subscripts.

Strings included in DATA statements do not have to be enclosed in quote marks in Atari BASIC, as a result it is also not possible for data items to contain a comma. The READ statement also cannot be used with array variables.

Arrays have a base index of 0, so a statement such as DIM A(10) actually creates an 11-element array (elements 0-10).

Input/Output

The Atari OS includes a subsystem for peripheral device input/output (I/O) known as CIO (Central Input/Output). Most programs can be written independently of what device they might use, as they all conform to a common interface; this was rare on home computers at the time. New device drivers could be written fairly easily that would automatically be available to Atari BASIC and any other program using the Atari OS, and existing drivers could be supplanted or augmented by new ones. A replacement E:, for example could displace the one in ROM to provide an 80-column display, or to piggyback on it to generate a checksum whenever a line is returned (such as used to verify a type-in program listing).

Atari BASIC supports CIO access with reserved words OPEN #, CLOSE #, PRINT #, INPUT #, GET #, PUT #, NOTE #, POINT # and XIO #. There are routines in the OS for graphics fill and draw, but they are not all available as specific BASIC keywords. PLOT and DRAWTO for line drawing are supported while a command providing area fill is not. The fill feature can be used through the general CIO entry point, which is called using the BASIC command XIO.

The BASIC statement OPEN # prepares a device for I/O access:

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

Here, OPEN # means "ensure channel 1 is free," 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 "read" (other codes are 8 for write and 12 = 8 + 4 for "read-and-write"). The third number is auxiliary information, set to 0 when not needed. The C:MYPROG.DAT is the name of the device and the filename; the filename is ignored for the cassette driver. Physical devices can have numbers (mainly disks, printers and serial devices), so "P1:" might be the plotter and "P2:" the daisy-wheel printer, or "D1:" may be one disk drive and "D2:" and so on. If not present, 1 is assumed.

The LPRINT statement is used to output strings to the printer.

Atari BASIC does not include an equivalent of the Microsoft BASIC GET or INKEY$ commands to detect a keypress, this can be simulated either by POKEing the keyboard driver directly or opening it as a file (e.g. OPEN 1,4,0,"K:":GET #1,A$) although the latter will wait for a keypress unlike GET or INKEY$.

Typing DOS from BASIC will exit to the Atari DOS command menu. Any unsaved programs will be lost. There is no command to display a disk directory from within BASIC and this must be done by exiting out to DOS.

DOS occupies roughly 5k of memory, thus a cassette-based Atari machine (48k or greater) will have around 37,000 bytes of free BASIC program memory and 32,000 bytes if DOS is present. BASIC cannot use the extra RAM on XL and XE machines.

Graphics and sound support

Atari BASIC has built-in support of sound, (via the SOUND statement), setting up the screen graphics (GRAPHICS, SETCOLOR, drawing graphics COLOR, PLOT, DRAWTO), joysticks (STICK, STRIG), and paddles (PADDLE, PTRIG). The underlying operating system included a routine to fill arbitrary shapes, but BASIC did not have a PAINT command and it instead had to be called with the XIO command.[17]

There is no dedicated command for clearing the screen in Atari BASIC, this is usually done with PRINT CHR$(125), which PRINTs the clear screen control code (analogous to PRINT CHR$(147) in Commodore BASIC). Atari BASIC does not include a TAB function; this can be simulated by either POKEing the cursor column position at $55 or the tab position at $C9, which has a default value of 10. The changed values will not take effect until a PRINT statement is executed. There is also no SPC function in Atari BASIC.

Advanced aspects of the hardware such as player/missile graphics (sprites), redefined character sets, scrolling, and custom graphics modes are not supported by BASIC; these will require machine language routines or PEEK/POKE statements. A few graphics modes cannot be accessed from BASIC on the Atari 400/800 as the OS ROMs do not support them; the only way to access them is in machine language by setting the ANTIC registers and Display List manually. The OS ROMs on the XL/XE added support for these modes.[18]

Bitmap modes in BASIC are normally set to have a text window occupying the last three rows at the bottom of the screen so the user may display prompts and enter data in a program. If a 16 is added to the mode number invoked via the GRAPHICS statement, the entire screen will be in bitmap mode (e.g. GRAPHICS 8+16). If bitmap mode in full screen is invoked, Atari BASIC will automatically switch back into text mode when program execution is terminated unlike many other BASICs which leave the user in bitmap mode and have an unreadable screen that can only be switched out of via typing a blind command or resetting the computer.

Bitmap coordinates are calculated in the range of 1 to maximum row/column minus one, thus in Mode 6 (160x192), the maximum coordinates for a pixel can be 159 and 191. If the user goes over the allowed coordinates for the mode, BASIC will exit out with an error.

Advanced techniques

Line labels

Unlike MS-derived BASICs, Atari BASIC allows numeric variables and expressions to be used to supply line numbers to GOTO and GOSUB commands. This can be used to clarify code. For instance, a subroutine that clears the screen could be written as GOSUB CLEARSCREEN, which is much easier to understand than the typical GOSUB 10000. If a particular subroutine is executed frequently, placing its line number in a variable will also improve execution speed as it is faster for BASIC to look up a constant in a variable instead of processing it each time the statement is executed.

Includes

Most BASICs of the era allow the LIST command to send the source code to a printer or other device. Atari BASIC also includes the ENTER command, which reads source code from a device and merges it back into the program, as if the user had typed it in. This allows programs to be saved out in sections, reading them in using ENTER to merge or replace existing code. By carefully using blocks of line numbers that do not overlap, programmers can build libraries of subroutines and merge them into new programs as needed.

Embedded machine language

Atari BASIC can call machine code subroutines. The machine code is generally stored in strings, which can be anywhere in memory so the code needs to be position independent, or in the 256-byte Page 6 area (starting at address 153610, 60016), which is not used by BASIC or the operating system. Code can be loaded into Page 6 by reading it from DATA statements.

Machine code is invoked with the USR function. The first parameter is the address of the machine code routine and the following values are parameters. For example, if the machine language code is stored in a string named ROUTINE$ it can be called with parameters as ANSWER=USR(ADR(ROUTINE$),VAR1,VAR2).

Parameters are pushed onto the hardware stack as 16-bit integers in the order specified in the USR function in low byte, high byte order. The last value pushed to the stack is a byte indicating the number of arguments. The machine language code must remove all of these values before returning via the RTS instruction. A value can be returned to the BASIC program by placing it in addresses 21210 and 21310 (D416 and D516) as a 16-bit integer.

Performance

In theory, Atari BASIC should run much faster than contemporary BASICs based on the MS pattern. Because the source code is tokenized when it is entered, instead of at run time, the entire tokenization and parsing steps are already complete. Even complex mathematical operations are ready-to-run, with any numerical constants already converted to the internal 40-bit format, and variables can be looked up by address rather than having to be searched for.[d] In spite of these theoretical advantages, in reality, Atari BASIC is slower than other home computer BASICs, often by a large amount.[19]

On two widely used benchmarks of the era, Byte magazine's Sieve of Eratosthenes and the Creative Computing benchmark test written by David H. Ahl, the Atari finished near the end of the list in terms of performance, and was much slower than the contemporary Apple II or Commodore PET,[20] in spite of having the same CPU but running it at roughly twice the speed of either. It finished behind relatively slow machines like the Sinclair ZX81 and even some programmable calculators.[21]

Most of the language's slowness stemmed from three problems.[19]

The first is that the floating-point math routines were poorly optimized. In the Ahl benchmark, a single exponent operation, which internally loops over a poorly optimized multiplication function, was responsible for much of the machine's poor showing.[19]

In addition to performing most mathematical operations slowly, the conversion between the internal floating-point format and the 16-bit integers used in certain parts of the language were relatively slow. Internally, these integers were used for line numbers and array indexing, along with a few other tasks, but numbers in the program were always stored in binary coded decimal (BCD) format.[22] Whenever one of these is encountered, for instance, in the line number in GOTO 100, the tokenized BCD value has to be converted to integer, an operation that can take as long as 3500 microseconds.[23] Other BASICs avoided this delay by special-casing the conversion of numbers that could only possibly be integers, like the line number following a GOTO, switching to special ASCII-to-integer code to improve performance.

Another problem is due to how Atari BASIC implemented branches. To perform a branch in a GOTO or GOSUB, the interpreter searches through the entire program for the matching line number it needs.[15] One minor improvement found in most Microsoft-derived BASICs is to compare the target line number to the current line number, and search forward from that point if it is greater, or start from the top if less. This improvement was missing in Atari BASIC. It was further slowed by the fact that the numbers were stored in BCD format and thus had to be converted from BCD to integer before the search could begin. This could take as long as 3500 microseconds.[24]

The most serious problem was the implementation of FOR...NEXT loops; MS-based interpreters would push a pointer to the location of the FOR on a stack, so when it reached the NEXT it could easily return to the FOR again in a single branch operation. It also pushed the line number for error reporting purposes. Atari BASIC used only the line number. This meant every time a NEXT was encountered, the system had to search through the entire program to find the corresponding FOR line. As a result, any loops in an Atari BASIC program cause a large loss of performance relative to other BASICs.[19]

Several BASICs for the Atari addressed some or all of these issues, resulting in large performance gains. BASIC XL reduced the time for the Byte benchmark from 194 to 58 seconds,[19] over three times as fast. This was accomplished by caching the location of FOR/NEXT loops, as in other BASICs, and also used this same cache to perform GOTO and GOSUB line lookups for further improvements. Turbo-BASIC XL included a different solution to the line-lookup issue, as well as a re-written, high-performance, floating-point library. On the Ahl benchmark, Atari BASIC required 405 seconds, while exactly the same code in Turbo BASIC took 41.6 seconds, an order of magnitude improvement.[25]

Differences from Microsoft BASIC

  • The following keywords are not in Atari BASIC: INKEY$, CLS,DEF FN, TAB, ELSE.
  • All arrays must be dimensioned prior to use while Microsoft BASIC defaults an array to 10 elements if not dimensioned.
  • String variables are treated as arrays and must be dimensioned before use.
  • Atari BASIC does not allow arrays of strings or string concatenation.
  • There is no support for integer variables.
  • There are no bitwise operators.
  • Variable names can be of arbitrary length.
  • INPUT cannot include a prompt.
  • PRINT may be abbreviated as ? as in Microsoft BASIC, but Atari BASIC does not tokenize it into PRINT. LIST-ing a program still shows the question mark.
  • The target of GOTO and GOSUB can be a variable or expression.
  • FOR..NEXT loops in Atari BASIC must have a variable name referenced by the NEXT statement while Microsoft BASIC does not require it.
  • Multiple variables are not permitted with NEXT statements as they are in Microsoft BASIC (e.g., NEXT X,Y).
  • LIST uses a comma to separate a range instead of a minus sign.

Keywords

See also

Notes

  1. ^ AppleSoft BASIC occupied memory locations $D000 through $F7FF, a total of 10240 bytes.
  2. ^ Although the parse tree is implemented as a set of tables, which is really an implementation detail.
  3. ^ Although 0 is actually explicitly disallowed here by BASIC assuming it to be a coding error, isn't it?
  4. ^ This is the reason MS-basics only have two significant letters in variable names, they are stored in a list with only two bytes of ASCII for the name in other to improve searching time.

References

Citation

  1. ^ Wilkinson, O'Brien & Laughton 1983.
  2. ^ Decuir 2004.
  3. ^ a b c d e Wilkinson 1982, p. ix.
  4. ^ Steil, Michael (20 October 2008). "Create your own Version of Microsoft BASIC for 6502". Some Assembly Required.
  5. ^ Wilkinson 1982, pp. iv–v.
  6. ^ a b Wilkinson 1982, p. v.
  7. ^ a b Wilkinson 1982, p. x.
  8. ^ Cherry, Charles (June 1987). "BASIC Bonanza". Antic.
  9. ^ Wilkinson 1982, p. vi.
  10. ^ a b "Atari BASIC Bugs". Compute!. July 1986. p. 10.
  11. ^ a b Radcliff, Matthew (September 1995). "Revision C Converter". Antic.
  12. ^ a b c d Chadwick 1985, p. 230.
  13. ^ Chadwick 1985, pp. 250–251.
  14. ^ Hardy, Bob (February 1993). "Keycode Getter". Atari Classics. p. 18.
  15. ^ a b Winner, Lane (1982). "De Re Atari, Chapter 10: Atari BASIC". Atari, Inc.
  16. ^ Wilkinson, O'Brien & Laughton 1983, p. 5.
  17. ^ Atari BASIC Reference Manual. p. 54.
  18. ^ "ATR: chpt.15: Display Lists".
  19. ^ a b c d e Wilkinson 1985, p. 139.
  20. ^ Ahl, David (November 1983). "Benchmark comparison test". Creative Computing. pp. 259–260.
  21. ^ Ahl, David (January 1984). "Creative Computing Benchmark". Creative Computing. p. 12.
  22. ^ Wilkinson, O'Brien & Laughton 1983, p. 17.
  23. ^ Crawford, Chris (1988). De Re Atari. Atari Program Exchange. p. 8-45.
  24. ^ Crawford, Chris (1988). De Re Atari. Atari Program Exchange. p. 8-45.
  25. ^ "Ahl's Benchmark?". 28 November 2007.

Bibliography

External links