Lights, Camera, ACTION!
San Jose, Calif.
I popped the fluorescent orange cartridge into its slot and slammed the hood shut. Let's take this baby out for a spin.
Switch on the ignition, put it into low, and let's go. Pretty smooth, pretty responsive -- so far. Let's really test this thing out. I floored it. Zero to 60 in 10 seconds. Woowee! Goodbye BASIC, farewell Forth, here comes Action!. This is the best thing to happen to Atari since Nolan Bushnell figured out people would play ping-pong on a TV screen.
Whoa, fella. Slow down. That's a pretty bold statement. Yeah I know, but Action! is such a revolutionary product.
Action! is a cartridge-based programming language that requires 16K bytes random access memory. A cassette or disk drive is recommended for saving your programs and everything you need to write Action! programs are included in the cartridge: a complete text editor, the Action! compiler and a monitor to debug your programs.
The editor is the best I've ever used. It's a full-screen editor that uses all the Atari's built-in features. Also, it supports:
- A split screen mode that allows the simultaneous editing of two files.
- A comprehensive search and replace function.
- Text lines as long as 240 characters.
- A "Paste" buffer of almost unlimited size to move or copy blocks of text.
- "Tags" that mark your text, so you can jump from place to Place with ease.
- Movement through the text a line or a page at a time.
- Type-over or insert modes, allowing you to choose between typing over what you've already written, or automatically inserting your additions between existing text.
In fact, except for the lack of word wrap and printer formatting commands, this is a complete word processing system that's very responsive. After using the Action! editor for a few hours, other software seem sluggish.
Action! was designed for people who program in Atari BASIC. Now, I'll admit I have a prejudice against BASIC. I use it because there has been nothing better. Sure, BASIC has its good points -- it's universal and friendly, you can run a program, stop it if it doesn't work, make a few changes and continue exactly where you left off -- but you pay a price for this convenience. It's s-l-o-w.
Action! on the other hand, is very fast. About 200 times faster than BASIC. The only language that is faster is assembly language, and that is just by a little. (Look at the Benchmark Table to get an idea of how fast Action! is.) Our benchmark program calculates the first 1,899 prime numbers 10 times for a more accurate timing. BASIC takes nearly an hour to do it. Even using a very good C complier on a Z-80 computer running twice the speed of the Atari, I couldn't improve Action's! time by more than a few seconds. Also, it compiles programs just as quickly. A 13K byte source program will translate into machine code in less than 30 seconds.
There is one drawback, however. BASIC programmers may be thrown by the syntax of Action!. There are not any line numbers, no GOSUB or GOTO statements. But don't worry, you'll get used to it -- you may even grow to like it!
Action! is based on structured, procedure-oriented languages like PASCAL, C and PL/1. The program consists of a number of independent modules called procedures or functions, each with its own task to perform and its own set of variables. The last procedure in the program puts all of them together in the right sequence. For example, if you were to write a program to describe your morning run, it might include the procedures: GET-DRESSED, GO-OUTSIDE, LEFT-FOOT-FORWARD, RIGHT-FOOT-FORWARD, TOO-TIRED, GO-HOME and so on. Your final procedure, GO-JOGGING, puts them together like this:
That's how an Action! program works. If necessary, any procedure may communicate with any other by passing along numeric values.
In the Action! version of the benchmark program, Prime seive() does all the work. Above it are some variable definitions. These are called declarations, and this is another area where Action! differs from BASIC. All variables must be declared. That is, you must tell the computer each variable's name and type before you use it. The fundamental types are CHAR for ATASCII letter, BYTE for numbers in the range 0-255, CARD for 0-65,535, and INT for -32,768 to +32,767. Action! also supports one-dimensional arrays, strings, pointer variables, and a limited record type.
You may give any variable a starting value, or tell the computer where to store the variable in memory. They may be declared globally, so they are available to the whole program, or locally, or so they are available only to the procedure in which they are used.
Action! allows you to store a procedure anywhere in memory. Or you may name a code block already in memory and then call it by that name in your program. Programmers can use this feature to access pre-assembled routines, or to use the routines built into the operating system. Machine language also may be typed directly into your source program.
Action!, which has simple syntax, looks a little like a stripped down C or PASCAL. It has a small set of built-in commands, but provides most of the control structures and arithmetic operators you would expect from a powerful high-level language.
Similar to C, Action! has no built-in commands for input or output. All I/O and most high-level functions are provided by a library of routines in the cartridge. There are nearly 70 prewritten procedures and functions that duplicate most BASIC commands. BASIC programmers will feel right at home with the library routines, since they're just like BASIC. Action! Setcolor (2,0,0) does exactly what BASIC SETCOLOR 2,0,0 does.
OSS also is offering a Programmer's Aid Disk with supplemental routines, including player-missile graphics procedures, floating point functions, a powerful print formatting procedure and two games written in Action!. The disk is available for $30 and a complete Action! source code is included.
After you've written your program, you can use the Action! monitor to do simple debugging. You may examine or write to memory, examine or set a variable's value, or run any procedure or function by itself. There is a trace mode which will display the routines called by your program as it runs and the values passed to them. Also, the monitor allows you to change certain system parameters to suit your taste, or execute an Action! statement stand alone.
You compile Action! programs from the monitor and you can run the program there or save it to disk as a binary file. Programs saved this way may be run using the DOS "L" command. If, during compilation, Action! detects an error, it will stop and print an error message. As with most compilers, Action! is often in the dark about what went wrong, but it will leave the cursor in the text where it stopped. So it's fairly easy to find your mistake.
Action! compiles to true 6502 machine code, but the cartridge must be in place to provide support routines while your program runs. OSS offers a run-time package that may be appended to Action! programs to allow them to run without the cartridge's support. The run-time package is small, less than 4K bytes, and will be inexpensive. OSS plans to charge $30 for public-domain and personal use, several hundred dollars for commercial software publishers.
I've been using Action! for a month now, and I've never seen a more powerful or useful programming environment on a microcomputer. This is all the more amazing, since the editor is only 4K bytes and the compiler only 6K.
Naturally, some compromises have been made to achieve this compactness:
- Floating point numbers are not directly supported by Action! They are available on OSS's Programmer's Aid Disk, but the implementation is awkward.
- There is no CASE-type control structure.
- Action! does not allow negative compiler constants. You can't initialize a variable to a negative number -- inconvenient, but not fatal.
- You must compile your entire program at one time. Modules cannot be separately compiled. And although you can compile from disk, you cannot compile to disk, so the size of your compiled program may not exceed available memory. That's about 27K on my 48K machine.
I think the biggest problem most will encounter will be getting used to a structured language. However, in the long run this language will be easier. Learning it on your own can be tough, though, and unfortunately the manual is not much help. Many of the features of the language are ignored and in some parts the manual is wrong. What we really need is a tutorial. OSS is working on one, but until they release it, look for some late-night sessions with the computer.
Given the choice between Action! and any other Atari-oriented language, I would vote for Action!. This language is like a finely tuned racing car. There's a lot that can go wrong and it may take a little more skill to drive. If you'd prefer to stick with the BASIC station wagon, with its automatic transmission and CPU hogging engine, I won't blame you. As for myself, give me the feel of the wind in my hair. Give me Action!.
- Leo G. Laporte
Prime Number Benchmark
A benchmark is a program that tests the speed with which a language performs certain tasks. The following programs are based on a standard benchmark first published in BYTE Magazine. This program calculates all the prime numbers between 3 and 16,000 using an algorithm called Eratosthanes Seive. Each version repeats its calculations 10 times for more accurate timing.
Programmers experienced in each of the following languages will no doubt find more efficient means of performing these calculations, but it is our intention that the methods used below reflect the approach a typical user of each language might take.
No single benchmark can accurately reflect the true efficiency of a language. These tests should be used only to gauge the relative performance of each language in the areas of data manipulation, controlled loops, and memory references. In other words, use these figures for comparison only. Your mileage may differ.
DEFINE size "8190", ON = "1", OFF = "0" BYTE ARRAY flags(size+1) CARD count, i, k, prime, jifs BYTE secs, hunds, iter, tick = 20, tock = 19 PROC Prime seive() tick = 0 tock = 0 FOR iter = 1 to 10 DO count = 0 SetBlock (flags, size, ON) FOR i = 0 to size DO IF flags(i) THEN prime = i+i+3 k = prime + 1 WHILE k < = size DO flags(k) = OFF k = = + prime OD count = = + 1 FI OD OD jifs = tick + 256*tock secs = jifs/60 hunds = ((jifs MOD 60)*100)/60 PrintF("%U.%U secs", secs, hunds) RETURN
10 SIZE= 8191:DIM FLAG$(SIZE) 20 FOR ITER=1 TO 10 30 FLAG$="1":FLAG$(8191)= FLAG$:FLAG$(2) = FLAG$ 70 FOR I = 1 TO SIZE 80 IF FLAG$(I,I) = "0" THEN 160 90 PRIME = I + I + 3 100 K=I+PRIME 110 IF K>SIZE THEN 150 120 FLAG$(K, K)="0" 130 K=K+PRIME 140 GOTO 110 150 COUNT=COUNT+1 160 NEXT I 170 NEXT ITER
Scr # 1 0 (Prime Number Benchmark) 1 2 8191 CONSTANT SIZE 3 SIZE CARRAY FLAG 4 5 : PRIME NO SEIVE 6 10 0 DO 0 FLAG SIZE 1 FILL 7 SIZE 0 DO 8 1 FLAG C 9 IF I DUP + 3 + DUP I + 10 BEGIN DUP SIZE < WHILE 11 0 OVER FLAG C! 12 OVER + 13 REPEAT DROP DROP 14 ENDIF 15 LOOP LOOP:
< 1 sec