Classic Computer Magazine Archive ANTIC VOL. 4, NO. 6 / OCTOBER 1985


How to convert 8-bit Atari program for the ST

by PATRICK BASS, Antic ST Program Editor

In May, 1985 I wrote a letter to the Editors of Antic asking if I could perhaps write an article or three for them. I mentioned that I had been a game designer/programmer for the old Atari during its heyday, and that later I programmed games for two Silicon Valley start-up companies that didn't quite "start up."
   So one Thursday when I'd just gotten home from being told I was overqualified to deliver pizzas, my father told me Antic phoned and wanted me to come up to San Francisco and see the editors. The next morning I hopped onto my Yamaha 250 motorcycle and hit the freeway. Shortly before noon, Antic sat me down at a 520ST and wouldn't let me leave.
   I was in hog heaven when Antic hired me to learn how to program their development ST. I had already decided to buy a 520ST when it became available, my only problem was figuring out how to afford one.
   The pile of highly technical documentation that came with Antic's 520ST was almost three feet high. I took home as much as I could carry and spent the weekend reading it.
   Back at Antic on Monday morning I confidently expected to start writing my first 520ST program using 68000 machine language, which I'm familiar with. However, the ST had other ideas.
   For one whole day I was stuck at one seemingly innocent statement (.ORG or Originate) that told the computer where to start putting my program into memory. The 520ST absolutely would not get past this.
   After what seemed like a couple of eternities I finally figured out that I was mistakenly assuming the 520ST acts like a microcomputer. In fact it acts much more like a minicomputer.
   The ST operating system is essentially Digital Research's CP/M 68K, which is a multi-tasking system that can run more than one program at the same time. If two or more programs tried to occupy the same memory address at the same time, the computer would fail.
   Therefore every application program written for the ST must be completely relocatable, able to run from any address. This is not really so strange. Any interpreted BASIC program on any computer is completely relocatable, it's constantly being shifted up and down in memory as you add or delete lines to your program.

It took another two weeks of solving more mysteries like "The Riddle of the Crashing ORG Statement" before I was actually ready to get a program up and running on the 520ST...
   I had never programmed in C before I sat down at the ST. And I was happy to discover it's possible to write programs in C that look very much like BASIC. To demonstrate this, I'll explain how I wrote a program that does the same thing in C on a 520ST and in BASIC on any 8-bit Atari computer.
   A simple program that I've used many times creates an impressive graphic display. It plots a sine wave from left to right and a cosine wave from right to left. Then each time it plots a pair of sine and cosine dots, it draws a line between them. The result is a pattern of lines that cascades differently across the screen each time.

It's safe to assume that more Antic readers can program in BASIC than in C. So let's get started by examining the BASIC program for 8-bit Ataris line by line.
   Line 100 opens a channel to the keyboard and line 110 sets the X, Y screen limits of Graphics Mode 8.
   Line 120 creates an endless loop. If you program a loop in BASIC with a STEP size of zero, that loop will never end. Since we have a beginning value of zero and an exit value of one, the loop will never reach one until we reset LOOP to a value higher than one. This is as close as we can get to a REPEAT... UNTIL construct in Atari BASIC.
   Lines 130-140 set the graphics mode and set the background and border colors to black.
   Lines 150-160 select a random number between 10 and 80 for the AMPLITUDE (height) of the wave.
   Lines 170-180 select random numbers between 5 and 75 for the PERIOD of the wave. The period of a sine or cosine function determines how many times the value returned from sine or cosine will cycle within a given space. The smaller the number, the more "hills and valleys."
   Line 190 places a random value between 1 and 6 into the variable SIZE. Line 200 uses SIZE as a STEP value in a FOR/NEXT loop which determines the number of X points to be plotted along the X axis.
   Line 210 figures the first Y axis point. Look at it as BASIC would, beginning from the innermost set of parentheses. XPOINT and SINE-PERIOD might typically hold values of 110 and 30 which result in 3.66 when divided. BASIC will then calculate the SIN of the result, which will yield -0.5012.
   This is then multiplied by SINE-AMPLITUDE, (typically around 50) giving an answer of -25.06. Since sine and cosine values may range below zero, and BASIC cannot PLOT negative values, we add half the screen height (YRES/2) in order to shift the dot about halfway down the screen.
   Line 220 performs the same action as 210 for the cosine value.
   Line 230 PLOTs the first pair of points, using XPOINT and SINEY, and DRAWs a line TO the right side of the screen minus XPOINT and COSINEY.
   Line 240 checks to see if a key has been pressed while the computer was figuring and drawing the line. If so, it cleanly finishes the loop by setting the XPOINT counter to its highest expected value, which line 250 awaits to finish its drawing loop.
   Line 250 completes the logic of the drawing loop.
   Line 260 places the value of any key pressed during the loop into KEYPRESS. Line 270 then checks to see if the character pressed was an X. If so, the value for the LOOP counter is set greater than its exit value and we the leave loop-and the program.

Color Cascade screen

Now that we've gone through the BASIC program, let's take a look at how it works in the C listing, step by step. If you are unfamiliar with C, you should first read our sidebar-C at a Glance.
   The first two lines of the C listing are comment lines bracketed between / * and * /. The next five lines cause the C compiler to #include files containing previously typed defihitions that may be used throughout the program. You may use or ignore these definitions as you see fit.
   The whole next block of code- down to, but not including main( )- is our declaration of the variables and arrays to be used by the program. The first two lines are required by GEM and provide a way to send GEM control and input parameters, while GEM sends back parameters as answers or limitations.
   The rest of the int's are 16-bit variables which we chose for the program. There are also two doubles because these variables will be required to hold values greater than 16 bits.
   extern double means that these are routines already saved on another disk file which we will link in our program during compilation. Think of these routines as pre-written functions.
   Since our program is small, it will all be contained within the main() function. All functions called within main( ) will be provided by either the C library, or whichever files are included or linked at compilation time. Most of the functions will be GEM calls.

Now that we've taken care of all the declarations, let's look at our main( ) program, step by step.
   The first thing you see is a left curly bracket (brace). This means "begin." At the bottom of the program, you will find the right brace which means "end." But within the program are more braces containing the beginning and ending of logical routines
   Our first actual program statement is appl_init( );. We can see that it's a complete statement since it ends with a semicolon. appl_init( ) is a routine that prepares GEM to receive information from our application.
   Following this is handle = graf_ handle(&dummy, &dummy, &dummy, &dummy);. Since GEM can have more than one screen window open at any time, we need a way to keep track of which window we want.
   When we make this call, GEM assigns a number to the new window and stores it in the variable we have chosen to call "handle."
   GEM returns additional information from the graf_handle call- such as the X,Y co-ordinate of the upper left corner of our window. Our program doesn't use this information, but we need to provide parameters (&dunmy) for GEM to store the data.

Now we get to a statement which is very similar to a BASIC FOR/NEXT loop. The elements are: FOR (entry condition of loop; condition to be satisfied for the loop to continue; STEP value for loop). In BASIC this would be: FOR I=0 TO 9 STEP 1: NEXT I.
   In C the loop says: for (i starts at zero; continue as long as i is less than 10; use i, then increment it). The last part could also have been written as i=i+1, or, more cryptically, i+ =1.
   The instruction executed within the loop is contained between the braces. This loop fills an array called 1_intin with information such as line style, color, and character size. This data is needed by GEM prior to opening the graphics window.
   The next statement is v_opnvwk (1_intin, &handle, 1_out); similar to a GRAPHICS call from BASIC. 1_intin is the list of parameters passed to GEM that we prepared above. &handle means: "give the address of the handle to GEM", and 1_out is an array that GEM returns describing things like screen size and number of colors. We can later access these values if and when we need them.
   For example, right below we use three of those values. xres is how wide the screen is, yres is how high the screen is and max_color is how many colors we can work with on the device opened. By using these variables, instead of constants, we can be assured our program will work in all video resolutions.
   Now, we encounter a FOR loop which directly corresponds to the FOR loop in the BASIC program that defines our "endless" loop. This line reads: Loop starts at zero. Continue as long as loop is less than one. Each loop add nothing to Loop.
   The next DO WHILE construct will choose a color. It reads: DO choose a random number called COLOR between 0 and 15 WHILE COLOR is less than zero OR (the two vertical lines mean OR) COLOR is greater than the maximum number of colors we can show on the screen.
   The next line vsl_color (handle, color);, corresponds directly to the COLOR statement in the BASIC program. It selects which color the line will be drawn with next.
   The next line selects a random number between one and four for the STEP value in our drawing loop.
   The next four DO WHILE constructs will select a random number for the amplitude and period of our sine and cosine values in the drawing loop.

Now we enter the drawing loop itself, which uses the variable iter as a counter across the screen.
   We indent again to show we are in another loop.
   Next we set xpoint, a double precision variable, equal to the value of iter so we can perform floating point math on it.
   The next two pairs of lines will figure the values needed for our two line endpoints. The GEM call that draws a line is called v_pline( ), but before we call it we need to figure in advance which X,Y points the routine will draw to. Then we place them as elements in an array variable which will become one of the parameters in the GEM call. We could specify more than just one pair of points if we needed to.

We now come to the nucleus of the program: vpline( ). This call reads: "GEM, draw a polyline inside window 'handle'. The line has two points and the X, Y coordinates for the line are in an array called 'ptsin'."
   v_pline( ) is very much like the BASIC USR calls which are in Antic's GUP program (June, 1985). You establish your parameters and variables, then place them in the parentheses and make the call. GEM does the rest.
   The matching brace which ends our drawing loop FOR construct acts the same as NEXT in BASIC

We now come to a DO WHILE construct that creates an endless loop. The GEM call vq_key_s( ) will cause GEM to put the value of Shift/ Alternate/Control keys in a variable called key_state.
   It will continue to do this as long as key_state is equal to zero, which means no keys are pressed. (The == means "test for equality" and is different from a single , which means "is assigned the value of.")
   The IF statement causes the loop to exit by comparing the key_state value to eight-the value of the Alternate key. When the Alternate key is pressed, key-state is set to eight and the value for our "endless" loop counter is incremented, causing the exit of the loop.
   If the alternate was pressed, we fall down to the v_clsvwk(handle) call, which will free the space GEM set aside for our workstation.
   Then we come to the appl_exit( ); call, in which we "un-hook" our application from GEM, and free the memory used for other applications.
   The last line is the brace that ends our main() function.
   We hope this detailed take-apart gives you some idea of how GEM is implemented in the Atari ST Many of you have never used C, so you may have to struggle a bit. Again, take a look at GUP in our June, 1985 issue. GUP is very similar in concept to the GEM calls. The main difference is that GEM uses the elements within arrays and the arrays utilized as parameter elements in the calls.

Listing 1  SINEWAVE.BAS Download

Listing 2  Color Sinewave Program (GEM) (not available)

C is a compiled language, like assembly language. This means the original program is written on a text editor and saved in a file called the "source" code. This source code is compiled (translated) into machine or "object" code.
   C source code contains no line numbers. The compiler uses spaces as delimiters between the recognizable symbols. Therefore it ignores spaces and carriage returns. For this reason, you can write C source code in any format you please. However over the years certain standards in C formatting have developed.
   By custom. C code is written in lower-case letters, although it usually doesn't matter to the compiler. Indentation is an important element in C readability. Nested loops, for example, are indented.

Since there are no line numbers the compiler recognizes the semicolon (;) to separate logical lines or statements. Similarly, there are structures-such as the BASIC FOR/ NEXT loop, or the ACTION! DO...OD structure-which require a delimiter that does not even appear on the Atari 8-bit keyboard. This is the curly bracket "{". Left curly bracket means "begin" and right curly bracket, "}" means "end."

In Atari BASIC all strings or array variables must be DlMensioned so that BASIC knows how much room in memory to reserve for them. ln C, all variables must be "declared."
   This is necessary because C variables can take up different amounts of memory, depending on their data type. Declared variables can be a ''char'' (8 bits), ''int'' (16 bits), or "double" (32 bits).
   Let's take a quick look at the overall structure of a C program, and then we'll list some books which can really give c you the details.
   C programs are made up of a group of subroutines called "functions". Functions may be written by the user, provided by the C compiler, or provided by other files called "libraries." These library files are merged with the code during compilation.
   BASIC programmers may think of functions as USR calls. Parameters may or may not be passed to them, and values may or may not be expected in return.
   Each function title will contain the name of the function, followed by a pair of parentheses which contain any required parameters. If a value is to be returned by a function, the word ''return'' followed by parentheses must appear at the end of the function.

Every C program must have one function called ''main'', which calls the others. A small program may contain only the main function. To follow a C listing, first look within the main function, which will act as a "table of contents'' of the other functions.
   Since C functions may come from the language, or the user, or the library files, it becomes a matter of experience to differentiate between those function titles reserved by the language and libraries, and those created by the programmer. In the specific case of the Atari ST GEM libraries, any function beginning with the letter ''v'' will be part of a GEM VDI call.


by Brian W. Kernighan and
Dennis M. Ritchie
Prentice-Hall Software Series
Englewood Cliffs, NJ 07632
228 pages, paperbound

by Warren A. Stewart
TAB Books, Inc.
Blue Ridge Summit, PA 17214
270 pages, paperbound

by Leon A. Wortman and
Thomas 0. Sidebottom
Robert J. Brady Co.
Bowie, MD 20715
274 pages, paperbound

by Bruce H. Hunter
2344 Sixth Street
Berkeley, CA 94710
320 pages, paperbound

by Thomas Plum
Prentice-Hall, Inc.
Englewood Cliffs, NJ 07632
230 pages, hardcover